1. 能干啥?
官方说法:Spring Cloud Ribbon 是 基于 Netflix Ribbon 实现的一套客户端的负载均衡工具,Ribbon 客户端组件提供一系列的完善的配置,如超时,重试等。通过 Load Balancer(LB)获取到服务提供的所有机器实例,Ribbon 会自动基于某种规则(轮询,随机)去调用这些服务。Ribbon 也可以实现我们自己的负载均衡算法;
个人简述:用户的一个请求,多个服务可以处理,以下问题的解决;
选择哪一个服务进行处理;
如果高效使用所服务资源;
怎样保证响应速度;
2. 怎么玩?
2.1 项目搭建
spring-boot 项目初始化
2.2 引入ribbon
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
<version>2.1.3.RELEASE</version>
</dependency>
复制代码
2.3 配置
这里为了简单,不采用注册中心形式
server.port=18090
eat.ribbon.eureka.enabled=false
eat.ribbon.listOfServers=http://localhost:18091,http://localhost:18092
复制代码
注: http://localhost:18091 ,http://localhost:18092 服务可以自行创建,也可以直接使用参见中的源码项目
eat 服务的负载均衡代码
核心配置:@LoadBalanced
@Configuration
public class RibbonConfig {
@LoadBalanced
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
复制代码
controller 使用
@RestController
@RequestMapping("/eat")
public class EatController {
@Autowired
private RestTemplate restTemplate;
@PostMapping("/fruit1")
public String eatFruit(){
return restTemplate.postForObject("http://eat/eat/fruit",null,String.class);
}
}
复制代码
注:restTemplate 使用规则:http:// {请求uri}
2.4 使用
访问: localhost:18090/eat/fruit1
I eat fruit on 18091
I eat fruit on 18092
交替出现,默认区域负载均衡策略生效;
2.5 修改默认负载均衡策略
自定义策略:一台机器执行5次后,下一台开始执行5次,依次轮询;
继承AbstractLoadBalancerRule实现自定义规则
public class YiRule extends AbstractLoadBalancerRule {
/** 总共被调用的次数,目前要求每台被调用5次 */
private int total = 0;
/** 当前提供服务的机器号 */
private int currentIndex = 0;
public Server choose(ILoadBalancer lb, Object key) {
if (lb == null) {
return null;
}
Server server = null;
while (server == null) {
if (Thread.interrupted()) {
return null;
}
//激活可用的服务
List<Server> upList = lb.getReachableServers();
if (total < 5) {
server = upList.get(currentIndex);
total++;
} else {
total = 0;
currentIndex++;
if (currentIndex >= upList.size()) {
currentIndex = 0;
}
}
if (server == null) {
Thread.yield();
continue;
}
if (server.isAlive()) {
return (server);
}
// Shouldn't actually happen.. but must be transient or a bug.
server = null;
Thread.yield();
}
return server;
}
@Override
public void initWithNiwsConfig(IClientConfig clientConfig) {
}
@Override
public Server choose(Object key) {
return choose(getLoadBalancer(), key);
}
}
复制代码
仅对eat 服务配置此规则
@RibbonClient(name = "eat",configuration = YiRule.class)
@SpringBootApplication
public class YiyiRibbonConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(YiyiRibbonConsumerApplication.class, args);
}
}
复制代码
可以自行debug 查看是否走自定义策略;
3. 分析原理
分析ribbon原理,铁定是要看源码的,这里我们从两个角度去看;
请求链路流转
从这个角度看,我们debug 即可;
debug 目的:
1) 找到两个服务是何时加载的;
2) 哪个地方将 eat 服务替换成了 服务示例 localhost:1808x;
ribbon配置加载
LoadBalancerAutoConfiguration
spring-cloud 中的负载均衡扩展配置 ;
RibbonAutoConfiguration
ribbon 核心配置加载;
配置+时序图
下图展示了请求时序图,结合配置我们可以看出:
ribbon 是 spring-cloud-common 提供的 LoadbalancerClient 上的实现,即LoadbalancerClient是ribbon 的入口,后续的处理就是ribbon 的个性实现;