/*
* Copyright 2009-2016 Weibo, 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.
*/package com.weibo.api.motan.cluster.loadbalance;import java.util.List;import java.util.concurrent.ThreadLocalRandom;import com.weibo.api.motan.core.extension.SpiMeta;import com.weibo.api.motan.rpc.Referer;import com.weibo.api.motan.rpc.Request;/**
*
* random load balance.
*
* @author fishermen
* @version V1.0 created at: 2013-5-21
*/@SpiMeta(name ="random")publicclassRandomLoadBalance<T>extendsAbstractLoadBalance<T>{@Overrideprotected Referer<T>doSelect(Request request){
List<Referer<T>> referers =getReferers();int idx =(int)(ThreadLocalRandom.current().nextDouble()* referers.size());for(int i =0; i < referers.size(); i++){
Referer<T> ref = referers.get((i + idx)% referers.size());if(ref.isAvailable()){return ref;}}return null;}@OverrideprotectedvoiddoSelectToHolder(Request request, List<Referer<T>> refersHolder){
List<Referer<T>> referers =getReferers();int idx =(int)(ThreadLocalRandom.current().nextDouble()* referers.size());for(int i =0; i < referers.size(); i++){
Referer<T> referer = referers.get((i + idx)% referers.size());if(referer.isAvailable()){
refersHolder.add(referer);}}}}
轮询算法
轮询算法,就是按照指定的顺序,把可用的服务节点挨个访问一次
轮询算法通常是吧可用节点放到一个数组里面,然后按照数组编号,挨个访问。
/*
* Copyright 2009-2016 Weibo, 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.
*/package com.weibo.api.motan.cluster.loadbalance;import java.util.List;import java.util.concurrent.atomic.AtomicInteger;import com.weibo.api.motan.core.extension.SpiMeta;import com.weibo.api.motan.rpc.Referer;import com.weibo.api.motan.rpc.Request;import com.weibo.api.motan.util.MathUtil;/**
*
* Round robin loadbalance.
*
* @author fishermen
* @version V1.0 created at: 2013-6-13
*/@SpiMeta(name ="roundrobin")publicclassRoundRobinLoadBalance<T>extendsAbstractLoadBalance<T>{private AtomicInteger idx =newAtomicInteger(0);@Overrideprotected Referer<T>doSelect(Request request){
List<Referer<T>> referers =getReferers();int index =getNextNonNegative();for(int i =0; i < referers.size(); i++){
Referer<T> ref = referers.get((i + index)% referers.size());if(ref.isAvailable()){return ref;}
idx.incrementAndGet();}return null;}@OverrideprotectedvoiddoSelectToHolder(Request request, List<Referer<T>> refersHolder){
List<Referer<T>> referers =getReferers();int index =getNextNonNegative();for(int i =0, count =0; i < referers.size()&& count < MAX_REFERER_COUNT; i++){
Referer<T> referer = referers.get((i + index)% referers.size());if(referer.isAvailable()){
refersHolder.add(referer);
count++;}}}// get non-negative intprivateintgetNextNonNegative(){return MathUtil.getNonNegative(idx.incrementAndGet());}}
/*
* Copyright 2009-2016 Weibo, 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.
*/package com.weibo.api.motan.cluster.loadbalance;import java.util.Collections;import java.util.Comparator;import java.util.List;import java.util.Random;import java.util.concurrent.ThreadLocalRandom;import com.weibo.api.motan.core.extension.SpiMeta;import com.weibo.api.motan.rpc.Referer;import com.weibo.api.motan.rpc.Request;/**
* "低并发优化" 负载均衡
*
* <pre>
* 1) 低并发度优先: referer的某时刻的call数越小优先级越高
*
* 2) 低并发referer获取策略:
* 由于Referer List可能很多,比如上百台,如果每次都要从这上百个Referer或者最低并发的几个,性能有些损耗,
* 因此 random.nextInt(list.size()) 获取一个起始的index,然后获取最多不超过MAX_REFERER_COUNT的
* 状态是isAvailable的referer进行判断activeCount.
* </pre>
*
* @author maijunsheng
* @version 创建时间:2013-6-14
*
*/@SpiMeta(name ="activeWeight")publicclassActiveWeightLoadBalance<T>extendsAbstractLoadBalance<T>{@Overrideprotected Referer<T>doSelect(Request request){
List<Referer<T>> referers =getReferers();int refererSize = referers.size();int startIndex = ThreadLocalRandom.current().nextInt(refererSize);int currentCursor =0;int currentAvailableCursor =0;
Referer<T> referer = null;while(currentAvailableCursor < MAX_REFERER_COUNT && currentCursor < refererSize){
Referer<T> temp = referers.get((startIndex + currentCursor)% refererSize);
currentCursor++;if(!temp.isAvailable()){continue;}
currentAvailableCursor++;if(referer == null){
referer = temp;}else{if(compare(referer, temp)>0){
referer = temp;}}}return referer;}@OverrideprotectedvoiddoSelectToHolder(Request request, List<Referer<T>> refersHolder){
List<Referer<T>> referers =getReferers();int refererSize = referers.size();int startIndex = ThreadLocalRandom.current().nextInt(refererSize);int currentCursor =0;int currentAvailableCursor =0;while(currentAvailableCursor < MAX_REFERER_COUNT && currentCursor < refererSize){
Referer<T> temp = referers.get((startIndex + currentCursor)% refererSize);
currentCursor++;if(!temp.isAvailable()){continue;}
currentAvailableCursor++;
refersHolder.add(temp);}
Collections.sort(refersHolder,newLowActivePriorityComparator<T>());}privateintcompare(Referer<T> referer1, Referer<T> referer2){return referer1.activeRefererCount()- referer2.activeRefererCount();}staticclassLowActivePriorityComparator<T>implementsComparator<Referer<T>>{@Overridepublicintcompare(Referer<T> referer1, Referer<T> referer2){return referer1.activeRefererCount()- referer2.activeRefererCount();}}}
一致hash算法
一致性hash算法,是通过某个hash函数,把同一个来源的请求都映射到同一个节点上。
/*
* Copyright 2009-2016 Weibo, 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.
*/package com.weibo.api.motan.cluster.loadbalance;import java.util.ArrayList;import java.util.Arrays;import java.util.Collections;import java.util.List;import com.weibo.api.motan.common.MotanConstants;import com.weibo.api.motan.core.extension.SpiMeta;import com.weibo.api.motan.rpc.Referer;import com.weibo.api.motan.rpc.Request;import com.weibo.api.motan.util.MathUtil;/**
*
* Use consistent hash to choose referer
*
* @author fishermen
* @version V1.0 created at: 2013-5-21
*/@SpiMeta(name ="consistent")publicclassConsistentHashLoadBalance<T>extendsAbstractLoadBalance<T>{private List<Referer<T>> consistentHashReferers;@OverridepublicvoidonRefresh(List<Referer<T>> referers){super.onRefresh(referers);
List<Referer<T>> copyReferers =newArrayList<Referer<T>>(referers);
List<Referer<T>> tempRefers =newArrayList<Referer<T>>();for(int i =0; i < MotanConstants.DEFAULT_CONSISTENT_HASH_BASE_LOOP; i++){
Collections.shuffle(copyReferers);for(Referer<T> ref : copyReferers){
tempRefers.add(ref);}}
consistentHashReferers = tempRefers;}@Overrideprotected Referer<T>doSelect(Request request){int hash =getHash(request);
Referer<T> ref;for(int i =0; i <getReferers().size(); i++){
ref = consistentHashReferers.get((hash + i)% consistentHashReferers.size());if(ref.isAvailable()){return ref;}}return null;}@OverrideprotectedvoiddoSelectToHolder(Request request, List<Referer<T>> refersHolder){
List<Referer<T>> referers =getReferers();int hash =getHash(request);for(int i =0; i < referers.size(); i++){
Referer<T> ref = consistentHashReferers.get((hash + i)% consistentHashReferers.size());if(ref.isAvailable()){
refersHolder.add(ref);}}}privateintgetHash(Request request){int hashcode;if(request.getArguments()== null || request.getArguments().length ==0){
hashcode = request.hashCode();}else{
hashcode = Arrays.hashCode(request.getArguments());}return MathUtil.getNonNegative(hashcode);}}
`