二、微服务客户端负载均衡之Ribbon


Ribbon简介

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

架构图


为服务消费者整合Ribbon

  1. 启动一个Eureka注册中心,启动两个Eureka服务提供者(参考传送门);

  2. 创建服务消费者,在pom文件中添加依赖:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
  1. 创建启动类:
// 添加注解,使其具备负载均衡能力
@LoadBalanced
@Bean
public RestTemplate restTemplate() {
    return new RestTemplate();
}

public static void main(String[] args) {
    SpringApplication.run(ConsumerMovieRibbonApplication.class, args);
}
  1. 创建 Controller:
@RestController
public class MovieRibbonController {

    private static final Logger LOGGER = LoggerFactory.getLogger(MovieRibbonController.class);

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private LoadBalancerClient loadBalancerClient;


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

    @GetMapping("/log-user-instance")
    public void logUserInstance() {
        ServiceInstance serviceInstance = this.loadBalancerClient.choose("microservice-provider-user");
        // 打印当前节点
        MovieRibbonController.LOGGER.info(
                "{}:{}:{}",
                serviceInstance.getServiceId(),
                serviceInstance.getHost(),
                serviceInstance.getPort());
    }
}
  1. 多次访问http://127.0.0.1:8010/log-user-instance,返回结果:
INFO 11146 --- [nio-8010-exec-2] c.itmuch.consumer.MovieRibbonController  : microservice-provider-user:192.168.200.104:9000
INFO 11146 --- [nio-8010-exec-4] c.itmuch.consumer.MovieRibbonController  : microservice-provider-user:192.168.200.104:9001
INFO 11146 --- [nio-8010-exec-6] c.itmuch.consumer.MovieRibbonController  : microservice-provider-user:192.168.200.104:9000
INFO 11146 --- [nio-8010-exec-8] c.itmuch.consumer.MovieRibbonController  : microservice-provider-user:192.168.200.104:9001
INFO 11146 --- [io-8010-exec-10] c.itmuch.consumer.MovieRibbonController  : microservice-provider-user:192.168.200.104:9000
INFO 11146 --- [nio-8010-exec-2] c.itmuch.consumer.MovieRibbonController  : microservice-provider-user:192.168.200.104:9001
INFO 11146 --- [nio-8010-exec-4] c.itmuch.consumer.MovieRibbonController  : microservice-provider-user:192.168.200.104:9000
INFO 11146 --- [nio-8010-exec-7] c.itmuch.consumer.MovieRibbonController  : microservice-provider-user:192.168.200.104:9001
INFO 11146 --- [nio-8010-exec-9] c.itmuch.consumer.MovieRibbonController  : microservice-provider-user:192.168.200.104:9000
  • 可以看到,请求会均匀分布到两个微服务节点上。
  • 不能将restTemplate.getForObject(...)loadBalancerClient.choose(...)写在一个方法中,两者会有冲突——restTemplate实际上是一个Ribbon客户端,本身包含choose的行为。

Ribbon自定义配置

指定名称配置
  1. 创建Ribbon配置类:
@Configuration
public class RibbonConfiguration {
    @Bean
    public IRule ribbonRule() {
        // 负载均衡改为随机
        return new RandomRule();
    }
}
  1. 创建空类:
@Configuration
@RibbonClient(name = "microservice-provider-user",configuration = RibbonConfiguration.class)
public class TestConfiguration {

}
  1. 多次访问http://127.0.0.1:8010/log-user-instance,返回结果:
INFO 11193 --- [nio-8010-exec-1] c.itmuch.consumer.MovieRibbonController  : microservice-provider-user:192.168.200.104:9000
INFO 11193 --- [nio-8010-exec-3] c.itmuch.consumer.MovieRibbonController  : microservice-provider-user:192.168.200.104:9000
INFO 11193 --- [nio-8010-exec-5] c.itmuch.consumer.MovieRibbonController  : microservice-provider-user:192.168.200.104:9001
INFO 11193 --- [nio-8010-exec-7] c.itmuch.consumer.MovieRibbonController  : microservice-provider-user:192.168.200.104:9000
INFO 11193 --- [nio-8010-exec-9] c.itmuch.consumer.MovieRibbonController  : microservice-provider-user:192.168.200.104:9001
INFO 11193 --- [nio-8010-exec-1] c.itmuch.consumer.MovieRibbonController  : microservice-provider-user:192.168.200.104:9000
INFO 11193 --- [nio-8010-exec-4] c.itmuch.consumer.MovieRibbonController  : microservice-provider-user:192.168.200.104:9001
全局配置
  • 可使用@RibbonClients注解提供默认配置:
@RibbonClients
public class RibbonClientDefaultConfigurationTestsConfig {
    public static class BazServiceList extends ConfigurationBasedServerList {
        public BazServiceList(IClientConfig config) {
            super.initWithNiwsConfig(config);
        }
    }
}

class DefaultRibbonConfig {
    @Bean
    public IRule ribbonRule() {
        return new BestAvailableRule();
    }

    @Bean
    public IPing ribbonPing() {
        return new PingUrl();
    }

    @Bean
    public ServerList<Server> ribbonServerList(IClientConfig config) {
        return new RibbonClientDefaultConfigurationTestsConfig.BazServiceList(config);
    }

    @Bean
    public ServerListSubsetFilter serverListFilter() {
        return new ServerListSubsetFilter();
    }
}
使用属性自定义Ribbon配置
  • NFLoadBalancerClassName: 配置ILoadBalancer的实现类。
  • NFLoadBalancerRuleClassName: 配置IRule的实现类。
  • NFLoadBalancerPingClassName: 配置IPing的实现类。
  • NIWSServerListClassName: 配置ServerList的实现类。
  • NIWSServerListFilterClassName: 配置ServerListFilter的实现类。

指定名称配置

microservice-provider-user:
  ribbon:
    NFLoadBalancerClassName: com.netflix.loadbalancer.RandomRule

全局配置

ribbon:
  NFLoadBalancerClassName: com.netflix.loadbalancer.RandomRule

该文章摘自《Spring Cloud 与 Docker 微服务架构实战(第二版)》

以上


文章作者: Qliang
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Qliang !
评论
 上一篇
三、微服务声明式REST调用之Feign 三、微服务声明式REST调用之Feign
Feign简介在负载均衡篇的示例中使用RestTemplate实现REST API调用: @GetMapping("/user/{id}") public User findById(@PathVariable Long id) {
2019-01-21
下一篇 
一、微服务注册与发现之Eureka 一、微服务注册与发现之Eureka
Eureka简介 Eureka是Netflix开源的服务发现组件,本身是一个基于 REST 的服务。包含Server和Client两部分。Spring Cloud将它集成在子项目Spring Cloud Netflix中,从而实现微服务的注
2019-01-15
  目录