教育行业A股IPO第一股(股票代码003032)
全国咨询/投诉热线:400-618-4000
因为微服务是目前互联网公司比较流行的架构,所以spring就提供了一个顶级框架-springcloud,来解决我们在开发微服务架构中遇到的各种各样的问题,今天的主角是springcloud框架中集成的组件Ribbon,那么Ribbon能解决什么问题呢,我们来思考下面的问题。
微服务架构中的每个服务为了高可用,很大程度上都会进行集群,我们假设现在集群了3个user服务,同时能提供相同的服务,问题来了,我们如何决定调用这3个user服务中的哪一个呢?
根据不同分析角度,会有不同的答案,也可以理解为根据不同的情况,我们可以写不同的算法,来决定到底此时此刻,调用这3个user服务的哪一个,那么,Ribbon就给我们提供了不同的算法,我们可以根据业务场景,调整配置文件,决定到底使用哪个算法,这样,算法中就会计算出调用哪个user服务了。
1)我们准备一个eureka注册中心
2)再准备一个order服务
3)再准备3个相同代码的user服务,这样,order服务通过eureka注册中心,就可以发现user的3个服务
Ribbon是通过IRule的这个接口来选择3个user服务中的哪个的,但是实际执行的代码肯定是继承了这个接口的实现类,所以选择不同的实现类,就会选择不同负载均衡策略
publicinterfaceIRule{Serverchoose(Objectvar1);voidsetLoadBalancer(ILoadBalancervar1);ILoadBalancergetLoadBalancer();}3.1.RoundRobinRule轮询策略此策略是Ribbon的默认策略,是按照顺序,依次对所有的user服务进行访问。
通过重写IRule的choose方法,来选择并返回决定调用的user服务,在下面的源码中,ListallServers=lb.getAllServers();获得了所有的3个user服务实例,intnextServerIndex=this.incrementAndGetModulo(serverCount);保存了当前调用的user实例的序号,然后就可以按照顺序调用下一个user服务了
publicServerchoose(ILoadBalancerlb,Objectkey){if(lb==null){log.warn("noloadbalancer");returnnull;}else{Serverserver=null;intcount=0;while(true){if(server==null&&count++<10){List
第一次访问:访问的是第一个实例
第二次访问:访问的是第二个实例
就和这个策略的名字一样,是对user的3个服务的随机调用,所以不存在规律,如下源码中intindex=this.chooseRandomInt(serverCount);通过随机数来选择下标,所以对user服务的调用是随机的
publicServerchoose(ILoadBalancerlb,Objectkey){if(lb==null){returnnull;}else{Serverserver=null;while(server==null){if(Thread.interrupted()){returnnull;}List
第二次访问:访问的还是第一个实例
第三次访问:访问的是第三个实例
extendsRoundRobinRulepublicServerchoose(ILoadBalancerlb,Objectkey){if(lb==null){returnnull;}else{Serverserver=null;while(server==null){List
前几次访问:maxTotalWeight都是0.0,使用轮询策略,但是开始缓存权重数据
30秒之后:开始根据权重数据来分配权重,选择实例
如下图:8081端口的权重显然没有8082的权重大,所以8082端口的user服务实例被访问的次数多
重试策略是指通过轮询策略选出一个实例,然后去访问,如果此实例为null或者已经失效,那么会重试其他的实例,answer=this.subRule.choose(key);会根据轮询策略选择一个实例,然后if((answer==null||!answer.isAlive())&&System.currentTimeMillis() publicServerchoose(ILoadBalancerlb,Objectkey){longrequestTime=System.currentTimeMillis();longdeadline=requestTime+this.maxRetryMillis;Serveranswer=null;answer=this.subRule.choose(key);if((answer==null||!answer.isAlive())&&System.currentTimeMillis() 会根据每个服务实例的并发数量来决定,访问并发数最少的那个服务,intconcurrentConnections=serverStats.getActiveRequestsCount(currentTime);会获得当前遍历的实例的并发数,然后和其他的实例的并发数进行判断,最终访问并发量最少的那个实例 publicServerchoose(Objectkey){if(this.loadBalancerStats==null){returnsuper.choose(key);}else{List publicServerchoose(Objectkey){intcount=0;for(Serverserver=this.roundRobinRule.choose(key);count++<=10;server=this.roundRobinRule.choose(key)){//通过predicate来过滤if(this.predicate.apply(newPredicateKey(server))){returnserver;}}//过滤掉一些服务之后,会采用轮询的方式调用剩下的服务returnsuper.choose(key);}3.7.ClientConfigEnabledRoundRobinRule自定义策略此策略本身并没有实现什么特殊的处理逻辑,但是可以通过重置LoadBalancer来达到自定义一些高级策略的目的,可以重写initWithNiwsConfig和setLoadBalancer