资料参考:《Spring Cloud 微服务实战》
目录
ClientConfigEnablrdRoundRobinRule
Spring Cloud Ribbon是一个基于HTTP和TCP的客户端负载均衡工具,它基于Netflix Ribbon实现。通过Spring Cloud的封装,可以让我们轻松地面向服务的REST模板请求自动转换成客户端负载均衡的服务调用。Spring Cloud Ribbon虽然只是一个工具栏框架,他不像服务注册中心、配置中心、API网关那样需要独立部署,但是他几乎存在于每一个Spring Cloud构成得微服务和基础设施组件中。因为微服务之间得调用,API网关得请求转发等内容,实际上都是通过Ribbon来实现得,包括后续我们会讲到得Feign,他也是基于Ribbon实现得工具。所以,对Spring Cloud Ribbon得理解和使用,对我们使用Spring Cloud老构建微服务非常重要。
在这一章,我们将具体得介绍如何具体得使用Ribbon来实现客户端得负载均衡,并且通过源码分析来了解Ribbon实现客户端负载均衡得基本原理。
客户端负载均衡
负载均衡是在系统架构中不得不实施得内容。负载均衡是对系统得高可用、网络压力得缓解和处理能力扩容得重要手段之一。我们所说得负载均衡一般是指软件负载均衡,是通过在服务器上安装一些具有均衡负载功能或模块得软件来完成请求分发工作。比如Nginx等。硬件负载均衡一般是指通过在服务器节点之间安装专门用于负载均衡得设备,比如F5等。不管是硬件还是软件负载均衡,只要是服务端负载均衡都能以类似下面得架构方式构建起来:
硬件负载均衡设备或软件负载均衡软件模块都会维护一个下挂可用得服务端清单,通过心跳检测来剔除故障得服务端节点以保证清单中都是可正常访问得服务端节点。当客户端发送请求到负载均衡设备的时候,该设备按某种算法(比如线性轮询、按权重负载均衡、按流量负载均衡等等)从清单中取出一台服务端地址,然后进行转发。
而客户端负载均衡和服务端负载均衡最大得不同点在于上面所提及得服务清单得储存位置不同。所以客户端节点都维护着自己要访问得服务端清单,而这些清单都来自于服务注册中心,比如上一章我们介绍得Eureka服务端。通服务端负载均衡得架构类似,客户端也有一个心跳机制来维护服务端清单得健康性。比如Eureka客户端就有一个配置客户端每30秒更新一次来维护清单得健康性。
通过Spring Cloud Ribbon得封装,我们在微服务架构中使用客户端负载均衡调用非常简单,只需要两部:
- 服务提供者只需要启动多个服务实例,并注册到一个注册中心或是多个相关联得服务注册中心。
- 服务消费者直接调用被@LoadBalanced注解修饰过得RestTemplate来实现面向服务得接口调用。
这样,,我们就可以将服务提供者得高可用以及服务消费者得负载均衡调用一起实现了。
RestTemplate详解
在上一章中,我们已经通过引入Ribbon来实现了服务端得客户端负载均衡功能,读者可以通过查看第1章中得“服务发现与消费”一节来获取实验示例。其中,我们使用了一个非常有用得对象RestTemplate。该对象会使用Ribbon得自动化配置,同事通过配置@LoadBalanced还能够开启客户端得负载均衡。之前我们演示了通过RestTemplate实现了最简单得服务访问,下面我们将详细介绍RestTemplate针对几种不同请求类型和参数类型得服务调用实现。
GET请求
在RestTemplate中,对GET请求可以通过如下两个方法进行调用。
1:第一种:getForEntity函数。该方法返回的是ResponseEntity,该对象是Spring对HTTP请求响应的封装,其中主要存储了HTTP的几个重要元素,比如HTTP请求状态码的枚举对象HttpStatus(也就是我们常说的400、500等错误码)、在他的父类HttpEntity中还存储了HTTP请求头的信息对象HttpHeaders以及泛型类型的请求体对象。比如下面的例子,就是访问USER-SERVER服务的/user请求,同时最后一个参数didi会替换url中的{1}占位符,而返回的ResponseEntity对象中的body内容类型会根据第二个参数转换为String类型。
若我们希望返回的body是一个User对象类型,也可以这样实现:
上面的例子是比较常见的方法,getForEntity函数实际还提供了以下三种不同的重载实现。
2:getForObject函数。该方法可以理解为对getForEntity的进一步封装,它通过HttpMessageConverterExtractor对HTTP的请求响应体body内容进行对象转换,实现请求直接返回包装好的对象内容。比如:
POST请求
在RestTemplate中,对POST请求时可以通过如下三个方法进行调用实现。
1:第一种:postForEntity函数。该方法通GET请求中的getForEntity类似。
2:第二种:postForObject函数。该方法也跟getForObject的类型类似。
3:第三种:postForLocation函数。该方法实现了以POST请求提交资源,并返回了新资源的URI,比如下面的例子:
PUT请求
DELETE请求
源码分析
很多熟悉Spring的都有一个疑问:RestTemplate不说Spring自己提供的么?跟Ribbon的客户端负载均衡有什么关系?所以我们将通过源码分析来了解下Ribbon是如何通过RestTemplate实现客户端负载均衡的。
首先,我们回顾下之前我们的案例,实现负载均衡的时候,使用了一个注解@LoadBalanced,这个之前我们也没有接触过。因为我们通过该注解为入口来了解下Spring Cloud Ribbon的源码实现。
从@LoadBalanced注解源码的注释中可以知道,该注解用来给RestTemplate做标记,以使用负载均衡的客户端(LoadBalancerClient)来配置它。
负载均衡器
通过之前分析,我们对Spring Cloud如何使用Ribbon有了基本了解。虽然Spring Cloud中定义了LoadBalancerClient作为负载均衡器的通过接口,并且针对Ribbon实现了RibbonLoadBalancer,但是它在具体实现负载均衡策略时,是通过Ribbon的IloadBalancer接口实现的。下面来了解下IloadBalancer接口是如何实现负载均衡的。
AbstractLoadBalancer
BaseLoadBalancer
DynamicServerListLoadBalancer
ZoneAwareLoadBalancer
负载均衡策略
RandomRule-随机选择策略
RoundRobinRule-线性轮询策略
RetryRule-重试机制策略
WeightedResponseTimeRule-权重策略
ClientConfigEnablrdRoundRobinRule
还有很多策略就不记录了。