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

Ribbon简介

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

架构图


为服务消费者整合Ribbon

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

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

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

public static void main(String[] args) {
SpringApplication.run(ConsumerMovieRibbonApplication.class, args);
}
  1. 创建 Controller:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
@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,返回结果:
1
2
3
4
5
6
7
8
9
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配置类:
1
2
3
4
5
6
7
8
@Configuration
public class RibbonConfiguration {
@Bean
public IRule ribbonRule() {
// 负载均衡改为随机
return new RandomRule();
}
}
  1. 创建空类:
1
2
3
4
5
@Configuration
@RibbonClient(name = "microservice-provider-user",configuration = RibbonConfiguration.class)
public class TestConfiguration {

}
  1. 多次访问http://127.0.0.1:8010/log-user-instance,返回结果:
1
2
3
4
5
6
7
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注解提供默认配置:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
@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的实现类。

指定名称配置

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

全局配置

1
2
ribbon:
NFLoadBalancerClassName: com.netflix.loadbalancer.RandomRule

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

以上

LeoQin wechat
欢迎您扫一扫上面的微信公众号,订阅我的博客!
0%