一:Ribbon简介Ribbon是Netflix公司开源的一个负载均衡的项目,是一个客户端负载均衡器,运行在客户端上 。它是一个经过了云端测试的IPC库,可以很好地控制HTTP和TCP客户端的一些行为 。Feign已经默认使用了Ribbon 。
二:Ribbon的工作流程
文章插图
1:user微服务1、user微服务2、user微服务3是一个服务集群,它们都会向注册中心注册服务(它们的应用名都是USER-SERVICE)
2:注册中心记录集群元数据信息,即USER-SERVICE下有3个服务节点
3:Ribbon拦截所有的请求,从请求信息中获取应用名
4:ribbon根据应用名从eureka注册中心获取服务列表
5:ribbon从服务列表中通过相关均衡策略获取具体某个服务
6:请求远程服务
三:Ribbon源码解析第一步:Ribbon拦截请求,获取应用名LoadBalancerAutoConfiguration是Ribbon的自动配置类,在这个配置类里面配置了一个拦截器,该拦截器会拦截所有请求,这就是Ribbon的入口
文章插图
LoadBalancerInterceptor的intercept方法(当远程调用的时候都会被拦截器拦截)
@Overridepublic ClientHttpResponse intercept(final HttpRequest request, final byte[] body,final ClientHttpRequestExecution execution) throws IOException {final URI originalUri = request.getURI();String serviceName = originalUri.getHost();//这里就是获取应用名可以打断点测试Assert.state(serviceName != null, "Request URI does not contain a valid hostname: " + originalUri);return this.loadBalancer.execute(serviceName, requestFactory.createRequest(request, body, execution));}
第二步:通过应用名获取服务列表负载均衡器ZoneAwareLoadBalancer是获取服务列表的重要组件@Overridepublic <T> T execute(String serviceId, LoadBalancerRequest<T> request) throws IOException {ILoadBalancer loadBalancer = getLoadBalancer(serviceId);//获取负载均衡器Server server = getServer(loadBalancer);if (server == null) {throw new IllegalStateException("No instances available for " + serviceId);}RibbonServer ribbonServer = new RibbonServer(serviceId, server, isSecure(server,serviceId), serverIntrospector(serviceId).getMetadata(server));return execute(serviceId, ribbonServer, request);}
ILoadBalancer是一个接口,具体的实现类是ZoneAwareLoadBalancer// Source code recreated from a .class file by IntelliJ IDEA// (powered by Fernflower decompiler)//package com.netflix.loadbalancer;import JAVA.util.List;public interface ILoadBalancer {void addServers(List<Server> var1);//从列表中获取具体某个服务Server chooseServer(Object var1);void markServerDown(Server var1);/** @deprecated */@DeprecatedList<Server> getServerList(boolean var1);List<Server> getReachableServers();//获取服务列表List<Server> getAllServers();}
ZoneAwareLoadBalancer负载均衡器是在RibbonClientConfiguration中提前定义的@Bean@ConditionalOnMissingBeanpublic ILoadBalancer ribbonLoadBalancer(IClientConfig config, ServerList<Server> serverList, ServerListFilter<Server> serverListFilter, IRule rule, IPing ping, ServerListUpdater serverListUpdater) {return (ILoadBalancer)(this.propertiesFactory.isSet(ILoadBalancer.class, this.name) ?(ILoadBalancer)this.propertiesFactory.get(ILoadBalancer.class, config, this.name) :new ZoneAwareLoadBalancer(config, rule, ping, serverList, serverListFilter, serverListUpdater));}
ZoneAwareLoadBalancer的继承关系图如下:文章插图
getAllServers获取服务列表,ZoneAwareLoadBalancer没有定义getAllServers方法,但是父类BaseLoadBalancer定义了该方法
第三步:从列表中获取具体服务ZoneAwareLoadBalancer定义了获取服务的方法,但是该方法最终调用的是父类BaseLoadBalancer chooseServer方法
public Server chooseServer(Object key) {if (counter == null) {counter = createCounter();}counter.increment();if (rule == null) {return null;} else {try {return rule.choose(key);} catch (Exception e) {logger.warn("LoadBalancer [{}]:Error choosing server for key {}", name, key, e);return null;}}}
默认均衡策略ZoneAvoidanceRule,在RibbonClientConfiguration配置类中配置了IRule bean文章插图
均衡策略的接口是IRule,具体实现类有10个:
文章插图
IRule这是所有负载均衡策略的父接口,里边的核心方法就是choose方法,用来选择一个服务实例 。
推荐阅读
- 超简单本地备份服务器搭建攻略
- 花了17年!微软修复Windows DNS服务器漏洞
- |老实人,掌握这三个核心技能,拥有安身立命之本,不会被领导淘汰
- 微博|还有两个月退休,我该什么时候向领导提出交接工作?
- 对DBA、开发、测试、产品同时友好 大规模多存储场景的数据库选型与服务平台建设
- 福建名茶白牡丹茶,属微发酵茶
- 微软|七年前老问题卷土重来!Win11再现0xc1900101更新失败报错
- 现代服务业包括哪些行业?
- linux下多线程与并发服务器设计方案及常见问题
- kali linux之应用层Dos