Ribbon 是 Netflix 发布的负载均衡器,它有助于控制 HTTP 和 TCP 客户端的行为。为 Ribbon 配置服务提供者地址列表后,Ribbon 就可基于某种负载均衡算法,自动地帮助服务消费者去请求。Ribbon 默认为我们提供了很多的负载均衡算法,例如轮询、随机等。当然,我们也可为 Ribbon 实现自定义的负载均衡算法。Ribbon 现在已经进入维护状态,但目前仍在大规模使用,Spring Cloud 准备使用 LoadBalancer 作为 Ribbon 的替换方案。
因为现在的注册中心帮我们引入了 Ribbon 我们不需要再次引入就可以直接使用,当然也可以再引入一次没有影响。
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
开启负载均衡非常简单,只需要在 RestTemplate 的配置方法上加上 @LoadBalanced
注解即可使用最简单的轮询。
/**
* Created with IntelliJ IDEA.
*
* @author Demo_Null
* @date 2020/10/29
* @description 消费者启动类
*/
@SpringBootApplication
@EnableDiscoveryClient
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class, args);
}
@Bean
@LoadBalanced
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
}
/**
* Created with IntelliJ IDEA.
*
* @author Demo_Null
* @date 2020/10/29
* @description
*/
@RestController
@RequestMapping("/consumer")
public class ConsumerController {
@Autowired
private DiscoveryClient discoveryClient;
@Autowired
private RestTemplate restTemplate;
@GetMapping("/go")
public void go() {
List<ServiceInstance> providerServer = discoveryClient.getInstances("ProviderServer");
if (0 == providerServer.size()) {
return;
}
ServiceInstance serviceInstance = providerServer.get(0);
String url = serviceInstance.getUri() + "/provider/get";
System.out.println(url + " --- ");
String str = restTemplate.getForObject(url, String.class);
System.out.println(str);
}
}
喔嚯!报错了,明明可以访问到为什么会报找不到实例呢?这是应为咱们使用 DiscoveryClient 直接获取到了服务提供者集群中某一个的地址,然后让 RestTemplate 去进行负载均衡。我们都已经拿到了准确地址再怎么进行负载均衡?所以我们这里不能使用 IP 要使用服务名称。
@RestController
@RequestMapping("/consumer")
public class ConsumerController {
@Autowired
private RestTemplate restTemplate;
@GetMapping("/go")
public void go() {
String url = "http://ProviderServer/provider/get";
String str = restTemplate.getForObject(url, String.class);
System.out.println(str);
}
}
修改完毕之后就可以看到服务提供者是轮换进行提供服务的
策略名 | 策略描述 |
---|---|
RoundRobinRule | 轮询选择 server |
RandomRule | 随机选择一个 serve |
RetryRule | 先按轮询策略获取服务,如果获取服务失败则在指定时间内重试,获取可用服务 |
BestAvailableRule | 会先过滤由于多次访问故障而处于断路器跳闸状态的服务,然后选择一个并发量最小的服务 |
AvailabilityFilteringRule | 会优先过滤故障实例,再选择并发较小的实例 |
WeightedResponseTimeRule | 对轮询的扩展,响应速度越快的实例选择比重权越大,越容易被选择 |
ZoneAvoidanceRule | 复合判断 server 所在区域的性能和 server 的可用性选择 server |
官方文档明确警告,这个自定义配置类不能放在 @ComponedtScan 所扫描的当前包下以及子包下,否则我们自定义的这个配置类就会被所有的 Ribbon 客户端所共享。即在 Spring Boot 主程序扫描的包外定义配置类或在与 Spring Boot 主程序的同一级目录但在排除扫描。配置类创建完毕后为 Spring Boo 主程序添加 @RibbonClient 注解引入配置类,用 name 属性来指定调用的服务名称,configuration 属性指定自定义配置类
@Configuration
public class MyRibbonRule {
@Bean
public IRule ribbonRule() {
return new RandomRule();
}
}
@SpringBootApplication
@EnableDiscoveryClient
// 用 name 来指定调用的服务名称,configuration 指定自定义配置类
@RibbonClient(name = "ProviderServer", configuration = MyRibbonRule.class)
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class, args);
}
@Bean
@LoadBalanced
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
}
# 这种配置的优先级低于配置类
# 想要调用的服务名称,即服务提供者名称
ProviderServer:
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule