EBOOK | |
You probably already know that developing your apps using a microservices approach makes them more flexible, more stable, and faster. This eBook provides a useful set of resources to get started in your transition to microservices.
| |
EBOOK | |
You probably already know that developing your apps using a microservices approach makes them more flexible, more stable, and faster. This eBook provides a useful set of resources to get started in your transition to microservices.
| |
|
|
A medida que se inician las instancias de servicio, registrarán su ubicación física, ruta y puerto a los que se puede acceder con una o más instancias de detección de servicios. Si bien cada instancia de un servicio tendrá una dirección IP y un puerto únicos, cada instancia de servicio que surja se registrará con la misma ID de servicio. Un ID de servicio no es más que una clave que identifica de forma única a un grupo de las mismas instancias de servicio.
Por lo general, un servicio solo se registrará con una instancia de servicio de detección de servicios. La mayoría de las implementaciones de detección de servicios utilizan un modelo de propagación de datos de igual a igual en el que los datos de cada instancia de servicio se comunican a todos los demás nodos del clúster.
Dependiendo de la implementación del descubrimiento de servicios, el mecanismo de propagación podría usar una lista codificada de servicios para propagar o usar un protocolo de multidifusión. Como el protocolo "gossip" o "infection-style" para permitir que otros nodos "descubran" cambios en el clúster.
Finalmente, el servicio de detección de servicios empujará o sacará de su estado cada instancia de servicio. Cualquier servicio que no devuelva una buena verificación de estado se eliminará del conjunto de instancias de servicio disponibles.
Una vez que un servicio se ha registrado en un servicio de descubrimiento de servicios, está listo para ser utilizado por una aplicación o servicio que necesita usar sus capacidades. Existen diferentes modelos para que un cliente “descubra” un servicio. Un cliente puede confiar únicamente en el motor de descubrimiento de servicios para resolver las ubicaciones de los servicios cada vez que se llama a un servicio. Con este enfoque, el motor de detección de servicios se invocará cada vez que se realice una llamada a una instancia de microservicio registrada. Desafortunadamente, este enfoque es frágil porque el cliente del servicio depende completamente del motor de detección de servicios que se está ejecutando para encontrar e invocar un servicio.
Un enfoque más sólido es utilizar lo que se denomina balanceo de carga del lado del cliente. En este modelo, cuando un actor consumidor necesita invocar un servicio, se pondrá en contacto con el servicio de detección de servicios para todas las instancias de un servicio. El consumidor está solicitando y luego almacenar en caché los datos localmente en la máquina del consumidor del servicio.
Cada vez que un cliente desee llamar al servicio, el consumidor del servicio buscará la información de ubicación del servicio en la memoria caché.
El almacenamiento en caché utilizará un algoritmo de balanceo de carga simple como el algoritmo de balanceo de carga "round-robin" para garantizar que las llamadas de servicio se distribuyan entre múltiples instancias de servicio.
Luego, el cliente se comunicará periódicamente con el servicio de descubrimiento de servicios y actualizará su caché de instancias de servicio. El caché del cliente finalmente es consistente, pero siempre existe el riesgo de que, entre el momento en que el cliente se pone en contacto con la instancia de detección de servicios para una actualización y se realicen las llamadas, las llamadas se dirijan a una instancia de servicio que no está en buen estado.
Si, durante el transcurso de la llamada a un servicio, la llamada de servicio falla, la memoria caché de detección de servicios local se invalida y el cliente de detección de servicios intentará actualizar sus entradas desde el agente de detección de servicios.
Siempre que tenga una aplicación que llama a recursos repartidos en varios servidores, necesita ubicar la ubicación física de esos recursos. En el mundo normal (no clud), esta resolución de ubicación de servicio a menudo se resolvía y se resuelve mediante una combinación de DNS y un balanceador de carga.
Una aplicación si necesita invocar un servicio intenta invocar el servicio utilizando un nombre genérico junto con una ruta que representa de forma única el servicio que la aplicación intentaba invocar. El nombre DNS se resolvería en un balanceador de carga.
El balanceador de carga, al recibir la solicitud del consumidor del servicio, ubica la entrada de la dirección física en una tabla de enrutamiento según la ruta a la que el usuario intentaba acceder. Esta entrada de la tabla de enrutamiento contiene una lista de uno o más servidores que alojan el servicio. Luego, el balanceador de carga elige uno de los servidores de la lista y reenvía la solicitud a ese servidor.
Cada instancia de un servicio se implementa en uno o más servidores de aplicaciones. La cantidad de estos servidores de aplicaciones a menudo era estática (por ejemplo, la cantidad de servidores de aplicaciones que alojaban un servicio no aumentaba ni disminuía) y persistente (por ejemplo, si fallaba un servidor que ejecutaba un servidor de aplicaciones, se restauraría al estado actual). mismo estado que tenía en el momento del bloqueo, y tendría la misma IP y configuración que tenía anteriormente).
Para lograr una forma de alta disponibilidad, un balanceador de carga secundario está inactivo y hace ping al balanceador de carga principal para ver si está activo. Si no está activo, el balanceador de carga secundario se activa, asumiendo la dirección IP del balanceador de carga principal y comenzando a atender las solicitudes.
Si bien este tipo de modelo funciona bien con aplicaciones que se ejecutan dentro de las cuatro paredes de un centro de datos corporativo y con una cantidad relativamente pequeña de servicios que se ejecutan en un grupo de servidores estáticos, no funciona bien para aplicaciones de microservicio basadas en la nube. Las razones para esto incluyen :
Estas cuatro razones no son una acusación general de los balanceadores de carga. Funcionan bien en un entorno corporativo donde el tamaño y la escala de la mayoría de las aplicaciones pueden manejarse a través de una infraestructura de red centralizada. Además, los balanceadores de carga aún tienen un papel que desempeñar en términos de centralizar la terminación SSL y administrar la seguridad del puerto del servicio. Un balanceador de carga puede bloquear el acceso al puerto de entrada (entrada) y salida (salida) a todos los servidores que se encuentran detrás de él. Este concepto de acceso mínimo a la red suele ser un componente crítico cuando se trata de cumplir con los requisitos de certificación estándar de la industria, como el cumplimiento de PCI (industria de tarjetas de pago).
Sin embargo, en la nube, donde tiene que lidiar con cantidades masivas de transacciones y redundancia, una pieza centralizada de infraestructura de red no funciona tan bien en última instancia porque no se escala de manera efectiva y no es rentable.
Ofrece al equipo de aplicaciones la capacidad de escalar horizontalmente rápidamente la cantidad de instancias de servicio que se ejecutan en un entorno. Los consumidores del servicio se abstraen de la ubicación física del servicio a través del descubrimiento del servicio. Debido a que los consumidores del servicio no conocen la ubicación física de las instancias de servicio reales, se pueden agregar o eliminar nuevas instancias de servicio del grupo de servicios disponibles.
Esta capacidad de escalar rápidamente los servicios sin interrumpir a los consumidores del servicio es un concepto extremadamente poderoso, porque hace que un equipo de desarrollo acostumbrado a crear aplicaciones monolíticas deje de pensar en escalar solo en términos de agregar mayores , mejor hardware (escalado vertical) al enfoque más potente de escalado mediante la adición de más servidores (escalado horizontal).
Un enfoque monolítico suele llevar a los equipos de desarrollo por el camino de sobrecomprar sus necesidades de capacidad. Los aumentos de capacidad vienen en grupos y picos y rara vez son un camino suave y constante. Los microservicios nos permiten escalar hacia arriba o hacia abajo nuevas instancias de servicio. El descubrimiento de servicios ayuda a abstraer que estas implementaciones ocurren lejos del consumidor del servicio.
El segundo beneficio del descubrimiento de servicios es que ayuda a aumentar la resistencia de las aplicaciones. Cuando una instancia de microservicio no está en buen estado o no está disponible, la mayoría de los motores de detección de servicios eliminarán esa instancia de su lista interna de servicios disponibles.
El daño causado por un servicio inactivo se minimizará porque el motor de descubrimiento de servicios enrutará los servicios alrededor del servicio no disponible.
Cuando el cliente se inicia por primera vez, pasará el perfil de Spring y el end point para comunicarse con el servicio de configuración de Spring Cloud. El valor del perfil Spring se asigna al entorno de las propiedades que se recuperan para el servicio Spring. El servicio Spring Cloud Config luego usará el repositorio de configuración de back-end configurado (sistema de archivos, Git, Consul, Eureka) para recuperar la información de configuración específica para el valor del perfil de Spring pasado en el URI. Spring Boot luego inyectará estos valores en las partes apropiadas de la aplicación.
Lo primero que debe hacer es agregar un par de entradas más al archivo Maven :
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-client</artifactId>
</dependency>
Vamos a hacer una nueva aplicación string boot como servidor de configuraciones. Yo voy a utilizar spring initializr pero podemos agregar estas dependencias en un nuevo proyecto o uno existente.
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
</dependencies>
O con gradle sería así :
implementation 'org.springframework.cloud:spring-cloud-starter-config'
implementation 'org.springframework.cloud:spring-cloud-config-server'
La primera dependencia es la dependencia spring-cloud-starter-config que utilizan todos los proyectos de Spring Cloud. La segunda dependencia es el proyecto de inicio spring-cloud-config-server. Esto contiene las bibliotecas centrales para spring-cloud-config-server.
Necesitamos configurar un archivo más para que el servidor de configuración central esté en funcionamiento. Este archivo es el archivo application.yml y lo debemos generar en el directorio src/main/resources. El archivo application.yml le dirá a su servicio de configuración de Spring Cloud qué puerto escuchar y dónde ubicar el back-end que entregará los datos de configuración. En mi caso el appication.yml es así :
server:
port: 8888
spring:
profiles:
active: native
cloud:
config:
server:
native:
searchLocations: file:///{projectPath}/resources
Ojo que {projectPath} es donde esta el proyecto, la dirección por ejemplo el mio esta en /home/emanuel/misProyectos/application.
En la configuración de Spring Cloud, todo funciona con una jerarquía. La configuración de la aplicación está representada por el nombre de la aplicación y luego un archivo de propiedades para cada entorno para el que se desea tener información de configuración. En cada uno de estos entornos, configurará dos propiedades de configuración.
Vamos a suponer que tenemos 3 entornos uno de dev, otro de uat y otro de prod. Vamos a crear directorios para cada uno de los entornos en src/main/resources una carpeta por cada entorno.
El mapeo de las carpetas y los archivos va a ser de la siguiente manera :
/{application}/{profile}[/{label}]
/{application}-{profile}.yml
/{label}/{application}-{profile}.yml
/{application}-{profile}.properties
/{label}/{application}-{profile}.properties
Noten que el label es opcional. Por lo tanto si hacemos archivos application-dev.properties o application-uat.properties esto debería andar.
Y por ultimo le decimos a spring que vamos a utilizar spring config con esta anotación :
@SpringBootApplication
@EnableConfigServer
public class SettingsApplication {
Ahora levantamos el servidor y si necesitamos las configuraciones de uat deberíamos hacer :
http://localhots:8888/application/uat
Tendremos este resultado :
{"name":"demo","profiles":["uat"],"label":null,"version":null,"state":null,"propertySources":[{"name":"file:/home/emanuel/Projects/spring-cloud/settings/src/main/resources/demo-uat.yml","source":{"env":"dev"}},{"name":"file:/home/emanuel/Projects/spring-cloud/settings/src/main/resources/application.yml","source":{"server.port":8888,"spring.profiles.active":"native","spring.cloud.config.server.native.searchLocations":"file:///home/emanuel/Projects/spring-cloud/settings/src/main/resources"}}]}
Y listo, nos queda ver como podemos consumir estos settings. (pero eso es para otro post)
Dejo link: https://cloud.spring.io/spring-cloud-config