轮询
轮询是一种CPU决策如何提供周边设备服务的方式,又称“程控输入输出”。
普通轮询
将请求依次发给服务器,周而复始。
加权轮询
为了解决普通轮询的问题:效率偏低,无法满足服务器配置不同的情况。
按照每台服务器的权重值分配。例如现在有3台服务器A=5,B=3,C=1,数字代表权重值。将3台服务器的权重值相加值为9,也就是说每9个请求将会分5个给A,3个给B,1个给C,依次循环{AAAAABBBCC…}
package com.woniuxy;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.ArrayList;
import java.util.List;
@Data
@AllArgsConstructor
@NoArgsConstructor
class Server{
private String ip;
private int weight;
}
//nginx底层算法
public class apptest3 {
private static List<Server> servers=new ArrayList<>();
static {
servers.add(new Server("A",5));
servers.add(new Server("B",3));
servers.add(new Server("C",1));
}
public static int n=0;
//负载均衡
public static Server getServer(int requestId){
//计算总权重
int total=0;
for (Server server:servers) {
total+=server.getWeight();
}
//n的值在1-7之间
int n=requestId%total+1;
for (Server server:servers) {
if (n<=server.getWeight()){
return server;
}
n=n-server.getWeight();
}
//没有
return null;
}
public static void main(String[] args) {
//模拟请求 轮询算法
for (int i = 0; i <20 ; i++) {
Server server=getServer(i);
System.out.println(i+1+"次访问的是:"+server.getIp());
}
}
}
运行后展示:
平滑加权轮询
为了解决加权轮询的问题:短时间内权重大的服务器得到过多的请求数,不是一种均匀的分配方式。
平滑的加权轮询,例如现在有3台服务器A=4,B=2,C=2,依次循环后结果不是{AAAABBCC),而是很均匀很平滑的{ABCAABCA},即Nginx负载均衡策略中所用的平滑加权轮询算法。
package com.woniuxy;
import java.util.ArrayList;
import java.util.List;
@Data
@NoArgsConstructor
@AllArgsConstructor
class Server {
//服务器
private String ip;
// 静态权重
private int weight;
// 动态权重
private int dynamicWeight;
}
public class AppTest5s {
private static List<Server> servers = new ArrayList<Server>();
static {
servers.add(new Server("A",4,0));
servers.add(new Server("B",2,0));
servers.add(new Server("C",2,0));
}
public static Server getServer(int requestIp){
//计算总权重
int total=0;
for (Server server: servers) {
total += server.getWeight();
}
//给每一个服务器静态权重,都加上各自的动态权重
for (Server server:servers) {
server.setDynamicWeight(server.getDynamicWeight()+server.getWeight());
}
//选出一个动态权重最大的Server
Server maxServer=servers.get(0);
for (int i = 1; i < servers.size(); i++) {
Server next = servers.get(i);
if (maxServer.getDynamicWeight()<next.getDynamicWeight()){
maxServer=next;
}
}
//再把本次选中的最大动态权重的Server的动态权重减去总权重
maxServer.setDynamicWeight(maxServer.getDynamicWeight()-total);
return maxServer;
}
public static void main(String[] args) {
for (int i = 0; i < 20; i++) {
Server server=getServer(i);
System.out.println("本次访问的是:"+server.getIp());
}
}
}
运行后展示: