简单使用 Ribbon 实现微服务高可用通信 2022-03-06 程序之旅,记录 暂无评论 659 次阅读 ## 简单使用 Ribbon 实现微服务高可用通信 负载均衡按实现分类方式,可以分为服务端负载均衡和客户端负载均衡 ### 服务端负载均衡 在架构中会提供专用的负载均衡器,由负载均衡器持有后端节点的信息,服务消费者发来的请求经由专用的负载均衡器分发给服务提供者,进而实现负载均衡。 常用的负载均衡器硬件有:F5、Nginx、HaProxy 等。 ### 客户端负载均衡 在架构中不在部署额外的负载均衡器,在每个服务消费者内部持有服务端负载均衡器,由内置的负载均衡策略决定向哪个服务提供者发起请求。 常用的有:Netfilx Ribbon ### Ribbon + RestTemplate 实现服务间高可用通信 > RestTemplate 对象是 Spring Cloud 封装的 RESTful 通信对象,它封装了基于 HTTP 协议的操作,通过简单的 API 便可发起 HTTP 请求并自动处理响应 在Spring Initializr 中创建 spring boot 项目,构建地址使用的是 `https://start.aliyun.com`。 #### 搭建环境 | Ip | 端口 | 描述 | | ------------- | ---- | ------------------ | | 192.168.1.102 | 8848 | Nacos 注册中心实例 | | 192.168.1.101 | 9081 | 服务提供者1 | | 192.168.1.102 | 9081 | 服务提供者2 | | 192.168.1.101 | 9091 | 消费者 | #### 第一步,创建服务提供者 pom.xml 依赖有 ```xml org.springframework.boot spring-boot-starter-web com.alibaba.cloud spring-cloud-starter-alibaba-nacos-discovery org.springframework.boot spring-boot-starter-test test org.junit.vintage junit-vintage-engine ``` application.properties 配置文件 ```properties # 应用名称 spring.application.name=provider-service # 应用服务 WEB 访问端口 server.port=9080 # Nacos帮助文档: https://nacos.io/zh-cn/docs/concepts.html # Nacos认证信息 spring.cloud.nacos.discovery.username=nacos spring.cloud.nacos.discovery.password=nacos # Nacos 服务发现与注册配置,其中子属性 server-addr 指定 Nacos 服务器主机和端口 spring.cloud.nacos.discovery.server-addr=192.168.1.102:8848 # 注册到 nacos 的指定 namespace,默认为 public spring.cloud.nacos.discovery.namespace=public ``` 创建服务提供者的接口 ```java import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class ProviderController { @GetMapping("/provider/msg") public String sendMessage() { return "这个服务提供接口"; } } ``` 打包运行后出现如下: ![image-20220306160444096](https://mufeng-blog.oss-cn-beijing.aliyuncs.com/typecho/image-20220306160444096.png) #### 第二部,创建服务消费者 构建流程与创建服务提供者一样,创建 consumer-service。 pom.xml 配置 ```xml org.springframework.boot spring-boot-starter-web com.alibaba.cloud spring-cloud-starter-alibaba-nacos-discovery org.springframework.cloud spring-cloud-netflix-ribbon ${spring-cloud-alibaba.version} org.springframework.boot spring-boot-starter-test test org.junit.vintage junit-vintage-engine ``` 在启动类中声明 RestTemplate ```java @SpringBootApplication public class ConsumerServiceApplication { // 创建 RestTemplate 对象 @Bean public RestTemplate restTemplate() { return new RestTemplate(); } public static void main(String[] args) { SpringApplication.run(ConsumerServiceApplication.class, args); } } ``` 消费者接口 ```java @RestController public class ConsumerController { @Resource private LoadBalancerClient loadBalancerClient; @Resource private RestTemplate restTemplate; @GetMapping("/consumer/msg") public String getProviderMessage() { // loadBalancerClient.choose() 方法会从 Nacos 获取 provider-service 所有可用实例 // 并按负载均衡策略从中选择一个可用实例,封装为 ServiceInstance (服务实例)对象 // 结合享有环境,两个实例选择一个包装为 ServiceInstance ServiceInstance serviceInstance = loadBalancerClient.choose("provider-service"); String host = serviceInstance.getHost(); int port = serviceInstance.getPort(); System.out.println("本次调用 provider-service 的" + host + ":" + port + "实例节点负责处理"); String result = restTemplate.getForObject("http://" + host + ":" + port + "/provider/msg", String.class); String resultString = "provider-service 响应数据:" + result; System.out.println(resultString); return resultString; } } ``` Ribbon 的执行流程如上 - 先从 Nacos 获取可用服务提供实例信息 - 在通过 RestTemplate.getForObject() 向改实例发起 RESTful 请求请求完成处理 > 另一种实现方式,可以在声明 RestTemplate 前加上 @LoadBalanced 注解,使 RestTemplate 对象自动支持 Ribbon负载均衡,以上代码可以忽略 LoadBalancerClient 的声明。其中 Ribbon 采用的轮询策略。 打包运行后 ![image-20220306162445282](https://mufeng-blog.oss-cn-beijing.aliyuncs.com/typecho/image-20220306162445282.png) 浏览器执行地址 http://localhost:9091/consumer/msg,响应数据如下 ![image-20220306163027222](https://mufeng-blog.oss-cn-beijing.aliyuncs.com/typecho/image-20220306163027222.png) ### Ribbon 的负载均衡策略 **RoundRobinRule** 轮询策略,Ribbon 默认策略,默认超过 10 次获取到的 server 都不可用,会返回一个空的 server。 **RandomRule** 随机策略,如果随机到的 server 为 null 或者不可用的话,会不停低循环选取 **RetryRule** 重试策略,一定时限循环重试 >- RetryRule 会在每次选取之后,对选举的 server 进行判断,是否为 null,是否 alive,并且在 500 ms 内会不停低选取判断 >- RoundRobinRule 失效的策略是超过 10 次 >- RandomRule 没有失效时间的概念,只要 serverList 没都挂 **BestAvailableRule** 最小连接数策略,遍历 serverList,选取出可用的且连接数最小的一个 server,会调用 RoundRobinRule 重新选取。 **AvailabilityFilteringRule** 可用过滤策略,扩展了轮询策略,会先通过默认的轮询选取一个 server,再去判断该 server 是否超过可用、当前连接数是否超限,都成功再返回。 **ZoneAvoiddanceRule** 区域权衡策略,扩展了轮询策略,处理过滤超时和连接数过多的 server,还会过滤掉不符合要求的 zone 区域里面的所有节点,始终保证在一个区域/机房的服务实例进行轮询。 #### 使用方法 consumer 配置文件中添加一下内容 ```pro #针对client-a服务使用随机策略 consumer-service.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RandomRule ``` 打赏: 微信, 支付宝 标签: spring boot, spring cloud alibaba, ribbon, 负载均衡 本作品采用 知识共享署名-相同方式共享 4.0 国际许可协议 进行许可。