polling
The main idea is to pick a server of a service
1 simple implementation
public class RoundRobin {
private static Integer pos = 0;
public static String getServer() {
if(pos >= ServerIps.LIST.size()) {
pos = 0;
}
String ip = ServerIps.LIST.get(pos);
pos++;
return ip;
}
public static void main(String[] args) {
for(int i = 0; i < 20; i++) {
System.out.println(getServer());
}
}
}
2 Optimization: Considering Weight
When considering weight
- Violence to resolve, will create a LIST =, the IP address into the inside LIST according to the size of the weights
- Or in accordance with the idea of stochastic optimization
Wherein A, B, C represent the three IP addresses, weights are 5,3,2 A: 5 B: 3 C: 2
Mapped to the coordinate axis
0 ----- --- 8--10. 5
offset value of another is not a random number, but 0,1,2,3,4,5,6,7,8,9
1 ——> A
2 ——> A
...
6 ——> B
...
Code
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
public class ServerIps {
public static final Map<String, Integer> WEIGHT_MAP = new LinkedHashMap<>();
static {
WEIGHT_MAP.put("192.168.0.1", 2);
WEIGHT_MAP.put("192.168.0.2", 8);
WEIGHT_MAP.put("192.168.0.3", 1);
WEIGHT_MAP.put("192.168.0.4", 9);
WEIGHT_MAP.put("192.168.0.5", 4);
WEIGHT_MAP.put("192.168.0.6", 6);
}
}
Note employed therein is a LinkedHashMap , so that the order can ensure consistent output and input
public class RequestId {
public static Integer num = 0;
public static Integer getAndIncrement() {
return num++;
}
}
Imitate the above code is the customer ID number to control the polling of the server according to the customer ID number.
public class RoundRobin2 {
public static String getServer() {
int totalWeight = 0;
for (Integer weight: ServerIps.WEIGHT_MAP.values()) {
totalWeight += weight;
}
int requestId = RequestId.getAndIncrement();
int offset = requestId % totalWeight;
for(String ip: ServerIps.WEIGHT_MAP.keySet()) {
Integer weight = ServerIps.WEIGHT_MAP.get(ip);
if (offset < weight) {
return ip;
}
offset -= weight;
}
return null;
}
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
System.out.println(getServer());
}
}
}
Optimization 3: smoothing algorithm WRR
Nginx default using this algorithm
A:. 5
B: 1
C: 1 In this case, the access order optimized as a AAAAABC, so pressure on the server A relatively large
If in discrete, then there would be such a problem, such as the following order
AABACAA
This will not only make the service more scattered, but also to ensure the weight, but also to achieve the purpose of polling
Specific process is as follows:
ip
weight: static, 5,1,1 currentWeight: Dynamic
currentWeight: 0,0,0
currentWeight+=weight | max(currentWeight) | result | max(currentWeight)-=sum(weight)7 |
---|---|---|---|
5,1,1 | 5 | A | -2,1,1 |
3,2,2 | 3 | A | -4,2,2 |
1,3,3 | 3 | B | 1,-4,3 |
6,-3,4 | 6 | A | -1,-3,4 |
4,-2,5 | 5 | C | 4,-2,-2 |
9,-1,-1 | 9 | A | 2,-1,-1 |
7,0,0 | 7 | A | 0,0,0 |
5,1,1 | ... | ... | ... |
Code
public class Weight {
private String ip;
private Integer weight;
private Integer currentWeight;
public Weight(String ip, Integer weight, Integer currentWeight) {
super();
this.ip = ip;
this.weight = weight;
this.currentWeight = currentWeight;
}
public String getIp() {
return ip;
}
public void setIp(String ip) {
this.ip = ip;
}
public Integer getWeight() {
return weight;
}
public void setWeight(Integer weight) {
this.weight = weight;
}
public Integer getCurrentWeight() {
return currentWeight;
}
public void setCurrentWeight(Integer currentWeight) {
this.currentWeight = currentWeight;
}
}
=============================
import java.util.LinkedHashMap;
import java.util.Map;
public class WeightRoundRobin {
private static Map<String, Weight> weightMap = new LinkedHashMap<>();
public static String getServer() {
if(weightMap.isEmpty()) {
for(String ip: ServerIps.WEIGHT_MAP.keySet()) {
Integer weight = ServerIps.WEIGHT_MAP.get(ip);
weightMap.put(ip, new Weight(ip, weight, 0));
}
}
// currentWeight += weight
for(Weight weight: weightMap.values()) {
weight.setCurrentWeight(weight.getCurrentWeight() + weight.getWeight());
}
Weight maxCurrentWeight = null;
for (Weight weight: weightMap.values()) {
if (maxCurrentWeight == null || weight.getCurrentWeight() > maxCurrentWeight.getCurrentWeight()) {
maxCurrentWeight = weight;
}
}
// max(currentWeight) -= sum(weight)
int totalWeight = 0;
for (Integer weight: ServerIps.WEIGHT_MAP.values()) {
totalWeight += weight;
}
maxCurrentWeight.setCurrentWeight(maxCurrentWeight.getCurrentWeight() - totalWeight);
//result
return maxCurrentWeight.getIp();
}
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
System.out.println(getServer());
}
}
}