Introducción
Contenido
Spring Framework es un marco muy robusto, lanzado en 2002. Sus características principales pueden aplicarse a aplicaciones Java simples o ampliarse a aplicaciones web modernas y complejas.
Dado que se actualiza constantemente y sigue nuevos paradigmas de arquitectura y programación, ofrece soporte para muchos otros marcos que trabajan de la mano con él.
Con una gama tan amplia de funcionalidades, es normal que nos presente algunas anotaciones nuevas, que son una parte clave del desarrollo de aplicaciones Spring.
La configuración de Spring es totalmente personalizable, lo que originalmente se hizo a través de archivos de configuración XML. Sin embargo, este enfoque se ha quedado obsoleto y la mayoría de las personas hoy en día recurren a la configuración de anotaciones.
Dicho esto, esta serie de artículos tiene como objetivo desentrañar las opciones que usted, como desarrollador, tiene para configurar y usar el marco Spring:
Te puede interesar:El patrón de diseño del observador en Java- Anotaciones de Spring: @RequestMapping y sus variantes
- Spring Annotations: anotaciones principales
- Notas de Spring: Spring Cloud
- Spring Annotations: Prueba de anotaciones
Anotaciones de Spring Cloud
Nube de Spring es una gran extensión del ya robusto Spring Framework. Permite a los desarrolladores crear patrones comunes sin esfuerzo y sin dolor cuando se trata de arquitectura basada en la nube, como la configuración de disyuntores, descubrimiento de clientes, enrutamiento, etc.
Ya hemos publicado varios artículos que cubren algunos de estos temas, por lo que si desea ver estas anotaciones sobre ejemplos prácticos, estos son un gran comienzo:
- Spring Cloud: descubrimiento de servicios con Eureka
- Spring Cloud: enrutamiento con Zuul y Gateway
- Nube de Spring: Hystrix
- Spring Cloud: Turbina
- Spring Cloud Stream con RabbitMQ: microservicios basados en mensajes
@EnableConfigServer
Spring Cloud nos presenta varias herramientas útiles, cada una de las cuales necesita algún tipo de configuración.
Si usamos varias herramientas, sería lógico almacenar todos los detalles de configuración en un solo lugar, similar a un application.properties
archivo.
Para hacer esto, anotamos una clase con el @EnableConfigServer
anotación, aplicada a nivel de clase:
@SpringBootApplication
@EnableConfigServer
public class SomeApplication {
public static void main(String[] args) {
SpringApplication.run(SomeApplication.class, args);
}
}
Esta anotación le dice a Spring dónde buscar configuraciones y al crear una configuración de servidor centralizada como esta, otras aplicaciones pueden comunicarse con él a través de su puerto, que por defecto es 8080
.
@EnableEurekaServer
Al desarrollar un proyecto con una arquitectura de microservicio, especialmente cuando hay numerosos servicios que deberían funcionar juntos, nos enfrentamos a un problema. La forma en que estos servicios se comunican entre sí.
Podríamos codificar todos los nombres y puertos en un archivo de propiedad, pero esta es una mala práctica y no es escalable en absoluto. Incluso si lo hiciéramos, ¿qué sucede cuando hay varias instancias de un servicio? ¿Cuál responde a la solicitud?
Para resolverlos, podemos confiar en Service Discovery a través de Eureka.
Muy similar al @EnableConfigServer
anotación, crearemos un servidor Eureka anotando una clase con @EnableEurekaServer
, que ahora se puede usar para buscar otros servicios registrados y administrarlos:
@SpringBootApplication
@EnableEurekaServer
public class SomeApplication {
public static void main(String[] args) {
SpringApplication.run(SomeApplication.class, args);
}
}
@HabilitarEurekaClient
Un servidor Eureka no es nada sin sus servicios. Cada servicio que queramos poner en el radar de nuestro servidor debe estar anotado con el @EnableEurekaClient
anotación.
Como alternativa, podríamos utilizar el @EnableDiscoveryClient
anotación, que proviene de spring-cloud-commons
. Sin embargo, si conoce la implementación específica que utilizará, es mejor ser específico. Si está usando el más genético @EnableDiscoveryClient
anotación, Spring elegirá la implementación en función de la .jar
s presentes en la ruta de clases.
@SpringBootApplication
@EnableEurekaClient
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
@EnableDiscoveryClient
La anotación de cliente de descubrimiento predeterminada que marca una clase como un servicio que se debe poner en el radar de un servidor.
@EnableCircuitBreaker
Una vez más, cuando trabajamos con microservicios, nos enfrentamos a un gran problema. Es común que los servicios trabajen con otros servicios para completar ciertas solicitudes.
Digamos que el Servicio A llama al Servicio B, que depende del Servicio C para completar una solicitud. Ahora digamos que el servicio C falla completamente debido a un error de red o una sobrecarga. Lo que sucede a continuación es un error en cascada en el flujo de lógica que regresa al Servicio A.
Te puede interesar:Algoritmo de optimización de recocido simulado en JavaLo que podemos hacer para corregir esto es implementar interruptores automáticos. Cada servicio debe tener un punto de ruptura de circuito, y si ocurre algo malo, «abren sus circuitos» para que el problema no se transponga a otros servicios. En este caso, el disyuntor de nuestra elección aísla el servicio que falla para que otros servicios no puedan llamarlo y fallar también.
los @EnableCircuitBreaker
La anotación se aplica a nivel de clase, para todos y cada uno de los servicios en nuestra arquitectura de microservicio:
@SpringBootApplication
@EnableDiscoveryClient
@EnableCircuitBreaker
public class ServiceA {
public static void main(String[] args) {
SpringApplication.run(ServiceA.class, args);
}
}
@SpringBootApplication
@EnableDiscoveryClient
@EnableCircuitBreaker
public class ServiceB {
public static void main(String[] args) {
SpringApplication.run(ServiceB.class, args);
}
}
@SpringBootApplication
@EnableDiscoveryClient
@EnableCircuitBreaker
public class ServiceC {
public static void main(String[] args) {
SpringApplication.run(ServiceC.class, args);
}
}
El patrón de disyuntor en Spring se implementa a través de Spring Cloud: Hystrix.
@HystrixCommand
Para que el patrón del disyuntor funcione completamente, no podemos solo anotar clases. Dado que en casi todas las situaciones podemos «esperar» que un método pueda ser riesgoso, en el sentido de que podría fallar cuando se llama, lo marcamos con @HystrixCommand
. Junto a la anotación, también podemos agregar una bandera que apunte a un método diferente para ejecutar si el original falla:
@GetMapping(value = "/personalized/{id}")
@HystrixCommand(fallbackMethod = "recommendationFallback")
public Product[] personalized(@PathVariable int id) {
Product[] result = restTemplate.getForObject("http://recommendation-service/recommendations", Product[].class);
return result;
}
public Product[] recommendationFallback(int id) {
System.out.println("=======recommendationFallback=========" + id);
return new Product[0];
}
@RibbonClient
Cinta funciona como un equilibrador de carga en el lado del cliente y le da control sobre los clientes HTTP y TCP.
Te puede interesar:El patrón de diseño de proxy en JavaEn la mayoría de los casos, cuando se utiliza un cliente de descubrimiento como Eureka, no es necesario utilizar esta anotación, ya que se aplica de forma predeterminada. En la gran mayoría de los casos, las opciones predeterminadas son lo suficientemente buenas como para encargarse del equilibrio de carga, pero si necesita modificarlas, puede hacerlo:
@Configuration
@RibbonClient(name = "custom", configuration = CustomConfiguration.class)
public class SomeConfiguration {
}
los CustomConfiguration
la clase también debe ser una @Configuration
clase anotada con la configuración de cinta personalizada configurada como beans.
@LoadBalanced
los @LoadBalanced
la anotación se usa para marcar RestTemplate
s que deberían funcionar con el RibbonLoadBalancerClient
al interactuar con sus servicios:
@RestController
@RibbonClient(name = "custom", configuration = CustomConfiguration.class)
public class SomeApplication {
@LoadBalanced
@Bean
RestTemplate restTemplate(){
return new RestTemplate();
}
// ...
}
Esta anotación básicamente permite RestTemplate
para aprovechar su soporte integrado para el equilibrio de carga.
Conclusión
El marco de Spring es un marco poderoso y robusto que realmente cambió el juego cuando se trata de desarrollar aplicaciones web. Entre su gran cantidad de proyectos, el módulo Spring Cloud es una gran extensión del marco original.
Te puede interesar:Nube de Spring: Hystrix