本文已参与「新人创作礼」活动,一起开启掘金创作之路。
定时判断服务器是否存活
负载均衡器里,就是ILoadBalancer里,有IRule负责负载均衡的规则,选择一个服务器;还有一个IPing负责定时ping每个服务器,判断其是否存活
ILoadBalancer balancer = new BaseLoadBalancer();
List<Server> serverList = Arrays.asList(8080, 8081).stream().map(port -> new Server(
"localhost", port)).collect(Collectors.toList());
balancer.addServers(serverList);
// http://localhost:8080/
// 每隔1秒去请求【http://localhost:8080/】地址
((BaseLoadBalancer) balancer).setPing(new PingUrl());
((BaseLoadBalancer) balancer).setPingInterval(1);
Thread.sleep(5000);
for (int i = 0; i < 10; i++) {
Server server = balancer.chooseServer(null);
log.info("server : {}", server);
}
可以自定义一个Ping组件,结合业务逻辑实现具体的服务器判活策略。
class MyPing implements IPing{
@Override
public boolean isAlive(Server server) {
return false;
}
}
spring cloud netflix ribbon的使用以及工作原理
在一个服务里调用另外一个服务。
@LoadBalanced
@Bean
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
用RestTemplate来访问别的服务,RestTemplate,就是一个http请求的组件,本身没有负载均衡的功能。用@LoadBalanced注解之后,默认底层会用ribbon实现负载均衡。
RestTemplate底层会去基于ribbon来对一个服务的服务实例列表(List<Server>)进行负载均衡式的访问。ribbon和eureka整合,在ribbon里,从eureka client拿到服务实例列表(List<Server>)
请求一个服务的时候,就找服务对应的服务实例列表(List<Server>),round robin轮询一下
装配自定义的IRule和IPing
@Configuration
public class RibbonConfigForServiceB {
@Bean
public IRule iRuleForServiceB(){
return new IRule() {
@Override
public Server choose(Object o) {
return null;
}
@Override
public void setLoadBalancer(ILoadBalancer iLoadBalancer) {
}
@Override
public ILoadBalancer getLoadBalancer() {
return null;
}
};
}
@Bean
public IPing iPingForServiceB(){
return new IPing() {
@Override
public boolean isAlive(Server server) {
return false;
}
};
}
}
@RibbonClient(value = "ServiceB", configuration = RibbonConfigForServiceB.class)
public class RibbonClientForServiceB {
}
Ribbon 源码流程图
RestTemplate请求:http://ServiceA/product。
ServiceA是一个服务名称,不是ip地址和主机名,也没有端口号,RestTemplate无法请求。
ILoadBalancer里面包含IRule和IPing。
IRule负责从server list中根据负载均衡的算法,选择出来某个server。
IPing定时发送请求获取服务实例的状态。
服务实例通过Eureka模块获取,通过IRule策略选择确定的服务实例供服务调用者使用。
Ribbon源码 - @LoadBalanced
@LoadBalanced
将RestTemplate标志为底层采用LoadBalancerClient来执行实际的http请求,支持负载均衡。
根据@LoadBalanced 所在jar包的META-INF/spring.factories文件的自动配置机制找到LoadBalancerAutoConfiguration.class
restTemplates
@LoadBalanced
@Autowired(required = false)
private List<RestTemplate> restTemplates = Collections.emptyList();
SmartInitializingSingleton
SmartInitializingSingleton.afterSingletonsInstantiated()方法,就是在系统启动的时候,在spring singleton bean实例化完之后执行的。
遍历容器内所有的RestTemplate,用所有的Customizer定制所有的RestTemplate
public interface SmartInitializingSingleton {
void afterSingletonsInstantiated();
}
RestTemplateCustomizer
为RestTemplate设置了一个拦截器。
@Bean
@ConditionalOnMissingBean
public RestTemplateCustomizer restTemplateCustomizer(
final LoadBalancerInterceptor loadBalancerInterceptor) {
return restTemplate -> {
List<ClientHttpRequestInterceptor> list = new ArrayList<>(
restTemplate.getInterceptors());
list.add(loadBalancerInterceptor);
restTemplate.setInterceptors(list);
};
}
LoadBalancerInterceptor
@Bean
public LoadBalancerInterceptor ribbonInterceptor(
LoadBalancerClient loadBalancerClient,
LoadBalancerRequestFactory requestFactory) {
return new LoadBalancerInterceptor(loadBalancerClient, requestFactory);
}
ClientHttpRequestInterceptor拦截器
LoadBalancerInterceptor implements ClientHttpRequestInterceptor