Spring Cloud Ribbon实现客户端负载均衡
一、负载均衡
Spring Cloud Ribbon 是一个基于 Http 和 TCP 的客户端负载均衡工具 ,Ribbon 主要解决集群服务中,多个服务高效率访问的问题。
负载均衡在系统架构中是一个非常重要,并且是不得不去实施的内容。因为负载均衡是对系统的高可用、网络压力的缓解和处理能力扩容的重要手段之一。
客户端与服务端级别的负载均衡
- 服务器端负载均衡:例如 Nginx,通过 Nginx 进行负载均衡过程如下:先发送请求给 nginx 服务器,然后通过负载均衡算法,在多个业务服务器之间选择一个进行访问;即在服务器端再进行负载均衡算法分配。
- 客户端负载均衡:客户端会有一个服务器地址列表,在发送请求前通过负载均衡算法选择一个服务器,然后进行访问,即在客户端就进行负载均衡算法分配。
服务端负载均衡
负载均衡是微服务架构中必须使用的技术,通过负载均衡来实现系统的高可用、集群扩容等功能。负载均衡可通过硬件设备及软件来实现,硬件比如:F5、Array 等,软件比如:LVS、Nginx 等。
客户端负载均衡
客户端负载均衡与服务端负载均衡的区别在于客户端要维护一份服务列表,Ribbon 从 Eureka Server 获取服务列表,Ribbon 根据负载均衡算法直接请求到具体的微服务,中间省去了负载均衡服务。
二、Ribbon
Ribbon 是 Netflix 发布的负载均衡器,有助于控制 HTTP 客户端行为。为 Ribbon 配置服务提供者地址列表后,Ribbon 就可基于负载均衡算法,自动帮助服务消费者请求。
Ribbon 默认提供的负载均衡算法
- 轮询(默认)
- 随机算法
- 重试算法
- 加权法
1 | #指定eureka服务地址 |
1、负载均衡源码跟踪探究
为什么只输入了Service
名称就可以访问了呢?不应该需要获取 ip 和端口吗?
负载均衡器动态的从服务注册中心中获取服务提供者的访问地址(host、port)
显然是有某个组件根据Service
名称,获取了服务实例 ip 和端口。就是LoadBalancerInterceptor
这个类会对 RestTemplate
的请求进行拦截,然后从Eureka
根据服务 id 获取服务列表,随后利用负载均衡算法得到真正服务地址信息,替换服务 id。
2、结论
- Ribbon 的负载均衡算法应用在客户端(Http 请求),只需要提供服务列表,就能帮助消费端自动访问服务端,并通过不同算法实现负载均衡。
- Ribbon 的轮询、随机算法配置:在
application.yml
中配置{服务名称}.ribbon.NFLoadBalancerRuleClassName
- 负载均衡的切换:在
LoadBalancerInterceptor
中获取服务的名字,通过调用RibbonLoadBalancerClient
的execute
方法,并获取ILoadBalancer
负载均衡器,然后根据ILoadBalancer
负载均衡器查询出要使用的节点,再获取节点的信息,并实现调用。
三、实现
Eureka 已经集成 Ribbon,所以无需引入依赖,要想使用 Ribbon,直接在 RestTemplate 的配置方法上添加@LoadBalanced
注解即可
1、修改user-consumer
的com.atguigu.UserConsumerApplication
启动类,在restTemplate()
方法上添加@LoadBalanced
注解
1 |
|
2、采用服务名访问配置
修改user-consumer
的UserController
的调用方式,不再手动获取 ip 和端口,而是直接通过服务名称调用
1 |
|
四、负载均衡原理
在 RestTemplate 中只需要给RestTemplate
实例上添加一个@LoadBalanced
注解,estTemplate 就会自动具备负载均衡功能。
这个功能的实现大致分三步:
- 从 Eureka Client 本地缓存的服务注册信息中,选择一个可调用的服务
- 根据 1 中选择的服务,重构请求 URL 地址
- 将 1、2 步的功能嵌入到 RestTemplate 中