sofa - rpc 폴 링 알고리즘 총화
26018 단어 sofa-rpc
유형
알고리즘 이름
묘사 하 다.
RandomLoadBalancer
부하 균형 랜 덤 알고리즘
LocalPreferenceLoadBalancer
로 컬 우선 순위 랜 덤 알고리즘
ConsistentHashLoadBalancer
일치 성 hash 알고리즘
RoundRobinLoadBalancer
폴 링 알고리즘
WeightRoundRobinLoadBalancer
폴 링 알고리즘
부하 균형 랜 덤 알고리즘
public class RandomLoadBalancer extends AbstractLoadBalancer {
private final Random random = new Random();
public RandomLoadBalancer(ConsumerBootstrap consumerBootstrap) {
super(consumerBootstrap);
}
public ProviderInfo doSelect(SofaRequest invocation, List providerInfos) {
ProviderInfo providerInfo = null;
int size = providerInfos.size();
int totalWeight = 0;
boolean isWeightSame = true;
int offset;
int i;
for(offset = 0; offset < size; ++offset) {
i = this.getWeight((ProviderInfo)providerInfos.get(offset));
totalWeight += i;
if (isWeightSame && offset > 0 && i != this.getWeight((ProviderInfo)providerInfos.get(offset - 1))) {
isWeightSame = false;
}
}
if (totalWeight > 0 && !isWeightSame) {
offset = this.random.nextInt(totalWeight);
for(i = 0; i < size; ++i) {
offset -= this.getWeight((ProviderInfo)providerInfos.get(i));
if (offset < 0) {
providerInfo = (ProviderInfo)providerInfos.get(i);
break;
}
}
} else {
providerInfo = (ProviderInfo)providerInfos.get(this.random.nextInt(size));
}
return providerInfo;
}
}
@Extension("roundRobin")
public class RoundRobinLoadBalancer extends AbstractLoadBalancer {
private final ConcurrentMap sequences = new ConcurrentHashMap();
public RoundRobinLoadBalancer(ConsumerBootstrap consumerBootstrap) {
super(consumerBootstrap);
}
public ProviderInfo doSelect(SofaRequest request, List providerInfos) {
String key = this.getServiceKey(request);
int length = providerInfos.size();
PositiveAtomicCounter sequence = (PositiveAtomicCounter)this.sequences.get(key);
if (sequence == null) {
this.sequences.putIfAbsent(key, new PositiveAtomicCounter());
sequence = (PositiveAtomicCounter)this.sequences.get(key);
}
return (ProviderInfo)providerInfos.get(sequence.getAndIncrement() % length);
}
private String getServiceKey(SofaRequest request) {
StringBuilder builder = new StringBuilder();
builder.append(request.getTargetAppName()).append("#").append(request.getMethodName());
return builder.toString();
}
}
public class PositiveAtomicCounter {
private static final int MASK = 2147483647;
private final AtomicInteger atom = new AtomicInteger(0);
public PositiveAtomicCounter() {
}
public final int incrementAndGet() {
return this.atom.incrementAndGet() & 2147483647;
}
public final int getAndIncrement() {
return this.atom.getAndIncrement() & 2147483647;
}
public int get() {
return this.atom.get() & 2147483647;
}
}
로 컬 우선 순위 랜 덤 알고리즘
@Extension("localPref")
public class LocalPreferenceLoadBalancer extends RandomLoadBalancer {
public LocalPreferenceLoadBalancer(ConsumerBootstrap consumerBootstrap) {
super(consumerBootstrap);
}
public ProviderInfo doSelect(SofaRequest invocation, List providerInfos) {
String localhost = SystemInfo.getLocalHost();
if (StringUtils.isEmpty(localhost)) {
return super.doSelect(invocation, providerInfos);
} else {
List localProviderInfo = new ArrayList();
Iterator i$ = providerInfos.iterator();
while(i$.hasNext()) {
ProviderInfo providerInfo = (ProviderInfo)i$.next();
if (localhost.equals(providerInfo.getHost())) {
localProviderInfo.add(providerInfo);
}
}
if (CommonUtils.isNotEmpty(localProviderInfo)) {
return super.doSelect(invocation, localProviderInfo);
} else {
return super.doSelect(invocation, providerInfos);
}
}
}
}
일치 성 hash 알고리즘 (값 학습)
2^32 ( Hash ), Hash ( [0, 2^32-1]) Hash ,
Key Hash ( [0, 232-1]),
Hash Key Hash , Key 。
/**
* hash , ( )
*
* @author GengZhang
*/
@Extension("consistentHash")
public class ConsistentHashLoadBalancer extends AbstractLoadBalancer {
/**
* {interface#method : selector}
*/
private ConcurrentMap<String, Selector> selectorCache = new ConcurrentHashMap<String, Selector>();
/**
*
*
* @param consumerBootstrap
*/
public ConsistentHashLoadBalancer(ConsumerBootstrap consumerBootstrap) {
super(consumerBootstrap);
}
@Override
public ProviderInfo doSelect(SofaRequest request, List<ProviderInfo> providerInfos) {
String interfaceId = request.getInterfaceName();
String method = request.getMethodName();
String key = interfaceId + "#" + method;
int hashcode = providerInfos.hashCode(); //
Selector selector = selectorCache.get(key);
if (selector == null //
||
selector.getHashCode() != hashcode) { //
selector = new Selector(interfaceId, method, providerInfos, hashcode);
selectorCache.put(key, selector);
}
return selector.select(request);
}
/**
*
*/
private static class Selector {
/**
* The Hashcode.
*/
private final int hashcode;
/**
* The Interface id.
*/
private final String interfaceId;
/**
* The Method name.
*/
private final String method;
/**
*
*/
private final TreeMap<Long, ProviderInfo> virtualNodes;
/**
* Instantiates a new Selector.
*
* @param interfaceId the interface id
* @param method the method
* @param actualNodes the actual nodes
*/
public Selector(String interfaceId, String method, List<ProviderInfo> actualNodes) {
this(interfaceId, method, actualNodes, actualNodes.hashCode());
}
/**
* Instantiates a new Selector.
*
* @param interfaceId the interface id
* @param method the method
* @param actualNodes the actual nodes
* @param hashcode the hashcode
*/
public Selector(String interfaceId, String method, List<ProviderInfo> actualNodes, int hashcode) {
this.interfaceId = interfaceId;
this.method = method;
this.hashcode = hashcode;
// ( provider 128 , )
this.virtualNodes = new TreeMap<Long, ProviderInfo>();
int num = 128;
for (ProviderInfo providerInfo : actualNodes) {
for (int i = 0; i < num / 4; i++) {
byte[] digest = HashUtils.messageDigest(providerInfo.getHost() + providerInfo.getPort() + i);
for (int h = 0; h < 4; h++) {
long m = HashUtils.hash(digest, h);
virtualNodes.put(m, providerInfo);
}
}
}
}
/**
* Select provider.
*
* @param request the request
* @return the provider
*/
public ProviderInfo select(SofaRequest request) {
String key = buildKeyOfHash(request.getMethodArgs());
byte[] digest = HashUtils.messageDigest(key);
return selectForKey(HashUtils.hash(digest, 0));
}
/**
* hash key
*
* @param args the args
* @return the string
*/
private String buildKeyOfHash(Object[] args) {
if (CommonUtils.isEmpty(args)) {
return StringUtils.EMPTY;
} else {
return StringUtils.toString(args[0]);
}
}
/**
* Select for key.
*
* @param hash the hash
* @return the provider
*/
private ProviderInfo selectForKey(long hash) {
Map.Entry<Long, ProviderInfo> entry = virtualNodes.ceilingEntry(hash);
if (entry == null) {
entry = virtualNodes.firstEntry();
}
return entry.getValue();
}
/**
* Gets hash code.
*
* @return the hash code
*/
public int getHashCode() {
return hashcode;
}
}
}
응용 장면