/*
* 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);}}
`