Skip to content

Commit ecfb9de

Browse files
committed
update codes
1 parent c184910 commit ecfb9de

File tree

6 files changed

+111
-88
lines changed

6 files changed

+111
-88
lines changed
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package io.github.dunwu.javatech;
2+
3+
import cn.hutool.core.collection.CollectionUtil;
4+
5+
import java.util.Collection;
6+
import java.util.LinkedList;
7+
import java.util.List;
8+
9+
/**
10+
* @author <a href="mailto:[email protected]">Zhang Peng</a>
11+
* @since 2021-01-18
12+
*/
13+
public abstract class BaseLoadBalance<N extends Node> implements LoadBalance<N> {
14+
15+
protected List<N> nodes = new LinkedList<>();
16+
17+
@Override
18+
public void buildNodes(final Collection<N> collection) {
19+
this.nodes = new LinkedList<>(collection);
20+
}
21+
22+
@Override
23+
public void addNode(N node) {
24+
this.nodes.add(node);
25+
}
26+
27+
@Override
28+
public void removeNode(N node) {
29+
this.nodes.remove(node);
30+
}
31+
32+
@Override
33+
public N select() {
34+
if (CollectionUtil.isEmpty(nodes)) {
35+
return null;
36+
}
37+
38+
// 如果 nodes 列表中仅有一个 node,直接返回即可,无需进行负载均衡
39+
if (nodes.size() == 1) {
40+
return nodes.get(0);
41+
}
42+
43+
return doSelect();
44+
}
45+
46+
protected abstract N doSelect();
47+
48+
}

codes/java-distributed/java-load-balance/src/main/java/io/github/dunwu/javatech/ConsistentHashLoadBalance.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ public class ConsistentHashLoadBalance<V extends Node> implements LoadBalance<V>
1818
private TreeMap<Integer, V> hashRing = new TreeMap<>();
1919

