/*
*
* Copyright 2013 Netflix, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/importcom.netflix.loadbalancer.AbstractLoadBalancerRule;importcom.netflix.loadbalancer.BaseLoadBalancer;importcom.netflix.loadbalancer.ILoadBalancer;importcom.netflix.loadbalancer.Server;importkl.cds.utils.PingUtil;importorg.slf4j.Logger;importorg.slf4j.LoggerFactory;importjava.util.List;importjava.util.concurrent.atomic.AtomicInteger;/**
* Ribbon的负载策略,单独使用时都不太好,自定义负载策略
* The most well known and basic load balancing strategy, i.e. Round Robin Rule.
*
* @author stonse
* @author Nikos Michalakis <nikos@netflix.com>
*
*/publicclassCommonRoundRobinRuleextendsAbstractLoadBalancerRule{privateAtomicInteger nextServerCyclicCounter;privatePingUtil pingUtil =newPingUtil();privatestaticLogger log =LoggerFactory.getLogger(CommonRoundRobinRule.class);publicCommonRoundRobinRule(){
nextServerCyclicCounter =newAtomicInteger(0);}publicCommonRoundRobinRule(ILoadBalancer lb){this();setLoadBalancer(lb);}publicServerchoose(String key,BaseLoadBalancer lb){if(lb ==null){
log.warn("no load balancer");returnnull;}Server server =null;int count =0;List<Server> reachableServers = lb.getReachableServers();List<Server> allServers = lb.getAllServers();if((reachableServers.size()==0)||(allServers.size()==0)){
log.warn("No up servers available from load balancer: "+ lb);returnnull;}
pingUtil.setKey(key);
server =getAliveServer(allServers, count);if(server ==null){
log.warn("No available alive servers");returnnull;}else{return server;}}/**
* Inspired by the implementation of {@link AtomicInteger#incrementAndGet()}.
*
* @param modulo The modulo to bound the value of the counter.
* @return The next value.
*/privateintincrementAndGetModulo(int modulo){for(;;){int current = nextServerCyclicCounter.get();int next =(current +1)% modulo;if(nextServerCyclicCounter.compareAndSet(current, next)){return next;}}}@OverridepublicServerchoose(Object key){returnchoose(key.toString(),(BaseLoadBalancer)getLoadBalancer());}/**
* 获得可用服务
* @param allServers
* @return
*/privateServergetAliveServer(List<Server> allServers,int count){// 当查询超过可用服务列表数量还没有可用服务时返回nullif(count > allServers.size()){
log.warn("No available alive servers");returnnull;}int nextServerIndex =incrementAndGetModulo(allServers.size());// 通过cas获取可用服务地址boolean alive;Server server;try{
server = allServers.get(nextServerIndex);}catch(Exception e){
nextServerIndex =incrementAndGetModulo(allServers.size());
server = allServers.get(nextServerIndex);}long start =System.currentTimeMillis();
alive = pingUtil.isTelnetAlive(server);long end =System.currentTimeMillis();System.out.println("telnet: "+(end-start));// 服务可用返回服务,不可用查找下一个可用服务if(alive){return server;}else{
count++;returngetAliveServer(allServers, count);}}}