Microservicios. Una aproximación básica.
Martin Fowler propone en su artículo “Microservices” una de las definiciones que más me gusta para describir qué son los microservicios:
La arquitectura basada en microservicios es una nueva manera de desarrollar aplicaciones como si fueran un conjunto de pequeños servicios, cada uno de ellos corriendo su propio proceso (servidor) y comunicándose entre si utilizando mecanismos de comunicación ligeros, normalmente protocolo HTTP.
Lo dice él y lo comparto yo, los microservicios son una nueva manera de diseñar aplicaciones que obliga a tener en cuenta el hecho de que cada funcionalidad es un servicio, cada uno con sus propios recursos, abandonando el consabido enfoque monolítico tradicional donde todas las funcionalidades forman parte de una único servicio.
Esta entrada abre una sucesión de artículos donde de manera básica quiero aproximarme al mundo de los microservicios utilizando diferentes aproximaciones; Spring Cloud, Play y vert.x.
Este primer artículo recorre el enfoque desde el punto de vista de Spring con Spring Cloud. Mi intención es implementar unos microservicios utilizando el ecosistema propuesto por Spring framework, a saber; Springfox, la implementación de Spring de la especificación Swagger para documentar la API REST, y Spring Cloud Netflix para ofrecer el microservicio y ponerlo a disposición de terceros a través del Service Registry de Netflix, Eureka.
El ejemplo.
El ejemplo elegido es una funcionalidad básica pero suficiente para permitir probar el desarrollo de microservicios a través de las soluciones elegidas, en esta entrada Spring Cloud.
La aplicación va a dar servicios a operaciones aritméticas ofreciendo dos microservicios, uno que realiza suma de dos operandos y el otro que realiza multiplicaciones de dos operandos.
De manera común a cada una de las pruebas voy a utilizar Apache Maven para manejar el ciclo de vida de cada componente que cree.
Spring Cloud y Spring Boot, dos facilitadores para el desarrollo.
Spring boot y Spring cloud son dos de las nuevas herramientas que Spring propone para facilitar el desarrollo de aplicaciones distribuidas basadas en microservicios.
Spring Boot es uno de los nuevos inventos de la familia Spring cuya pretensión es facilitar la vida a los desarrolladores simplificando todo el trabajo de configuración del propio framework. Para ello, Spring boot autoconfigura los componentes, automatizando la gestión de dependencias y el despliegue. Estas autoconfiguraciones son perfectas para los casos más comunes, pero en caso de necesitar algo más especial, las autoconfiguraciones pueden ser personalizadas utilizando anotaciones y/o ficheros de configuración.
Spring Cloud es otro de esos geniales inventos de la familia Spring que propone un ecosistema de herraminetas que nos ayudan a desplegar nuestros servicios en nubes. Soporta Cloud Foundry y Heroku de caja, así como otras nubes a través de conectores. Spring Cloud permitirá a las aplicaciones descubrir y compartir información/configuración de otras aplicaciones, y de sí misma, en tiempo de ejecución.
Servicios REST para la calculadora.
El primer paso para probar la tecnología de Spring es generar el servicio REST que va a proporcionar las operaciones aritméticas de suma y multiplicación de la calculadora.
Gracias a Spring Boot el desarrollo y pruebas de este API se hace muy rápidamente y con apenas esfuerzo.
El primer paso es crear un proyecto Java para contener el API REST. El proyecto se llama CalculadoraAritmeticaRestAPI.
4.0.0 com.tecnicomio.microservices.springfrwk CalculadoraAritmeticaRestAPI 1.0-SNAPSHOT org.springframework.boot spring-boot-starter 1.5.10.RELEASE org.springframework.boot spring-boot-starter-web 1.5.10.RELEASE
Es importante fijarse que las únicas dependencias que he añadido han sido las referentes con spring boot. No he incluido ninguna dependencia referente al API REST. Ya se encargará Spring Boot de encontrar las dependencias necesarias para compilar y ejecutar correctamente el proyecto. Lo que si se ha añadido es el starter web para que Spring Boot tenga las dependencias necesarias para manejar aplicaciones web.
El siguiente paso es crear el servicio REST que proporciona las operaciones que se necesitan para la calculadora aritmética; sumar y multiplicar.
package com.tecnicomio.microservicios.spring;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/aritmetica")
public class CalculadoraAritmeticaRESTController {
public CalculadoraAritmeticaRESTController() {
}
@RequestMapping(
value = "/sumar",
method = RequestMethod.GET,
params = {"operando1", "operando2"}
)
public Integer sumar(@RequestParam("operando1") Integer operando1,
@RequestParam("operando2") Integer operando2) {
return operando1 + operando2;
}
@RequestMapping(
value = "/multiplicar",
method = RequestMethod.GET,
params = {"operando1", "operando2"}
)
public Integer multiplicar(@RequestParam("operando1") Integer operando1,
@RequestParam("operando2") Integer operando2) {
return operando1 * operando2;
}
}
No es el objetivo de esta entrada explicar cómo desarrollar servicios REST con Spring así que sólo comentaré que la principal anotación para convertir una clase Java en un API REST es @RestController. La otras anotaciones, leanse @RequestMapping y @RequestParam, sirven para configurar las funcionalidades que se exponen en el API. Ni que decir tiene que existen muchas más anotaciones y configuraciones, así que os dejo un link al tutorial de servicios REST de spring.io donde se explican bastante bien los conceptos:
Building a RESTful Web Service
Y finalmente, para que Spring Boot obre su magia se implementa una clase cuyo principal cometido es decirle a Spring que nos encontramos ante una aplicación web que contiene un servicio REST que debe publicarse para poder ser invocado.
package com.tecnicomio.microservicios.spring;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication(scanBasePackages = {"com.tecnicomio.microservicios.spring"})
public class CalculadoraAritmeticaServer {
public static void main(String[] args) {
SpringApplication.run(CalculadoraAritmeticaServer.class, args);
}
}
Podría haber incluido estas líneas directamente en el controller REST, pero he preferido por orden y limpieza crear esta mini clase como launcher.
Lo más curioso de Spring Boot es la inteligencia que incorpora, ya que al ejecutar estas 11 escasas líneas de código, Spring Boot sabe que se encuentra ante una aplicación web, con un servicio REST y arranca un Tomcat embebido para que se pueda acceder y ejecutar el servicio aritmético de calculadora.
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v1.5.10.RELEASE)
2018-03-15 12:37:48.853 INFO 121776 --- [ main] c.t.m.s.CalculadoraAritmeticaServer : Starting CalculadoraAritmeticaServer on devstation.localdomain with PID 121776 (/srv/java/src/pruebassimples/microservices/springfrwk/SumaAritmetica/target/classes started by developer in /srv/java/src/pruebassimples/microservices/springfrwk/SumaAritmetica)
2018-03-15 12:37:48.859 INFO 121776 --- [ main] c.t.m.s.CalculadoraAritmeticaServer : No active profile set, falling back to default profiles: default
2018-03-15 12:37:48.975 INFO 121776 --- [ main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@782859e: startup date [Thu Mar 15 12:37:48 CET 2018]; root of context hierarchy
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by org.springframework.cglib.core.ReflectUtils$1 (file:/home/developer/.m2/repository/org/springframework/spring-core/4.3.14.RELEASE/spring-core-4.3.14.RELEASE.jar) to method java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int,java.security.ProtectionDomain)
WARNING: Please consider reporting this to the maintainers of org.springframework.cglib.core.ReflectUtils$1
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
2018-03-15 12:37:50.549 INFO 121776 --- [ main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 8080 (http)
2018-03-15 12:37:50.563 INFO 121776 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2018-03-15 12:37:50.564 INFO 121776 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/8.5.27
2018-03-15 12:37:50.646 INFO 121776 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2018-03-15 12:37:50.646 INFO 121776 --- [ost-startStop-1] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 1685 ms
2018-03-15 12:37:50.734 INFO 121776 --- [ost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean : Mapping servlet: 'dispatcherServlet' to [/]
2018-03-15 12:37:50.737 INFO 121776 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'characterEncodingFilter' to: [/*]
2018-03-15 12:37:50.737 INFO 121776 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'hiddenHttpMethodFilter' to: [/*]
2018-03-15 12:37:50.737 INFO 121776 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'httpPutFormContentFilter' to: [/*]
2018-03-15 12:37:50.737 INFO 121776 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'requestContextFilter' to: [/*]
2018-03-15 12:37:51.154 INFO 121776 --- [ main] s.w.s.m.m.a.RequestMappingHandlerAdapter : Looking for @ControllerAdvice: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@782859e: startup date [Thu Mar 15 12:37:48 CET 2018]; root of context hierarchy
2018-03-15 12:37:51.218 INFO 121776 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/aritmetica/multiplicar],methods=[GET],params=[operando1 && operando2]}" onto public java.lang.Integer com.tecnicomio.microservicios.spring.CalculadoraAritmeticaRESTController.multiplicar(java.lang.Integer,java.lang.Integer)
2018-03-15 12:37:51.219 INFO 121776 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/aritmetica/sumar],methods=[GET],params=[operando1 && operando2]}" onto public java.lang.Integer com.tecnicomio.microservicios.spring.CalculadoraAritmeticaRESTController.sumar(java.lang.Integer,java.lang.Integer)
2018-03-15 12:37:51.221 INFO 121776 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error]}" onto public org.springframework.http.ResponseEntity org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest)
2018-03-15 12:37:51.221 INFO 121776 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error],produces=[text/html]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)
2018-03-15 12:37:51.244 INFO 121776 --- [ main] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2018-03-15 12:37:51.244 INFO 121776 --- [ main] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2018-03-15 12:37:51.274 INFO 121776 --- [ main] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/**/favicon.ico] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2018-03-15 12:37:51.423 INFO 121776 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Registering beans for JMX exposure on startup
2018-03-15 12:37:51.537 INFO 121776 --- [ main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8080 (http)
2018-03-15 12:37:51.542 INFO 121776 --- [ main] c.t.m.s.CalculadoraAritmeticaServer : Started CalculadoraAritmeticaServer in 13.353 seconds (JVM running for 14.096)
Así que con un pom.xml y dos clases java muy simples tenemos el servicio REST publicado y accesible.

Documentando el API.
Para poder ejecutar los servicios expuestos debemos conocer la URL para invocarlo, los métodos que ofrece, los parámetros con que se llama a cada método y la información con la que se rellena.
Una manera de recibir esta información podría ser, por ejemplo, vía email, pero una mejor manera de recibirlo es tener un portal donde se pueda acceder a un listado de todos los servicios REST publicados y su información de uso. Este portal que concentra la información sobre APIs, es el objeto de la especificación Swagger.
La especificación swagger define un interfaz estándar para las APIs RESTful, que no se casa con ningún lenguaje de programación concreto, qué permite tanto a humanos como a máquinas descubrir y comprender las capacidades del servicio sin necesitad de acceder, ni al código fuente del mismo, ni a su documentación, ni a través de la inspección del comportamiento del servicio a través de la red. Cuando esta interfaz se define correctamente, los posibles consumidores del API pueden entender e interactuar correctamente con el servicio.
Springfox es la implementación de la especificación swagger que propone Spring. Para añadirla en nuestro servicio aritmético tenemos que seguir varios pasos.
El primero, añadir en el pom.xml la dependencia necesaria para utilizar Springfox.
io.springfox springfox-swagger2 2.8.0 io.springfox springfox-swagger-ui 2.8.0
El segundo es crear una clase de configuración de swagger.
package com.tecnicomio.microservicios.spring.com.tecnicomio.microservicios.spring.swagger;
import com.tecnicomio.microservicios.spring.CalculadoraAritmeticaRESTController;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
@Configuration
@EnableSwagger2
@ComponentScan(basePackageClasses = {CalculadoraAritmeticaRESTController.class})
public class SwaggerConfiguration {
@Bean
public Docket calculadoraAritmeticaApi() {
return new Docket(DocumentationType.SWAGGER_2)
.groupName("api-calculadora-aritmetica")
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.any())
.paths(PathSelectors.regex("/aritmetica.*"))
.build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("Calculadora aritmética API Rest")
.description("API RESTful para la calculadora aritmética.")
.termsOfServiceUrl("http://en.wikipedia.org/wiki/Terms_of_service")
.contact(new Contact("Eduardo González de Viñaspre", "http://tecnicomio.com", "eduardo.gonzalezdevinaspre@gmail.com"))
.license("Apache License Version 2.0")
.licenseUrl("http://www.apache.org/licenses/LICENSE-2.0.html")
.version("2.0")
.build();
}
}
Importante la anotación @EnableSwagger2 que indica que hay que activar swagger. El método calculadoraAritmeticaApi indica el formato de la documentación y su nombre, y el método apiInfo que indica información básica sobre la documentación que nos vamos a encontrar en el portal publicado.
Y finalmente documentar el controlador REST del API así como los POJOs que usemos para definir los parámetros de entrada y de salida de los diferentes métodos. En este caso como no hay POJOs, solo documento el controlador REST.
package com.tecnicomio.microservicios.spring;
import io.swagger.annotations.*;
import org.springframework.web.bind.annotation.*;
import javax.ws.rs.core.MediaType;
@RestController
@RequestMapping("/aritmetica")
@Api(value = "/aritmetica",
description = "Proporciona las operaciones necesarias para implementar una calculadora aritmética",
produces = "text/plain")
public class CalculadoraAritmeticaRESTController {
public CalculadoraAritmeticaRESTController() {
}
@RequestMapping(
value = "/sumar",
method = RequestMethod.GET,
params = {"operando1", "operando2"},
produces = MediaType.TEXT_PLAIN
)
@ApiOperation(value="Suma aritmética", notes = "Realiza la suma de dos operandos")
@ApiResponses( {
@ApiResponse(code = 200, message = "Devuelve el resultado de la suma.")
})
public Integer sumar(@RequestParam(value = "operando1",defaultValue = "0") @ApiParam(value = "operando 1 de la suma", defaultValue = "0", required = true, example = "5") Integer operando1,
@RequestParam(value = "operando2", defaultValue = "0") @ApiParam(value = "operando 2 de la suma", defaultValue = "0", required = true, example = "15") Integer operando2) {
return operando1 + operando2;
}
@RequestMapping(
value = "/multiplicar",
method = RequestMethod.GET,
params = {"operando1", "operando2"}
)
@ApiOperation(value="Multiplicación aritmética", notes = "Realiza la multiplicación de dos operandos")
@ApiResponses( {
@ApiResponse(code = 200, message = "Devuelve el resultado de la multiplicación.")
})
public Integer multiplicar(@RequestParam(value = "operando1", defaultValue = "1") @ApiParam(value = "operando 1 de la multiplicación", defaultValue = "1", required = true, example = "5") Integer operando1,
@RequestParam(value = "operando2", defaultValue = "1") @ApiParam(value = "operando 2 de la multiplicación", defaultValue = "1", required = true, example = "10") Integer operando2) {
return operando1 * operando2;
}
}
Las anotaciones que obran la magia son:
- @Api – Define un contenedor de documentación.
- @ApiOperation – Define la documentación de una operación dentro del servicio.
- @ApiResponses y @ApiResponse – Documenta las respuestas del método del servicio.
- @ApiParam- Documenta los parámetros de los parámetros de los métodos.
Gracias a Spring Boot no se necesita mucho más. Ahora ya se puede acceder a la URL de swagger: http://localhost:8080/swagger-ui.html# y si todo ha salido bien veremos la página que swagger ofrece con la documentación del servicio REST.

Si extendemos una operación, además de ver la documentación, podemos incluso llegar a probarla:

Arrancando una herramienta de Service Discovery: Eureka.
Al final la tecnología de microservicios está formada por servicios simples como el servicio de aritmética que acabamos de publicar, pero que además quedan envueltos por una ecosistema que aporta una serie de ventajas que facilitan el mantenimiento de estos servicios, por ejemplo, el registro y localización de los mismos, el balanceo de carga, la tolerancia a fallos, entre otros.
El registro de los servicios para su posterior localización y uso es importantísimo en cuanto tenemos un proyecto medio-grande entre manos. Basta con imaginar tener 100 microservicios dando servicio a un sitio web para darnos cuenta que tenemos que tener algún tipo de inventario con información sobre ellos. En el ecosistema de los microservicios la pieza que facilita este registro es el Service Discovery.
A día de hoy existen varios Service Discovery, algunos de los más importantes son:
- Zookeeper de Apache Foundation
- Eureka de Netflix
- Consul
El siguiente paso por tanto es registrar el servicio aritmético en un Service Discovery, y para ello voy a utilizar Eureka, el Service Discovery que utiliza Netflix, una de las empresas que sirve más peticiones a lo largo y ancho de internet.
Lo primero que voy a hacer es crear un nuevo proyecto EurekaApplication para contener todo lo relativo a la ejecución de Eureka. El pom.xml del nuevo proyecto es:
4.0.0 com.tecnicomio.microservices.springfrwk EurekaServer 1.0-SNAPSHOT org.springframework.cloud spring-cloud-starter-eureka-server 1.4.3.RELEASE org.springframework.boot spring-boot-starter 1.5.10.RELEASE javax.xml.bind jaxb-api 2.3.0 org.springframework.cloud spring-cloud-starter-parent Brixton.SR7 pom import
¡¡Cuidado!! He tenido que añadir las dependencias de jaxb-api para que el Tomcat que Spring Boot incluye arranque correctamente. Esto es debido a que en la JDK 9 tras implementar los Java Modules, algunas librerías ya no se incluyen como si se hacía en la JDK 6/7/8. Uno de esos paquetes que no se incluye es java.xml.bind que contiene todo el funcionamiento de JAXB.
A continuación añado una clase para arrancar el servidor de Eureka.
package com.tecnicomio.microservicios.spring;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
La anotación aquí es @EnableEurekaServer que le dice a Spring Boot que se quiere arrancar el Service Discovery de Eureka.
Y finalmente, para que configurar brevemente el servidor Eureka, se añade el fichero application.yml al directorio resources del proyecto.
server: port: 8761 eureka: client: registerWithEureka: false fetchRegistry: false
En el fichero de configuración estamos indicando que el servidor de Eureka se arranque en el puerto 8761 (el puerto por defecto de los servidores de Eureka), que el cliente no se registre a si mismo ya que vamos a registrar el servicio aritmético.
Así que finalmente, con estos pasos, ya deberíamos tener el servidor Eureka arrancado.

Con esto hemos conseguido que el servicio se autoregistre en Eureka, que le notifique cuando está disponible, cómo se le puede invocar, los metadatos que se pueden utilizar y mucha más información.
Descubriendo el servicio aritmético en Eureka.
Recapitulando, llegados a este punto hemos creado un servicio REST que ofrece funcionalidad para una calculadora aritmética, y hemos arrancado una instancia de Eureka, una herramienta para el descubrimiento de servicios.
Desafortunadamente, cuando miramos la consola de Eureka todavía no se ve registrado el servicio aritmético. Esto es debido a que hay que indicarle al servicio que implemente el Service Registry pattern de Eureka para convertirle en un posible cliente.
El primer paso es añadir las depedencias de Eureka al proyecto CalculadoraAritmeticaRestAPI:
org.springframework.cloud spring-cloud-starter-eureka-server 1.4.3.RELEASE
El segundo indicarle al servicio aritmético que es un cliente de Eureka. Para ello añadimos la anotación @EnableEurekaClient a la clase servidor.
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@EnableEurekaClient
@RestController
@RequestMapping("/aritmetica")
public class CalculadoraAritmeticaRESTController {
Y por último, configurar el cliente Eureka mediante un fichero application.yml donde indiquemos el nombre del micro-servicio, la URL y otras posibles configuraciones.
spring:
application:
name: calculadora-aritmetica-eureka-client
server:
port: 0
eureka:
client:
serviceUrl:
defaultZone: ${EUREKA_URI:http://localhost:8761/eureka}
instance:
preferIpAddress: true
Hecho esto, se arranca el servicio CalculadoraAritmetica y automáticamente debería registrarse en el servidor Eureka indicado en el fichero YAML de configuración.
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v1.3.8.RELEASE)
2018-03-15 15:25:41.087 INFO 7659 --- [ main] c.t.m.s.CalculadoraAritmeticaServer : No active profile set, falling back to default profiles: default
2018-03-15 15:25:41.105 INFO 7659 --- [ main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@5942ee04: startup date [Thu Mar 15 15:25:41 CET 2018]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext@43b9fd5
2018-03-15 15:25:42.095 WARN 7659 --- [ main] o.s.c.a.ConfigurationClassPostProcessor : Cannot enhance @Configuration bean definition 'refreshScope' since its singleton instance has been created too early. The typical cause is a non-static @Bean method with a BeanDefinitionRegistryPostProcessor return type: Consider declaring such methods as 'static'.
2018-03-15 15:25:42.259 INFO 7659 --- [ main] o.s.cloud.context.scope.GenericScope : BeanFactory id=357c0c59-b5b5-38af-babc-0373b7d67e30
2018-03-15 15:25:42.275 INFO 7659 --- [ main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring
2018-03-15 15:25:42.328 INFO 7659 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration' of type [class org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$defd02e1] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2018-03-15 15:25:42.335 INFO 7659 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.autoconfigure.RefreshEndpointAutoConfiguration' of type [class org.springframework.cloud.autoconfigure.RefreshEndpointAutoConfiguration$$EnhancerBySpringCGLIB$$885c04d7] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2018-03-15 15:25:42.710 INFO 7659 --- [ main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 0 (http)
2018-03-15 15:25:42.728 INFO 7659 --- [ main] o.apache.catalina.core.StandardService : Starting service Tomcat
2018-03-15 15:25:42.729 INFO 7659 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/8.0.37
2018-03-15 15:25:42.850 INFO 7659 --- [ost-startStop-1] org.apache.catalina.loader.WebappLoader : Unknown loader jdk.internal.loader.ClassLoaders$AppClassLoader@1b9e1916 class jdk.internal.loader.ClassLoaders$AppClassLoader
2018-03-15 15:25:42.868 INFO 7659 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2018-03-15 15:25:42.868 INFO 7659 --- [ost-startStop-1] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 1764 ms
2018-03-15 15:25:43.278 INFO 7659 --- [ost-startStop-1] o.s.b.c.e.ServletRegistrationBean : Mapping servlet: 'dispatcherServlet' to [/]
2018-03-15 15:25:43.282 INFO 7659 --- [ost-startStop-1] o.s.b.c.embedded.FilterRegistrationBean : Mapping filter: 'metricsFilter' to: [/*]
2018-03-15 15:25:43.282 INFO 7659 --- [ost-startStop-1] o.s.b.c.embedded.FilterRegistrationBean : Mapping filter: 'characterEncodingFilter' to: [/*]
2018-03-15 15:25:43.282 INFO 7659 --- [ost-startStop-1] o.s.b.c.embedded.FilterRegistrationBean : Mapping filter: 'hiddenHttpMethodFilter' to: [/*]
2018-03-15 15:25:43.282 INFO 7659 --- [ost-startStop-1] o.s.b.c.embedded.FilterRegistrationBean : Mapping filter: 'httpPutFormContentFilter' to: [/*]
2018-03-15 15:25:43.283 INFO 7659 --- [ost-startStop-1] o.s.b.c.embedded.FilterRegistrationBean : Mapping filter: 'requestContextFilter' to: [/*]
2018-03-15 15:25:43.283 INFO 7659 --- [ost-startStop-1] o.s.b.c.embedded.FilterRegistrationBean : Mapping filter: 'webRequestLoggingFilter' to: [/*]
2018-03-15 15:25:43.283 INFO 7659 --- [ost-startStop-1] o.s.b.c.embedded.FilterRegistrationBean : Mapping filter: 'applicationContextIdFilter' to: [/*]
2018-03-15 15:25:44.388 INFO 7659 --- [ main] o.s.cloud.commons.util.InetUtils : Cannot determine local hostname
2018-03-15 15:25:44.737 INFO 7659 --- [ main] s.w.s.m.m.a.RequestMappingHandlerAdapter : Looking for @ControllerAdvice: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@5942ee04: startup date [Thu Mar 15 15:25:41 CET 2018]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext@43b9fd5
2018-03-15 15:25:44.866 INFO 7659 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/aritmetica/sumar],methods=[GET],params=[operando1 && operando2]}" onto public java.lang.Integer com.tecnicomio.microservicios.spring.CalculadoraAritmeticaRESTController.sumar(java.lang.Integer,java.lang.Integer)
2018-03-15 15:25:44.867 INFO 7659 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/aritmetica/multiplicar],methods=[GET],params=[operando1 && operando2]}" onto public java.lang.Integer com.tecnicomio.microservicios.spring.CalculadoraAritmeticaRESTController.multiplicar(java.lang.Integer,java.lang.Integer)
2018-03-15 15:25:44.869 INFO 7659 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error]}" onto public org.springframework.http.ResponseEntity org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest)
2018-03-15 15:25:44.869 INFO 7659 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error],produces=[text/html]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)
2018-03-15 15:25:44.897 INFO 7659 --- [ main] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2018-03-15 15:25:44.897 INFO 7659 --- [ main] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2018-03-15 15:25:44.941 INFO 7659 --- [ main] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/**/favicon.ico] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2018-03-15 15:25:45.415 INFO 7659 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/pause || /pause.json],methods=[POST]}" onto public java.lang.Object org.springframework.cloud.endpoint.GenericPostableMvcEndpoint.invoke()
2018-03-15 15:25:45.416 INFO 7659 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/beans || /beans.json],methods=[GET],produces=[application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2018-03-15 15:25:45.417 INFO 7659 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/env],methods=[POST]}" onto public java.lang.Object org.springframework.cloud.context.environment.EnvironmentManagerMvcEndpoint.value(java.util.Map)
2018-03-15 15:25:45.417 INFO 7659 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/env/reset],methods=[POST]}" onto public java.util.Map org.springframework.cloud.context.environment.EnvironmentManagerMvcEndpoint.reset()
2018-03-15 15:25:45.420 INFO 7659 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/trace || /trace.json],methods=[GET],produces=[application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2018-03-15 15:25:45.421 INFO 7659 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/dump || /dump.json],methods=[GET],produces=[application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2018-03-15 15:25:45.422 INFO 7659 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/mappings || /mappings.json],methods=[GET],produces=[application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2018-03-15 15:25:45.423 INFO 7659 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/restart || /restart.json],methods=[POST]}" onto public java.lang.Object org.springframework.cloud.context.restart.RestartMvcEndpoint.invoke()
2018-03-15 15:25:45.424 INFO 7659 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/features || /features.json],methods=[GET],produces=[application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2018-03-15 15:25:45.424 INFO 7659 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/env/{name:.*}],methods=[GET],produces=[application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EnvironmentMvcEndpoint.value(java.lang.String)
2018-03-15 15:25:45.425 INFO 7659 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/env || /env.json],methods=[GET],produces=[application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2018-03-15 15:25:45.425 INFO 7659 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/configprops || /configprops.json],methods=[GET],produces=[application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2018-03-15 15:25:45.426 INFO 7659 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/archaius || /archaius.json],methods=[GET],produces=[application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2018-03-15 15:25:45.427 INFO 7659 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/health || /health.json],produces=[application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.HealthMvcEndpoint.invoke(java.security.Principal)
2018-03-15 15:25:45.427 INFO 7659 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/info || /info.json],methods=[GET],produces=[application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2018-03-15 15:25:45.428 INFO 7659 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/refresh || /refresh.json],methods=[POST]}" onto public java.lang.Object org.springframework.cloud.endpoint.GenericPostableMvcEndpoint.invoke()
2018-03-15 15:25:45.429 INFO 7659 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/metrics/{name:.*}],methods=[GET],produces=[application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.MetricsMvcEndpoint.value(java.lang.String)
2018-03-15 15:25:45.429 INFO 7659 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/metrics || /metrics.json],methods=[GET],produces=[application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2018-03-15 15:25:45.430 INFO 7659 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/resume || /resume.json],methods=[POST]}" onto public java.lang.Object org.springframework.cloud.endpoint.GenericPostableMvcEndpoint.invoke()
2018-03-15 15:25:45.431 INFO 7659 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/autoconfig || /autoconfig.json],methods=[GET],produces=[application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2018-03-15 15:25:45.554 INFO 7659 --- [ main] o.s.ui.freemarker.SpringTemplateLoader : SpringTemplateLoader for FreeMarker: using resource loader [org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@5942ee04: startup date [Thu Mar 15 15:25:41 CET 2018]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext@43b9fd5] and template loader path [classpath:/templates/]
2018-03-15 15:25:45.555 INFO 7659 --- [ main] o.s.w.s.v.f.FreeMarkerConfigurer : ClassTemplateLoader for Spring macros added to FreeMarker configuration
2018-03-15 15:25:45.634 WARN 7659 --- [ main] c.n.c.sources.URLConfigurationSource : No URLs will be polled as dynamic configuration sources.
2018-03-15 15:25:45.634 INFO 7659 --- [ main] c.n.c.sources.URLConfigurationSource : To enable URLs as dynamic configuration sources, define System property archaius.configurationSource.additionalUrls or make config.properties available on classpath.
2018-03-15 15:25:45.642 WARN 7659 --- [ main] c.n.c.sources.URLConfigurationSource : No URLs will be polled as dynamic configuration sources.
2018-03-15 15:25:45.642 INFO 7659 --- [ main] c.n.c.sources.URLConfigurationSource : To enable URLs as dynamic configuration sources, define System property archaius.configurationSource.additionalUrls or make config.properties available on classpath.
2018-03-15 15:25:45.689 WARN 7659 --- [ main] arterDeprecationWarningAutoConfiguration : spring-cloud-starter-eureka-server is deprecated as of Spring Cloud Netflix 1.4.0, please migrate to spring-cloud-starter-netflix-eureka-server
2018-03-15 15:25:45.768 INFO 7659 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Registering beans for JMX exposure on startup
2018-03-15 15:25:45.784 INFO 7659 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Bean with name 'refreshScope' has been autodetected for JMX exposure
2018-03-15 15:25:45.784 INFO 7659 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Bean with name 'environmentManager' has been autodetected for JMX exposure
2018-03-15 15:25:45.786 INFO 7659 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Bean with name 'configurationPropertiesRebinder' has been autodetected for JMX exposure
2018-03-15 15:25:45.787 INFO 7659 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Bean with name 'refreshEndpoint' has been autodetected for JMX exposure
2018-03-15 15:25:45.788 INFO 7659 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Bean with name 'restartEndpoint' has been autodetected for JMX exposure
2018-03-15 15:25:45.794 INFO 7659 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Located managed bean 'environmentManager': registering with JMX server as MBean [org.springframework.cloud.context.environment:name=environmentManager,type=EnvironmentManager]
2018-03-15 15:25:45.816 INFO 7659 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Located managed bean 'restartEndpoint': registering with JMX server as MBean [org.springframework.cloud.context.restart:name=restartEndpoint,type=RestartEndpoint]
2018-03-15 15:25:45.827 INFO 7659 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Located managed bean 'refreshScope': registering with JMX server as MBean [org.springframework.cloud.context.scope.refresh:name=refreshScope,type=RefreshScope]
2018-03-15 15:25:45.832 INFO 7659 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Located managed bean 'configurationPropertiesRebinder': registering with JMX server as MBean [org.springframework.cloud.context.properties:name=configurationPropertiesRebinder,context=5942ee04,type=ConfigurationPropertiesRebinder]
2018-03-15 15:25:45.848 INFO 7659 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Located managed bean 'refreshEndpoint': registering with JMX server as MBean [org.springframework.cloud.endpoint:name=refreshEndpoint,type=RefreshEndpoint]
2018-03-15 15:25:46.013 INFO 7659 --- [ main] o.s.c.support.DefaultLifecycleProcessor : Starting beans in phase 0
2018-03-15 15:25:46.158 INFO 7659 --- [ main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 42809 (http)
2018-03-15 15:25:46.158 INFO 7659 --- [ main] c.n.e.EurekaDiscoveryClientConfiguration : Updating port to 42809
2018-03-15 15:25:46.168 INFO 7659 --- [ main] o.s.c.n.eureka.InstanceInfoFactory : Setting initial instance status as: STARTING
2018-03-15 15:25:46.741 INFO 7659 --- [ main] c.n.d.provider.DiscoveryJerseyProvider : Using JSON encoding codec LegacyJacksonJson
2018-03-15 15:25:46.743 INFO 7659 --- [ main] c.n.d.provider.DiscoveryJerseyProvider : Using JSON decoding codec LegacyJacksonJson
2018-03-15 15:25:46.877 INFO 7659 --- [ main] c.n.d.provider.DiscoveryJerseyProvider : Using XML encoding codec XStreamXml
2018-03-15 15:25:46.878 INFO 7659 --- [ main] c.n.d.provider.DiscoveryJerseyProvider : Using XML decoding codec XStreamXml
2018-03-15 15:25:47.112 INFO 7659 --- [ main] c.n.d.s.r.aws.ConfigClusterResolver : Resolving eureka endpoints via configuration
2018-03-15 15:25:47.140 INFO 7659 --- [ main] com.netflix.discovery.DiscoveryClient : Disable delta property : false
2018-03-15 15:25:47.140 INFO 7659 --- [ main] com.netflix.discovery.DiscoveryClient : Single vip registry refresh property : null
2018-03-15 15:25:47.140 INFO 7659 --- [ main] com.netflix.discovery.DiscoveryClient : Force full registry fetch : false
2018-03-15 15:25:47.140 INFO 7659 --- [ main] com.netflix.discovery.DiscoveryClient : Application is null : false
2018-03-15 15:25:47.140 INFO 7659 --- [ main] com.netflix.discovery.DiscoveryClient : Registered Applications size is zero : true
2018-03-15 15:25:47.140 INFO 7659 --- [ main] com.netflix.discovery.DiscoveryClient : Application version is -1: true
2018-03-15 15:25:47.140 INFO 7659 --- [ main] com.netflix.discovery.DiscoveryClient : Getting all instance registry info from the eureka server
2018-03-15 15:25:47.657 INFO 7659 --- [ main] com.netflix.discovery.DiscoveryClient : The response status is 200
2018-03-15 15:25:47.658 INFO 7659 --- [ main] com.netflix.discovery.DiscoveryClient : Starting heartbeat executor: renew interval is: 30
2018-03-15 15:25:47.667 INFO 7659 --- [ main] c.n.discovery.InstanceInfoReplicator : InstanceInfoReplicator onDemand update allowed rate per min is 4
2018-03-15 15:25:47.670 INFO 7659 --- [ main] com.netflix.discovery.DiscoveryClient : Discovery Client initialized at timestamp 1521123947669 with initial instances count: 0
2018-03-15 15:25:47.696 INFO 7659 --- [ main] c.n.e.EurekaDiscoveryClientConfiguration : Registering application calculadora-aritmetica-eureka-client with eureka with status UP
2018-03-15 15:25:47.697 INFO 7659 --- [ main] com.netflix.discovery.DiscoveryClient : Saw local status change event StatusChangeEvent [timestamp=1521123947697, current=UP, previous=STARTING]
2018-03-15 15:25:47.715 INFO 7659 --- [ main] c.t.m.s.CalculadoraAritmeticaServer : Started CalculadoraAritmeticaServer in 11.699 seconds (JVM running for 12.527)
2018-03-15 15:25:47.716 INFO 7659 --- [nfoReplicator-0] com.netflix.discovery.DiscoveryClient : DiscoveryClient_CALCULADORA-ARITMETICA-EUREKA-CLIENT/localhost:calculadora-aritmetica-eureka-client:0: registering service...
2018-03-15 15:25:47.867 INFO 7659 --- [nfoReplicator-0] com.netflix.discovery.DiscoveryClient : DiscoveryClient_CALCULADORA-ARITMETICA-EUREKA-CLIENT/localhost:calculadora-aritmetica-eureka-client:0 - registration status: 204
2018-03-15 15:26:14.100 INFO 7659 --- [o-auto-1-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring FrameworkServlet 'dispatcherServlet'
2018-03-15 15:26:14.100 INFO 7659 --- [o-auto-1-exec-1] o.s.web.servlet.DispatcherServlet : FrameworkServlet 'dispatcherServlet': initialization started
2018-03-15 15:26:14.129 INFO 7659 --- [o-auto-1-exec-1] o.s.web.servlet.DispatcherServlet : FrameworkServlet 'dispatcherServlet': initialization completed in 29 ms
2018-03-15 15:26:17.659 INFO 7659 --- [freshExecutor-0] com.netflix.discovery.DiscoveryClient : Disable delta property : false
2018-03-15 15:26:17.659 INFO 7659 --- [freshExecutor-0] com.netflix.discovery.DiscoveryClient : Single vip registry refresh property : null
2018-03-15 15:26:17.659 INFO 7659 --- [freshExecutor-0] com.netflix.discovery.DiscoveryClient : Force full registry fetch : false
2018-03-15 15:26:17.659 INFO 7659 --- [freshExecutor-0] com.netflix.discovery.DiscoveryClient : Application is null : false
2018-03-15 15:26:17.659 INFO 7659 --- [freshExecutor-0] com.netflix.discovery.DiscoveryClient : Registered Applications size is zero : true
2018-03-15 15:26:17.659 INFO 7659 --- [freshExecutor-0] com.netflix.discovery.DiscoveryClient : Application version is -1: false
2018-03-15 15:26:17.659 INFO 7659 --- [freshExecutor-0] com.netflix.discovery.DiscoveryClient : Getting all instance registry info from the eureka server
2018-03-15 15:26:17.709 INFO 7659 --- [freshExecutor-0] com.netflix.discovery.DiscoveryClient : The response status is 200

Estableciendo un Gateway API para dar acceso a los servicios
Llegados a este punto tenemos:
- Un servicio REST para operaciones aritméticas
- El servicios REST de operaciones aritméticas documentado con Swagger, y está documentación accesible a través de una URL
- Eureka, el Registry Discovery de NETFLIX arrancado
- El servicio REST de operaciones aritméticas capaz de ser detectado por el Registry Discovery.
La ultima pieza que voy a incluir en este ecosistema de microservicios es el Gateway que concentra las llamadas de los clientes. La verdad es que el ejemplo que estoy utilizando se queda un poco corto para entender porque es necesario un gateway, total, solo tenemos un servicio publicado en una máquina al que podemos acceder desde una única URL.
Pero, ¿qué pasaría si tuviera 10 servicios cada uno con su URL propia? Tendría 10 urls, cada una diferente y cada una con su documentación swagger. El API Gateway viene al rescate y ofrece un único punto de acceso, una URL de invocación homogénea y una única documentación swagger.
El API Gateway en el que voy a integrar mi API de operaciones aritméticas va a ser ZUUL, el API Gateway de Netflix.
Links
