目录

  • Spring-Cloud 学习笔记-(4)负载均衡器Ribbon
  • 1、前言
  • 2、什么是负载均衡
    • 2.1、问题分析
    • 2.2、什么是Ribbon
  • 3、快速入门
    • 3.1、实现方式一

      • 3.1.1、修改代码
    • 3.2、实现方式二
      • 3.2.1、启动类
      • 3.2.2、调用代码
      • 3.2.3、测试
      • 3.2.4、实现原理
      • 3.2.5、断点调式
    • 3.3、修改轮询策略
    • 3.4、重载机制
      • 3.4.1、为什么要有重载机制
      • 3.4.2、实现代码

Spring-Cloud 学习笔记-(4)负载均衡器Ribbon

1、前言

  • 上个章节我们做了什么?

    上个章节我们说了用eureka来实现服务的注册与发现,并且用过服务的seviceId拉取了服务列表List<ServiceInstance> instances = discoveryClient.getInstances("user-service") 从而实现服务的调用方(order-service)调用服务的提供方(user-service)

  • 本章节我们会做什么?

    负载均衡

2、什么是负载均衡

2.1、问题分析

​ 上个章节我们实现了服务之间的调用,把原来代码里面写死的ip地址,换成用serviceId拉取服务列表,然后从服务列表中获取实例的方式,虽然代码变得复杂了,但是思想上我们得到的升级,但是还是存在一个问题,就是ServiceInstance instance = instances.get(0);每次我们都取同一个ip,要想每次使用不同的ip,我们自己就要写负载均衡算法,从多个实例当中获取某一个实例进行调用,这次我们这一章节讲的就是负载均衡器Ribbon,它里面内置了很多负载均衡的算法,帮我们从实例列表中获取一个实例。

2.2、什么是Ribbon

3、快速入门

我们按照上节课方法启动,一个Eureka注册中心,两个(方便演示负载均衡)服务的提供方(user-service),最后我们修改服务调用方(order-service)代码

pom文件

<!-- ribbon -->
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>

3.1、实现方式一

3.1.1、修改代码

    //注入  RibbonLoadBalancerClient@Autowiredprivate LoadBalancerClient client;
...//通过serviceId 拉取服务列表//List<ServiceInstance> instances = discoveryClient.getInstances("user-service");//ServiceInstance instance = instances.get(0);ServiceInstance instance = client.choose("user-service");
String jsonStr = restTemplate.getForObject("http://"+instance.getHost()+":"+instance.getPort()+"/api/v1/user/2", String.class);

之前我们是通过serviceId(“user-service”)获取到的是服务列表,现在我们直接可以通过serviceId,返回的是单个实例,不是因为列表里面只有一个实例,是因为choose方法中已经帮我们做了复杂均衡了。

3.2、实现方式二

3.2.1、启动类

/*** 把RestTemplate注入到Spring容器中*/
@Bean
@LoadBalanced //增加注解   让RestTemplate内置一个负载均衡器
public RestTemplate restTemplate(){return new RestTemplate();
}

3.2.2、调用代码

String jsonStr = restTemplate.getForObject("http://user-service/api/v1/user/2", String.class);

之前我们把serviceId交出去,别人帮我们取一堆,或者取一个,现在直接把serviceId写在url路径中。

3.2.3、测试

启动order-service

访问:http://localhost:8781/api/v1/order/2

3.2.4、实现原理

其实实现方式二低层就是用的实现方式一,只不过实现方式二加了一个拦截器LoadBalancerInterceptor对RestTemplate请求做了拦截,然后把请求路径中的serviceId("user-service")拿到,然后通过方式一获取某一个实例进行调用。

3.2.5、断点调式

我们按两下shift搜索到LoadBalancerInterceptor这个拦截器,在intercept方法中打好断点

