使用 Ribbon 实现客户端负载均衡

使用 Ribbon 实现客户端负载均衡

前言

在前文《使用Eureka提供服务注册与发现》https://mp.weixin.qq.com/s/L2Tx6Lk0jl6GW-g0SeUXyw 中,通过基于 Eureka 实现服务注册与发现。一般来说,在生产环境中,各个微服务都会部署多个实例,那么服务消费者要如何将请求分摊到多个服务提供者实例上呢?

在 Spring Cloud 中,当 Ribbon 和 Eureka 配合使用时,Ribbon 可自动从 Eureka Server 获取服务提供者地址列表,并基于负载均衡算法,请求其中一个服务提供者实例。

Ribbon 简介

Ribbon 是 Netflix 发布的负载均衡器,它有助于控制 HTTP 和 TCP 客户端的行为。为 Ribbon 配置服务提供者地址列表后, Ribbon 就可基于某种负载均衡算法,自动地帮助服务消费者去请求。 Ribbon 默认为我们提供了很多的负载均衡算法,例如轮询、随机等。当然,我们也可为 Ribbon 实现自定义的负载均衡算法。

6.Eureka与Ribbon配合使用架构图

为服务消费者整合 Ribbon

  1. 创建项目,复制项目 micro-consumer-movie ,将 artifactId 修改为 micro-consumer-movie-ribbon 。

  2. 为项目引入 Ribbon 的依赖,spring-cloud-starter-eureka 默认包含了 Ribbon 的依赖 spring-cloud-starter-ribbon 。

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
  1. 为 RestTemplate 添加 @LoadBalance 注解,就可为 RestTemplate 整合 Ribbon ,使其具备负载均衡的能力。
@Configuration
public class RestConfig {
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
}
  1. 启动 Eureka Server 注册中心 和 多个服务提供者 micro-provider-user 。
java -jar micro-discovery-eureka-0.0.1-SNAPSHOT.jar

java -jar micro-provider-user-0.0.1-SNAPSHOT.jar --spring.profiles.active=peer1
java -jar micro-provider-user-0.0.1-SNAPSHOT.jar --spring.profiles.active=peer2
  1. 修改服务消费者调用服务提供者的请求地址,http://localhost:8000/ 改为 http://micro-provider-user/ 。
@RestController
@RequestMapping("/movie/v1")
public class MovieController {
    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Resource
    private RestTemplate restTemplate;
    @Resource
    private LoadBalancerClient loadBalancerClient;

    @GetMapping("/{id}")
    public User findById(@PathVariable Long id){
        User entity = restTemplate.getForObject("http://micro-provider-user/user/v1/"+id, User.class);
        return entity;
    }

    @GetMapping("/log-instance")
    public void logUserInstance(){
        ServiceInstance serviceInstance = loadBalancerClient.choose("micro-provider-user");
        logger.info("{}:{}:{}", serviceInstance.getServiceId(), serviceInstance.getHost(), serviceInstance.getPort());
    }
}

micro-provider-user 是用户微服务的虚拟主机名(virtual host name),当 Ribbon 和 Eureka 配合使用时,会自动将虚拟主机名映射成微服务的网络地址。

在默认情况下,虚拟主机名和服务名称是一致的。当然,也可使用配置属性 eureka.instance.virtual-host-name 或 eureka.instance.secure-virtual-host-name 指定虚拟主机名。

  1. 启动服务消费者服务 micro-consumer-movie-ribbon ,测试 Ribbon ,多次访问 http://localhost:8010/movie/v1/1 ,可发现请求会均匀分布到两个用户微服务节点上,说明已经实现了负载均衡。

访问 http://localhost:8010/movie/v1/log-instance , logUserInstance() 方法中使用 LoadBalancerClient 的 API 更加直观地获取当前选择的用户微服务节点。

使用属性自定义 Ribbon 配置

Ribbon 支持使用属性自定义,支持的属性如下:

  • NFLoadBalancerClassName :配置 ILoadBalancer 的实现类
  • NFLoadBalancerRuleClassName :配置 IRule 的实现类。
  • NFLoadBalancerPingClassName :配置 IPing 的实现类。
  • NIWSServerListClassName :配置 ServerList 的实现类。
  • NIWSServerListFilterClassName :配置ServerListFilter 的实现类。

实践:通过属性来修改 Ribbon Client 的负载均衡规则。

  1. 复制项目 micro-consumer-movie-ribbon ,将 ArtifactId 修改为 micro-consumer-movie-ribbon-custom-props 。

  2. 修改 application.yml ,将名为 micro-provider-user 的 Ribbon Client 的负载均衡规则设为随机:

micro-provider-user:
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
  1. 启动服务 micro-consumer-movie-ribbon-custom-props ,测试 http://localhost:8010/movie/v1/log-instance ,查看日志,会发现此时请求会随机分布到两个用户微服务节点上。

脱离 Eureka 使用 Ribbon

现实中某些微服务可能并没有注册到 Eureka Server 上 ,此时要想使用 Ribbon 实现负载均衡,要怎么办呢?

7.脱离 Eureka 使用 Ribbon 架构图

  1. 复制项目 micro-consumer-movie-ribbon ,将 ArtifactId 修改为 micro-consumer-movie-ribbon-without-eureka 。

  2. 删除 eureka 的依赖 spring-cloud-starter-eureka ,并为项目添加 Ribbon 依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-ribbon</artifactId>
</dependency>
  1. 去掉启动类上的 @EnableDiscoveryClient 注解。

  2. 修改配置 application.yml ,为 micro-provider-user 设置 Ribbon 客户端设置请求的地址列表:

server:
  port: 8010

spring:
  application:
    name: micro-consumer-movie

micro-provider-user:
  ribbon:
    listOfServers: localhost:8000,localhost:8001
  1. 启动多个服务提供者 micro-provider-user 。
java -jar micro-provider-user-0.0.1-SNAPSHOT.jar --spring.profiles.active=peer1
java -jar micro-provider-user-0.0.1-SNAPSHOT.jar --spring.profiles.active=peer2
  1. 启动服务 micro-consumer-movie-ribbon-without-eureka ,测试 http://localhost:8010/movie/v1/2 或 http://localhost:8010/movie/v1/log-instance 。

由结果可知,尽管电影微服务和用户微服务此时并没有注册到 Eureka 上, Ribbon 仍可正常工作,请求依旧会分摊到两个用户微服务节点上。

饥饿加载

Spring Cloud 会为每个名称的 Ribbon Client 维护一个子应用程序上下文,这个上下文默认是懒加载的。指定名称的 Ribbon Client 第一次请求时,对应的上下文才会被加载,因此,首次请求往往会比较慢。

从 Spring Cloud Dalston 开始,我们可配置饥饿加载。例如

ribbon:
  eager-load:
    enabled: true
    clients: client1,client2

这样,对于名为 client1 , clent2 的 Ribbon Client ,将在启动时就加载对应的子应用程序上下文,从 而提高首次请求的访问速度。

代码仓库

https://gitee.com/chentian114/spring-cloud-practice

公众号

知行chen

参考

《Spring Cloud 与Docker 微服务架构实战》 周立

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值