-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #24 from RicrodoZ/master
[refactor] Added consistent hash load balancing mode.
- Loading branch information
Showing
10 changed files
with
120 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
92 changes: 92 additions & 0 deletions
92
...le/src/main/java/github/javaguide/loadbalance/loadbalancer/ConsistentHashLoadBalance.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
package github.javaguide.loadbalance.loadbalancer; | ||
|
||
import github.javaguide.loadbalance.AbstractLoadBalance; | ||
import lombok.extern.slf4j.Slf4j; | ||
|
||
import java.nio.charset.StandardCharsets; | ||
import java.security.MessageDigest; | ||
import java.security.NoSuchAlgorithmException; | ||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.TreeMap; | ||
import java.util.concurrent.ConcurrentHashMap; | ||
|
||
/** | ||
* refer to dubbo consistent hash load balance: http://dubbo.apache.org/zh-cn/blog/dubbo-consistent-hash-implementation.html | ||
* @author RicardoZ | ||
* @createTime 2020年10月20日 18:15:20 | ||
*/ | ||
@Slf4j | ||
public class ConsistentHashLoadBalance extends AbstractLoadBalance { | ||
private final ConcurrentHashMap<String, ConsistentHashSelector> selectors = new ConcurrentHashMap<>(); | ||
|
||
@Override | ||
protected String doSelect(List<String> serviceAddresses, String rpcServiceName) { | ||
int identityHashCode = System.identityHashCode(serviceAddresses); | ||
|
||
ConsistentHashSelector selector = selectors.get(rpcServiceName); | ||
|
||
// check for updates | ||
if (selector == null || selector.identityHashCode != identityHashCode) { | ||
selectors.put(rpcServiceName, new ConsistentHashSelector(serviceAddresses, 160, identityHashCode)); | ||
selector = selectors.get(rpcServiceName); | ||
} | ||
|
||
return selector.select(rpcServiceName); | ||
} | ||
|
||
static class ConsistentHashSelector { | ||
private final TreeMap<Long, String> virtualInvokers; | ||
|
||
private final int identityHashCode; | ||
|
||
ConsistentHashSelector(List<String> invokers, int replicaNumber, int identityHashCode) { | ||
this.virtualInvokers = new TreeMap<>(); | ||
this.identityHashCode = identityHashCode; | ||
|
||
for (String invoker : invokers) { | ||
for (int i = 0; i < replicaNumber / 4; i++) { | ||
byte[] digest = md5(invoker + i); | ||
for (int h = 0; h < 4; h++) { | ||
long m = hash(digest, h); | ||
virtualInvokers.put(m, invoker); | ||
} | ||
} | ||
} | ||
} | ||
|
||
static byte[] md5(String key) { | ||
MessageDigest md = null; | ||
|
||
try { | ||
md = MessageDigest.getInstance("md5"); | ||
byte[] bytes = key.getBytes(StandardCharsets.UTF_8); | ||
md.update(bytes); | ||
} catch (NoSuchAlgorithmException e) { | ||
log.error("An encryption algorithm that does not exist is used: ", e); | ||
e.printStackTrace(); | ||
} | ||
|
||
return md.digest(); | ||
} | ||
|
||
static long hash(byte[] digest, int idx) { | ||
return ((long) (digest[3 + idx * 4] & 255) << 24 | (long) (digest[2 + idx * 4] & 255) << 16 | (long) (digest[1 + idx * 4] & 255) << 8 | (long) (digest[idx * 4] & 255)) & 4294967295L; | ||
} | ||
|
||
public String select(String rpcServiceName) { | ||
byte[] digest = md5(rpcServiceName); | ||
return selectForKey(hash(digest, 0)); | ||
} | ||
|
||
public String selectForKey(long hashCode) { | ||
Map.Entry<Long, String> entry = virtualInvokers.tailMap(hashCode, true).firstEntry(); | ||
|
||
if (entry == null) { | ||
entry = virtualInvokers.firstEntry(); | ||
} | ||
|
||
return entry.getValue(); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
1 change: 1 addition & 0 deletions
1
...rk-simple/src/main/resources/META-INF/extensions/github.javaguide.loadbalance.LoadBalance
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
loadBalance=github.javaguide.loadbalance.loadbalancer.ConsistentHashLoadBalance |