Funcionamiento del balanceo de carga en Spring Cloud
Conetxto: Se ejecutan dos clientes UserService y uno OrderService, todos registrados en Eureka.
El consumidor de servicios OrderService utiliza el nombre del servicio registrado en el centro de registro en lugar de la dirección IP y puerto, configurando una estrategia de balanceo de carga, y llama directamente a uno de los proveedores de servicios disponibles.
/**
* Crear una instancia de RestTemplate y registrarla en el contenedor de Spring
* RestTemplate es una herramienta cliente HTTP dentro del framework Spring Cloud,
* utilizada para enviar solicitudes HTTP y comunicarse con servicios remotos.
* Abstrae operaciones comunes de HTTP, facilitando la comunicación entre microservicios.
*/
@Bean
@LoadBalanced
// El order-service (consumidor) utiliza un algoritmo de balanceo cuando accede a múltiples instancias de user-service (proveedor)
public RestTemplate restTemplate(){
return new RestTemplate();
}
- El interceptor
LoadBalancerInterceptorintercepta la solicitud
@Override
public ClientHttpResponse intercept(final HttpRequest request, final byte[] body,
final ClientHttpRequestExecution execution) throws IOException {
final URI originalUri = request.getURI();
String serviceName = originalUri.getHost();
Assert.state(serviceName != null,
"La URI de la solicitud no contiene un hostname válido: " + originalUri);
return this.loadBalancer.execute(serviceName,
this.requestFactory.createRequest(request, body, execution));
}
RibbonLoadBalancerClientrecupera el identificador del servicio desde la URL
public <T> T execute(String serviceId, LoadBalancerRequest<T> request, Object hint)
throws IOException {
ILoadBalancer loadBalancer = getLoadBalancer(serviceId);
Server server = getServer(loadBalancer, hint);
if (server == null) {
throw new IllegalStateException("No hay instancias disponibles para " + serviceId);
}
RibbonServer ribbonServer = new RibbonServer(serviceId, server,
isSecure(server, serviceId),
serverIntrospector(serviceId).getMetadata(server));
return execute(serviceId, ribbonServer, request);
}
- Se obtiene la lista de servicios registrados en Eureka para
user-service - Se aplica una estrategia definida por la interfaz
IRulepara seleccionar una instancia específica
public Server chooseServer(Object key) {
if (this.counter == null) {
this.counter = this.createCounter();
}
this.counter.increment();
if (this.rule == null) {
return null;
} else {
try {
return this.rule.choose(key);
} catch (Exception var3) {
logger.warn("LoadBalancer [{}]: Error seleccionando servidor para la clave {}", new Object[]{this.name, key, var3});
return null;
}
}
}
- Se modifica la URL y se envía la solicitud al servidor seleccionado