2020
@Override
21-
public void buildInList(final Collection<V> collection) {
21+
public void buildNodes(final Collection<V> collection) {
2222
this.nodes = new LinkedHashSet<>(collection);
2323
this.hashRing = buildConsistentHashRing(this.nodes);
2424
}
@@ -36,7 +36,7 @@ public void removeNode(V node) {
3636
}
3737

3838
@Override
39-
public V next() {
39+
public V select() {
4040
return next(UUID.randomUUID().toString());
4141
}
4242

codes/java-distributed/java-load-balance/src/main/java/io/github/dunwu/javatech/LoadBalance.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@
88
* @author <a href="mailto:[email protected]">Zhang Peng</a>
99
* @since 2020-01-21
1010
*/
11-
public interface LoadBalance<V extends Node> {
11+
public interface LoadBalance<N extends Node> {
1212

13-
void buildInList(Collection<V> collection);
13+
void buildNodes(Collection<N> collection);
1414

15-
void addNode(V node);
15+
void addNode(N node);
1616

17-
void removeNode(V node);
17+
void removeNode(N node);
1818

19-
V next();
19+
N select();
2020

2121
}
Lines changed: 37 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
package io.github.dunwu.javatech;
22

3-
import cn.hutool.core.collection.CollectionUtil;
4-
5-
import java.util.*;
3+
import java.util.Random;
64
import java.util.concurrent.ThreadLocalRandom;
75

86
/**
@@ -12,74 +10,51 @@
1210
* @see <a href="https://www.cnblogs.com/CodeBear/archive/2019/03/11/10508880.html">Zhang Peng</a>
1311
* @since 2020-01-20
1412
*/
15-
public class RandomLoadBalance<V extends Node> implements LoadBalance<V> {
16-
17-
private boolean weightMode;
13+
public class RandomLoadBalance<N extends Node> extends BaseLoadBalance<N> implements LoadBalance<N> {
1814

1915
private final Random random = ThreadLocalRandom.current();
2016

21-
private Set<V> nodes = Collections.emptyNavigableSet();
22-
23-
public RandomLoadBalance() {
24-
this.weightMode = false;
25-
}
26-
27-
public RandomLoadBalance(boolean weightMode) {
28-
this.weightMode = weightMode;
29-
}
30-
31-
@Override
32-
public void buildInList(final Collection<V> collection) {
33-
this.nodes = new LinkedHashSet<>(collection);
34-
}
35-
36-
@Override
37-
public void addNode(V node) {
38-
this.nodes.add(node);
39-
}
40-
4117
@Override
42-
public void removeNode(V node) {
43-
this.nodes.remove(node);
44-
}
45-
46-
@Override
47-
public V next() {
48-
if (weightMode) {
49-
return getNextInWeightMode();
50-
} else {
51-
return getNextInNormalMode();
52-
}
53-
}
54-
55-
private V getNextInWeightMode() {
56-
if (CollectionUtil.isEmpty(nodes)) {
57-
return null;
58-
}
59-
60-
List<V> list = new ArrayList<>();
61-
for (V node : nodes) {
62-
for (int i = 0; i < node.getWeight(); i++) {
63-
list.add(node);
18+
protected N doSelect() {
19+
boolean sameWeight = true;
20+
int length = nodes.size();
21+
int totalWeight = 0;
22+
// 下面这个循环有两个作用
23+
// 第一是计算总权重 totalWeight,
24+
// 第二是检测每个服务提供者的权重是否相同
25+
for (int i = 0; i < length; i++) {
26+
Integer weight = nodes.get(i).getWeight();
27+
// 累加权重
28+
totalWeight += weight;
29+
// 检测当前服务提供者的权重与上一个服务提供者的权重是否相同,
30+
// 不相同的话,则将 sameWeight 置为 false。
31+
if (sameWeight && i > 0 && weight.equals(nodes.get(i - 1).getWeight())) {
32+
sameWeight = false;
6433
}
6534
}
6635

67-
int totalWeight = nodes.stream().mapToInt(Node::getWeight).sum();
68-
int number = random.nextInt(totalWeight);
69-
return list.get(number);
70-
}
71-
72-
private V getNextInNormalMode() {
73-
if (CollectionUtil.isEmpty(nodes)) {
74-
return null;
36+
// 下面的 if 分支主要用于获取随机数,并计算随机数落在哪个区间上
37+
if (totalWeight > 0 && !sameWeight) {
38+
// 随机获取一个 [0, totalWeight) 区间内的数字
39+
int offset = random.nextInt(totalWeight);
40+
// 循环让 offset 数减去服务提供者权重值,当 offset 小于0时,返回相应的 Node。
41+
// 举例说明一下,我们有 servers = [A, B, C],weights = [5, 3, 2],offset = 7。
42+
// 第一次循环,offset - 5 = 2 > 0,即 offset > 5,
43+
// 表明其不会落在服务器 A 对应的区间上。
44+
// 第二次循环,offset - 3 = -1 < 0,即 5 < offset < 8,
45+
// 表明其会落在服务器 B 对应的区间上
46+
for (int i = 0; i < length; i++) {
47+
// 让随机值 offset 减去权重值
48+
offset -= nodes.get(i).getWeight();
49+
if (offset < 0) {
50+
// 返回相应的 Node
51+
return nodes.get(i);
52+
}
53+
}
7554
}
7655

77-
int number = random.nextInt(nodes.size());
78-
Iterator<V> iterator = nodes.iterator();
79-
while (number-- > 0) {
80-
iterator.next();
81-
}
82-
return iterator.next();
56+
// 如果所有服务提供者权重值相同,此时直接随机返回一个即可
57+
return nodes.get(random.nextInt(length));
8358
}
8459

8560
}

codes/java-distributed/java-load-balance/src/main/java/io/github/dunwu/javatech/RoundRobinLoadBalance.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ public RoundRobinLoadBalance(boolean weightMode) {
2828
}
2929

3030
@Override
31-
public void buildInList(final Collection<V> collection) {
31+
public void buildNodes(final Collection<V> collection) {
3232
this.offset = new AtomicInteger(0);
3333
this.nodes = new LinkedHashSet<>(collection);
3434
}
@@ -44,7 +44,7 @@ public void removeNode(V node) {
4444
}
4545

4646
@Override
47-
public V next() {
47+
public V select() {
4848
if (weightMode) {
4949
return getNextInWeightMode();
5050
} else {

codes/java-distributed/java-load-balance/src/test/java/io/github/dunwu/javatech/LoadBalanceTests.java

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ private Map<Node, Long> staticLoadBalance(LoadBalance<Node> algorithm) {
3232
Map<Node, Long> staticMap = new TreeMap<>();
3333

3434
for (int i = 0; i < 10000; i++) {
35-
Node node = algorithm.next();
35+
Node node = algorithm.select();
3636
// System.out.printf(">>>> url = %s\n", node.url);
3737
if (staticMap.containsKey(node)) {
3838
Long value = staticMap.get(node);
@@ -56,12 +56,12 @@ public void randomLoadBalanceDistribution() {
5656
List<Node> nodes = initNodes();
5757

5858
LoadBalance<Node> loadBalance = new RandomLoadBalance<>();
59-
loadBalance.buildInList(nodes);
59+
loadBalance.buildNodes(nodes);
6060
System.out.println("======================= 随机负载均衡 =======================");
6161
staticLoadBalance(loadBalance);
6262

63-
LoadBalance<Node> loadBalance2 = new RandomLoadBalance<>(true);
64-
loadBalance2.buildInList(nodes);
63+
LoadBalance<Node> loadBalance2 = new RandomLoadBalance<>();
64+
loadBalance2.buildNodes(nodes);
6565
System.out.println("======================= 加权随机负载均衡 =======================");
6666
staticLoadBalance(loadBalance2);
6767
}
@@ -72,15 +72,15 @@ public void randomLoadBalanceUpdateNodes() {
7272
List<Node> newNodes = oldNodes.subList(0, 80);
7373

7474
LoadBalance<Node> oldLoadBalance = new RandomLoadBalance<>();
75-
oldLoadBalance.buildInList(oldNodes);
75+
oldLoadBalance.buildNodes(oldNodes);
7676
LoadBalance<Node> newLoadBalance = new RandomLoadBalance<>();
77-
newLoadBalance.buildInList(newNodes);
77+
newLoadBalance.buildNodes(newNodes);
7878

7979
double count = 0.0d;
8080
int size = newNodes.size();
8181
for (int i = 0; i < newNodes.size(); i++) {
82-
Node oldNode = oldLoadBalance.next();
83-
Node newNode = newLoadBalance.next();
82+
Node oldNode = oldLoadBalance.select();
83+
Node newNode = newLoadBalance.select();
8484
if (oldNode.equals(newNode)) count++;
8585
}
8686
System.out.println(count / size);
@@ -91,12 +91,12 @@ public void roundRobinLoadBalanceDistribution() {
9191
List<Node> nodes = initNodes();
9292

9393
LoadBalance<Node> loadBalance = new RoundRobinLoadBalance<>();
94-
loadBalance.buildInList(nodes);
94+
loadBalance.buildNodes(nodes);
9595
System.out.println("======================= 轮询负载均衡 =======================");
9696
staticLoadBalance(loadBalance);
9797

9898
LoadBalance<Node> loadBalance2 = new RoundRobinLoadBalance<>(true);
99-
loadBalance2.buildInList(nodes);
99+
loadBalance2.buildNodes(nodes);
100100
System.out.println("======================= 加权轮询负载均衡 =======================");
101101
staticLoadBalance(loadBalance2);
102102
}
@@ -107,15 +107,15 @@ public void roundRobinLoadBalanceUpdateNodes() {
107107
List<Node> newNodes = oldNodes.subList(0, 80);
108108

109109
LoadBalance<Node> oldLoadBalance = new RoundRobinLoadBalance<>();
110-
oldLoadBalance.buildInList(oldNodes);
110+
oldLoadBalance.buildNodes(oldNodes);
111111
LoadBalance<Node> newLoadBalance = new RoundRobinLoadBalance<>();
112-
newLoadBalance.buildInList(newNodes);
112+
newLoadBalance.buildNodes(newNodes);
113113

114114
double count = 0.0d;
115115
int size = newNodes.size();
116116
for (int i = 0; i < newNodes.size(); i++) {
117-
Node oldNode = oldLoadBalance.next();
118-
Node newNode = newLoadBalance.next();
117+
Node oldNode = oldLoadBalance.select();
118+
Node newNode = newLoadBalance.select();
119119
if (oldNode.equals(newNode)) count++;
120120
}
121121
System.out.println(count / size);
@@ -124,7 +124,7 @@ public void roundRobinLoadBalanceUpdateNodes() {
124124
@Test
125125
public void consistentHashLoadBalanceDistribution() {
126126
LoadBalance<Node> loadBalance = new ConsistentHashLoadBalance<>();
127-
loadBalance.buildInList(initNodes());
127+
loadBalance.buildNodes(initNodes());
128128
System.out.println("======================= 一致性 Hash 负载均衡 =======================");
129129
staticLoadBalance(loadBalance);
130130
}
@@ -148,9 +148,9 @@ public void testNodeAddAndRemove() {
148148

149149
List<Node> newNodes = nodes.subList(0, 80);
150150
ConsistentHashLoadBalance<Node> oldLoadBalance = new ConsistentHashLoadBalance<>();
151-
oldLoadBalance.buildInList(nodes);
151+
oldLoadBalance.buildNodes(nodes);
152152
ConsistentHashLoadBalance<Node> newLoadBalance = new ConsistentHashLoadBalance<>();
153-
newLoadBalance.buildInList(newNodes);
153+
newLoadBalance.buildNodes(newNodes);
154154

155155
int count = 0;
156156
for (String key : keys) {

0 commit comments

Comments
 (0)