public ClientHttpResponse intercept(final HttpRequest request, final byte[] body, final ClientHttpRequestExecution execution) throws IOException {//1.拿到请求路径URI originalUri = request.getURI();//2.从路径中获取serviceIdString serviceName = originalUri.getHost();Assert.state(serviceName != null, "Request URI does not contain a valid hostname: " + originalUri);//3.执行execute方法.. 我们接着看execute方法return (ClientHttpResponse)this.loadBalancer.execute(serviceName, this.requestFactory.createRequest(request, body, execution));
}// RibbonLoadBalancerClient类中
public <T> T execute(String serviceId, LoadBalancerRequest<T> request) throws IOException {//4.根据serviceId获取到负载均衡器ILoadBalancer loadBalancer = this.getLoadBalancer(serviceId);//5.通过负载均衡器拿到某一个实例..我们接着看getServer方法Server server = this.getServer(loadBalancer);if (server == null) {throw new IllegalStateException("No instances available for " + serviceId);} else {RibbonLoadBalancerClient.RibbonServer ribbonServer = new RibbonLoadBalancerClient.RibbonServer(serviceId, server, this.isSecure(server, serviceId), this.serverIntrospector(serviceId).getMetadata(server));return this.execute(serviceId, ribbonServer, request);}}//RibbonLoadBalancerClient类中
protected Server getServer(ILoadBalancer loadBalancer) {//6.判断负载均衡器是不是为空,不为空调用chooseServer("default")方法,我们接着看return loadBalancer == null ? null : loadBalancer.chooseServer("default");
}//BaseLoadBalancer类中
public Server chooseServer(Object key) {//这里key是默认值“default”if (this.counter == null) {this.counter = this.createCounter();}this.counter.increment();if (this.rule == null) {return null;} else {try {//根据rule调用choose方法,其中IRule是一个接口,有很多实现类,每一个实现类对于不同的负载均衡策略,比如RandomRule随机,RoundRobinRule轮询等,我们BaseLoadBalancer类中有一个属性,   private static final IRule DEFAULT_RULE = new RoundRobinRule();代表默认轮询策略,有兴趣的可以看一下每一个实现的choose方法,比如轮询策略RoundRobinRule,底层维护一个自增长的count,每调用一次count++,然后每次用count模于服务列表的长度(比如第一次:1%5=1,第二次:2%5=2)得到的值为服务列表的位置索引,从而实现轮询。return this.rule.choose(key);} catch (Exception var3) {logger.warn("LoadBalancer [{}]:  Error choosing server for key {}", new Object[]{this.name, key, var3});return null;}}}

3.3、修改轮询策略

application.yml:

#--负载均衡轮询策略
# serviceId
user-service:ribbon:#负载均衡策略的classNameNFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule

3.4、重载机制

3.4.1、为什么要有重载机制

在上一章中我们说到,一个正常的eureka客户端,每间隔30秒没有给服务器发送心跳,如果90秒服务器还没有收到心跳,服务器就会认为这个客户端已经宕机,但是eureka不会马上剔除,没间隔60会同意剔除这些失效的客户端,这样导致,我们服务实际上已经宕机了但是服务列表里面还有,这样服务的消费者在调用的时候就会报错,假设我们服务的提供方有五个,虽然只宕机了一台,但是还有四台是正常的,在这个时候我们条用这个服务如果出现报错信息肯定不是我们希望看到的,所有我们就有了这个重载机制,Spring Cloud 整合了Spring Retry 来增强RestTemplate的重试能力,当一次服务调用失败后,不会立即抛出一次,而是再次重试下一个服务。

3.4.2、实现代码

application.yml

#服务名称
spring:application:name: order-servicecloud:loadbalancer:retry:enabled: true # 开启Spring Cloud的重试功能#负载均衡轮询策略
user-service:ribbon:#负载均衡策略的classNameNFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRuleConnectTimeout: 250 # Ribbon的连接超时时间ReadTimeout: 1000 # Ribbon的数据读取超时时间OkToRetryOnAllOperations: true # 是否对所有操作都进行重试MaxAutoRetriesNextServer: 1 # 切换实例的重试次数MaxAutoRetries: 1 # 对当前实例的重试次数

我们测试发现,就算我们user-service宕机了,也能通过另一台服务实例获取到结果!

转载于:https://www.cnblogs.com/bigfly277/p/10147083.html

Spring-Cloud 学习笔记-(4)负载均衡器Ribbon相关推荐

  1. Spring Cloud 学习笔记(1 / 3)

    Spring Cloud 学习笔记(2 / 3) Spring Cloud 学习笔记(3 / 3) - - - 01_前言闲聊和课程说明 02_零基础微服务架构理论入门 03_第二季Boot和Clou ...

  2. Spring Cloud 学习笔记(3 3)

    Spring Cloud 学习笔记(1 / 3) Spring Cloud 学习笔记(2 / 3) - - - 108_Nacos之Linux版本安装 109_Nacos集群配置(上) 110_Nac ...

  3. Spring Cloud 学习笔记(3 / 3)

    Spring Cloud 学习笔记(1 / 3) Spring Cloud 学习笔记(2 / 3) - - - 108_Nacos之Linux版本安装 109_Nacos集群配置(上) 110_Nac ...

  4. Spring Cloud 学习笔记(2 / 3)

    Spring Cloud 学习笔记(1 / 3) Spring Cloud 学习笔记(3 / 3) - - - 56_Hystrix之全局服务降级DefaultProperties 57_Hystri ...

  5. Spring Cloud 学习笔记(2 3)

    Spring Cloud 学习笔记(1 / 3) Spring Cloud 学习笔记(3 / 3) - - - 56_Hystrix之全局服务降级DefaultProperties 57_Hystri ...

  6. Spring Cloud学习笔记

    Spring Cloud学习笔记 相关代码地址:https://github.com/gongxings/spring-cloud-study.git 一.工程环境搭建 spring cloud版本: ...

  7. Spring Cloud学习笔记【十二】Hystrix的使用和了解

    Spring Cloud学习笔记[十二]Hystrix的使用和了解 Hystrix [hɪst'rɪks],中文含义是豪猪,因其背上长满棘刺,从而拥有了自我保护的能力.本文所说的Hystrix是Net ...

  8. Spring Cloud 学习笔记(四)-Spring Cloud Hystrix

    Spring Cloud 学习笔记(四)-Spring Cloud Hystrix 由于前一阵子项目的原因,今天才继续弄上,今天想学习一下Hystrix组件 这个组件还挺抽象的,最开始我一直没太明白, ...

  9. Spring Cloud学习笔记—网关Spring Cloud Gateway官网教程实操练习

    Spring Cloud学习笔记-网关Spring Cloud Gateway官网教程实操练习 1.Spring Cloud Gateway介绍 2.在Spring Tool Suite4或者IDEA ...

  10. 【Spring Cloud学习笔记】【3/2】下篇

    服务注册:将服务信息注册进注册中心 服务发现:从注册中心上获取服务信息 实质:存key服务命取value闭用地址 1先启动eureka注主册中心 2启动服务提供者payment支付服务 3支付服务启动 ...

最新文章

  1. [转]VC无负担实现XP风格界面
  2. hbase,根据前缀匹配进行搜索并分批次获取结果
  3. DFS 之 poj 2386 Lake Counting
  4. poj 3728(LCA + dp)
  5. (24)minify压缩的时候报错
  6. Derby与mysql的关系_Derby数据库简单介绍和使用方法 | 学步园
  7. selenium java api_selenium_java常用API操作
  8. NSNotFound
  9. mobile兼容性调整,根据rem,字体大小,视窗宽度
  10. 『nForce主板』巧妙去掉“安全删除硬盘”图标!
  11. 【路径规划】基于matlab改进的人工势场算法机器人避障路径规划【含Matlab源码 1151期】
  12. AcrelCloud-6800智慧消防管理云平台在学校的应用
  13. python自动翻译pdf_python pdf一键翻译脚本
  14. 路由器默认IP地址和猫IP冲突的解决方法
  15. 物联网芯片+区块链底层融合:紫光展锐开创产业升级新思路
  16. 【vscode】常用快捷键
  17. 【N32G457】基于RT-Thread和N32G457的墨水屏日历
  18. 论文阅读:GMAN: A Graph Multi-Attention Network for Traffic Prediction
  19. PS4游戏将登陆PC:一曲属于主机的悲歌
  20. Python第三章总结

热门文章

  1. PAT_B_1085_Java(25分)
  2. linux编程课后作业,Unix/Linux 编程实践教程第三章习题
  3. 玩转u-boot之【初探环境变量env/bootcmd/bootargs】
  4. 问答机器人接口python_设计用于机器学习工程的Python接口
  5. 迷你5和迷你4区别_可变大小的视频迷你批处理
  6. 使用GridSearchCV和RandomizedSearchCV进行超参数调整
  7. GRE tunnel源码分析之发送流程
  8. 【MobX】390- MobX 入门教程(上)
  9. MATLAB求音频信号特征的自定义函数.md
  10. stright 在mysql_MySQL优化的奇技淫巧之STRAIGHT_JOIN