Hoy vamos a ver como utilizar la funcionalidad de Service Discovery en un proyecto de Apache Camel, pero esta vez utilizando Consul de HashiCorp. Ya hemos visto esta misma funcionalidad pero con Eureka Netflix, aqui,. Por lo que este nuevo ejemplo no se diferenciará mucho.
Pero antes, averiguemos un poco más de Consul. A igual que Eureka es una herramienta que nos permite el registro de servicios de forma centralizada, permitiendo el descubrimiento de los mismos a otros clientes sin necesidad de conocer su dirección real, solo con un identificador. Pero además puede servirnos para almacenamiento de información o de la configuración a utilizar por los distintos clientes. Pero sobre este último apartado no veremos nada concreto en este ejemplo.
Lo primero que vamos a hacer es levantar Consul. Para el caso de las pruebas podemos levantar una única instancia de Consul a través de un simple comando de docker. Pero nosotros lo haremos un poco más complejo, ya que Consul también puede ser levantado como un cluster de servidores, donde uno de ellos es el principal. Para llevar a cabo esta aproximación, crearemos un docker compose que nos permita levantar varias instancias de Consul y dejarlas activas para el ejemplo. Aquí abajo tenemos el docker compose y si accedemos a la URL http://localhost:8500 podremos acceder a su interfaz gráfica.
#https://github.com/consul/consul/blob/master/docker-compose.yml version: '3' x-consul-container: &consul-container image: consul:latest networks: - consul-demo x-consul-server: &consul-server <<: *consul-container command: "agent -server -retry-join consul-server-bootstrap -client 0.0.0.0" services: consul-server-1: hostname: consult-server-1 container_name: consult-server-1 <<: *consul-server consul-server-bootstrap: hostname: consul-server-bootstrap container_name: consul-server-bootstrap <<: *consul-agent ports: - "8400:8400" - "8500:8500" - "8600:8600" - "8600:8600/udp" command: "agent -server -bootstrap-expect 2 -ui -client 0.0.0.0" networks: consul-demo:
El siguiente paso será crear un micro servicio con Apache Camel. Este micro servicio será muy básico y se conectará como cliente a Consul y registrará las distintas rutas en el. De esta forma y a través de un identificador, será consumibles por otros clientes del mismo servidor.
Para ello, por un lado añadimos las siguientes dependencias, además de las normales para un micro servicio:
- spring-boot-starter-actuator: Nos permite exponer rutas para la verificación del estado y los datos de la aplicación.
- camel-consul-starter: Nos permite preconfigurar Consul en nuestra aplicación.
- management.endpoints.web.exposure.include: Nos permite indicar rutas de monitorización a gestionar por Spring Actuator.
- camel.cloud.consul.enabled: Habilitar el uso de Consul.
- camel.cloud.consul.service-host: Indicar el servidor donde se encuentra ubicado Consul. Esta propiedad será la encargada de setear el tag service address al servicio en Consul.
- camel.cloud.consul.url: Para indicar la ruta completa donde se encuentra desplegado Consul.
@Component public class BookMockRouter extends RouteBuilder { private static Map<Integer, Book> books = new HashMap<>(); static { books.put(1, new Book(1, "Dune", "Frank Herbert")); books.put(2, new Book(2, "The stars my destination", "Alfred Bester")); books.put(3, new Book(3, "Ender's game", "Orson S. Card")); } @Override public void configure() throws Exception { ServiceRegistrationRoutePolicy policy = new ServiceRegistrationRoutePolicy(); rest().get("book").produces(MediaType.APPLICATION_JSON_VALUE).route()
.routeId("mockClientGetAll") .routeProperty(ServiceDefinition.SERVICE_META_NAME, "bookGetAll") .routeProperty(ServiceDefinition.SERVICE_META_PORT, "9092") .routeProperty(ServiceDefinition.SERVICE_META_PATH, "api/book")
.routePolicy(policy) .bean(BookMockRouter.class, "getAll(})").marshal().json(); rest().get("book/{id}").produces(MediaType.APPLICATION_JSON_VALUE)
.route().routeId("mockGetById")
.routeProperty(ServiceDefinition.SERVICE_META_NAME, "bookGetById") .routeProperty(ServiceDefinition.SERVICE_META_PORT, "9092") .routeProperty(ServiceDefinition.SERVICE_META_PATH, "api/book/")
.routePolicy(policy) .bean(BookMockRouter.class, "getById(${header.id})").marshal().json(); } public Collection<Book> getAll() { return books.values(); } public Book getById(final Integer id) { return books.get(id); } }
Con este simple servicio podremos comprobar dos cosas. Primero que si invocamos la ruta http://localhost:9092/api/book, veremos el listado de libros asociados a la primera de las rutas. Y segundo, que si accedemos de nuevo a Consul, podremos ver como tenemos dos servicios más registrados. Cliqueando sobre los mismos podremos ver los detalles que hemos indicado en el código fuente.
Para terminar el ejemplo y ver que funciona no solo la parte del registro de aplicaciones de forma dinámica en Consul. Sino que también funciona el descubrimiento de estos servicios, crearemos a continuación otro micro servicio con Apache Camel que hará uso del método serviceCall para invocar a Consul.
Este nuevo servicio será incluso más sencillo, puesto que solo necesitará las dependencias para usar Consul en una aplicación de Apache Camel. Y en cuanto a propiedades, solo necesitará dos específicas:
- camel.cloud.consul.enabled: Habilitar el uso de Consul.
- camel.cloud.consul.service-discovery.url: Indicar la ruta donde se encuentra ubicado Consul.
@Component public class BookServiceRouter extends RouteBuilder { @Override public void configure() throws Exception { rest("/serviceCall").get().produces(MediaType.APPLICATION_JSON_VALUE)
.route().removeHeader(Exchange.HTTP_URI).serviceCall("bookGetAll")
.convertBodyTo(String.class).log("Body: ${body}").end(); rest("/serviceCall/{id}").get().produces(MediaType.APPLICATION_JSON_VALUE)
.route().removeHeader(Exchange.HTTP_PATH)
.setHeader(Exchange.HTTP_PATH, simple("${header.id}")) .removeHeader(Exchange.HTTP_URI).serviceCall("bookGetById")
.convertBodyTo(String.class).log("Body: ${body}").end(); } }
No hay comentarios:
Publicar un comentario