负载均衡原理

image.png
image.png
LoadBalancerInterceptor实现 ClientHttpRequestInterceptor接口

  1. public class LoadBalancerInterceptor implements ClientHttpRequestInterceptor {...}

进入ClientHttpRequestInterceptor查看干什么:Client Http Request Interceptor本意是客户端Http请求拦截器。也就是它会拦截由客户端发起的http请求。而我们RestTemplate正是发起请求的客户端。

  1. public interface ClientHttpRequestInterceptor {
  2. ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException;
  3. }

返回刚才实现类,既然是实现这个接口,那么就会实现这个接口的方法。RestTemplate发起请求一定会被此方法拦截,我们可以打断点调试查看。

  1. public class LoadBalancerInterceptor implements ClientHttpRequestInterceptor {
  2. private LoadBalancerClient loadBalancer;
  3. private LoadBalancerRequestFactory requestFactory;
  4. public LoadBalancerInterceptor(LoadBalancerClient loadBalancer, LoadBalancerRequestFactory requestFactory) {
  5. this.loadBalancer = loadBalancer;
  6. this.requestFactory = requestFactory;
  7. }
  8. public LoadBalancerInterceptor(LoadBalancerClient loadBalancer) {
  9. this(loadBalancer, new LoadBalancerRequestFactory(loadBalancer));
  10. }
  11. public ClientHttpResponse intercept(final HttpRequest request, final byte[] body, final ClientHttpRequestExecution execution) throws IOException {
  12. URI originalUri = request.getURI();
  13. String serviceName = originalUri.getHost();
  14. Assert.state(serviceName != null, "Request URI does not contain a valid hostname: " + originalUri);
  15. return (ClientHttpResponse)this.loadBalancer.execute(serviceName, this.requestFactory.createRequest(request, body, execution));
  16. }
  17. }

访问浏览器http://localhost:8080/order/102后,程序就会停在我们刚才断点处,发现请求是被获取了,而且还得到我们配置服务名称。
image.png

既然拿到服务名称,那接下来就需要到Eureka进行服务拉取。他把服务名称交给loadBalancer 处理,而loadBalancer是一个BlockingLoadBalancerClient对象。execute是执行,继续跟入此方法。
image.png

我们就到BlockingLoadBalancerClient,继续跟进


负载均衡策略

image.png
image.png
image.png
第一种方式是全局的,以后无论调用哪种服务都会采用随机策略。而第二种方案则可以指定服务采用哪种负载均衡策略。


定义IRule方式

  1. package cn.itcast.order;
  2. @MapperScan("cn.itcast.order.mapper")
  3. @SpringBootApplication
  4. public class OrderApplication {
  5. //....
  6. @Bean
  7. public IRule randomRule(){
  8. return new RandomRule();
  9. }
  10. }

依次访问http://localhost:8080/order/下的101、102、103、104
image.png
image.png

注意:小范围测试可能都会映射再一个服务地址上,当访问次数大,总体上就是随机概率。


配置文件方式

  1. userservice:
  2. ribbon:
  3. NFloadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule

懒加载

Ribbon默认是采用懒加载,即第一次访问时才会去创LoadBalanceClient,请求时间会很长。而饥饿加载则会在项目启动时创建,降低第一次访问的耗时,通过下面配置开启饥饿加载:

  1. ribbon:
  2. eager-load:
  3. enabled: true # 开启饥饿加载
  4. clients: userservice # 指定对userservice这个服务饥饿加载
  5. ribbon:
  6. eager-load:
  7. enabled: true
  8. clients:
  9. - userservice1 #如果有多个服务需要就以下那么配置
  10. - userservice2