SpringCloud 中负载均衡的原理
前情 : 启动了两个 UserService 客户端和一个 OrderService 客户端,且都已经注册到 Eureka 中。
服务消费者OrderService,使用注册中心的名字代替 ip 和端口,设置负载均衡策略 ,直接调用了其中
之一的服务提供者。
java
/**
* 创建 RestTemplate 并注入 Spring 容器
* RestTemplate 是Spring Cloud框架中的一个HTTP客户端工具,
* 用于发送HTTP请求并与远程服务进行通信。
* 它封装了常见的HTTP操作,使得在微服务架构中进行服务间通信更加方便。
*/
@Bean
@LoadBalanced
// order-service(服务消费者) 在调用多个 user-service(服务提供者) 时,使用负载均衡算法
public RestTemplate restTemplate(){
return new RestTemplate();
}
- 通过
LoadBalancerInterceptor
负载均衡拦截器拦截到请求
java
@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,
"Request URI does not contain a valid hostname: " + originalUri);
return this.loadBalancer.execute(serviceName,
this.requestFactory.createRequest(request, body, execution));
}
- 通过
RibbonLoadBalancerClient
获取url 中的服务 id
java
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 instances available for " + serviceId);
}
RibbonServer ribbonServer = new RibbonServer(serviceId, server,
isSecure(server, serviceId),
serverIntrospector(serviceId).getMetadata(server));
return execute(serviceId, ribbonServer, request);
}
- 从 eureka 注册中心拉取
user-service
,返回服务列表 - 通过
IRule
接口选择一种负载均衡策略,拉取某个服务
java
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 choosing server for key {}", new Object[]{this.name, key, var3});
return null;
}
}
}
- 修改 url 发起请求