0%

SpringCloud-Ribbon-配置及详解

Ribbon 介绍

Ribbon 是一个客户端的负载均衡解决方案实现。它提供了我们很多已经实现好的负载方案,我们可以直接拿来用,或者自定义自己的负载均衡规则。Ribbon客户端在启动的时候会从Eureka Server端获取它需要调用服务的列表,并且做缓存,所以在Ribbon客户端启动以后,即使Eureka服务出现问题或者停掉,只要调用的服务没有问题,还是可以保证客户端的正常调用,这样做主要是为了保证CAP中的Availability。

Ribbon 配置

这里我们为了演示轮询的负载均衡方案,我们需要启动两个服务的provider,设置不同的端口,下面我们通过 Active profiles 来启动服务,配置如下:

application-7011.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
pring:
application:
name: provider-service

server:
port: 7011

eureka:
client:
register-with-eureka: true
fetch-registry: true
service-url:
defaultZone: http://eureka01:7001/eureka/,http://eureka02:7002/eureka/,http://eureka03:7003/eureka/

application-7012.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
spring:
application:
name: provider-service

server:
port: 7012

eureka:
client:
register-with-eureka: true
fetch-registry: true
service-url:
defaultZone: http://eureka01:7001/eureka/,http://eureka02:7002/eureka/,http://eureka03:7003/eureka/

在启动Application类中添加注解 @EnableDiscoveryClient,然后我们添加一个测试的Controllers类,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@RestController
public class RibbonTest {

@Autowired
ApplicationContext applicationContext;

@RequestMapping(value = "/provider/ribbon/printLog", method = RequestMethod.GET)
public String printLog() throws UnknownHostException {
String IPAddress = InetAddress.getLocalHost().getHostAddress();
String port = applicationContext.getEnvironment().getProperty("local.server.port");
return "Hello Provider ".concat(IPAddress).concat(":").concat(port);
}

}

至此,我们的provider service配置好了,接下来我们来配置 consumer service,首先我们需要在 pom.xml 添加 ribbon 依赖:
pom.xml

1
2
3
4
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>

application.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
spring:
application:
name: consumer-service

server:
port: 7021

eureka:
client:
register-with-eureka: true
fetch-registry: true
service-url:
defaultZone: http://eureka01:7001/eureka/,http://eureka02:7002/eureka/,http://eureka03:7003/eureka/

添加 Ribbon 的配置类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@Configuration
// 如果多个服务可以选择不同的策略
/*@RibbonClients({
@RibbonClient(name = "other",configuration = OtherConfig.class),
@RibbonClient(name = "provider",configuration = ProviderConfig.class)
})*/
@RibbonClient(name = "provider-service")
public class RibbonConfig {

//定义负载均衡规则
@Bean
public IRule ribbonRule(){
return new RoundRobinRule();
}

@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}

}

这里我们主要介绍一下 Irule:

  1. RoundRobinRule:轮询规则
  2. RandomRule:随机规则
  3. WeightedResponseTimeRule:使用响应时间的平均或者百分比为每个服务分配权重的规则,如果没法收集响应时间信息,会默认使用轮询规则
  4. BestAvailableRule:会先根据断路器过滤掉处于故障的服务,然后选择并发量最小的服务
  5. ZoneAvoidanceRule:根据server所在Zone和其性能,选择服务器,默认规则
  6. AvailabilityFilteringRule:先根据断路器规则过滤掉有问题的服务,然后对剩余的服务按照轮询的策略进行访问
  7. RetryRule:先按照RoundRobinRule规则进行服务获取,如果调用服务失败会在指定时间内进行重试,直到获取到可用的服务。

Consumer service的Controller演示类:

1
2
3
4
5
6
7
8
9
10
11
12
13
@RestController
public class RibbonTest {

@Autowired
private RestTemplate restTemplate;

@GetMapping(value = "/consumer/ribbon/printLog")
public String printProviderLog(){
String result = restTemplate.getForObject("http://provider-service/provider/ribbon/printLog", String.class);
return result;
}

}
演示Ribbon的轮询负载均衡

此时我们首先启动的的Eureka服务,然后通过Active Profiles启动两个不同端口的provider service,最后启动我们的consumer service,然后访问 http://localhost:7021/consumer/ribbon/printLog ,然后不断刷新,我们会看到端口7011和7012的不断变化。