跑马竞赛算法是什么?是一种能良好感知服务端负载进行连接的负载均衡算法。当客户端与服务端进行长连接时,客户端需要选择合适的一台服务器节点起进行连接。客户端选择服务端的ip有多种方式,跑马竞赛算法相比于其他又有什么优点呢,怎么去实现,接下来一一讲解
客户端与服务端进行长连
客户端通过http请求服务端拿到服务端所有的ip节点后,开始要选择一个ip进行连接,怎么选择ip呢?
方式1:hash取模
首先获取到客户端的ip,对客户端ip的进行hash,然后对服务端节点数进行取模,模的位置就是ip的位置
//获取客户端ip
String clientIp = getClientIp();
//http请求服务端拿到服务端所有节点ip
List<String> serverIpList = getServerIp();
//获取客户端ip的hash值
int hash = clientIp.hash();
//用hash值对服务端节点数进行取模
int index = hash % serverIpList.size();
//获取到客户端与服务端进行长连接的ip
String chooseIp = serverIpList.get(index);
方式2:随机获取
利用math.random随机获取一个随机数,随机数就是ip所在的位置
//获取客户端ip
String clientIp = getClientIp();
//http请求服务端拿到服务端所有节点ip
List<String> serverIpList = getServerIp();
//获取0至服务端节点数的一个随机值
int randomNum = new Random().nextInt(serverIpList.size());
//获取到客户端与服务端进行长连接的ip
String chooseIp = serverIpList.get(randomNum);
方式3:跑马竞赛
虽然上面两种负载均衡算法能较平均的分配客户端与服务端的连接数,但是平均不一定代表各服务器承受的压力一致,例如各服务器的配置不一样,配置低的服务端在相同连接的情况下压力明显会比其他服务器大,那怎么选择服务器负载低的节点进行连接呢,或者说是客户端怎么知道哪台服务器的负载低。那么跑马竞赛算法就上场了
原理是 : 客户端对所有服务器都ping一下,ping连接最快的服务器,即是负载最低的服务器
代码实现:
//获取客户端ip
String clientIp = getClientIp();
//http请求服务端拿到服务端所有节点ip
List<String> serverIpList = getServerIp();
final List<String> sortServerIpList = Collections.synchronizedList(new ArrayList<String>());
f//定义好一个边界,当所有线程都启动后,统一一起去ping各服务器ip
final CyclicBarrier cyclicBarrier = new CyclicBarrier(serverIpList.size());
//队每一个服务器ip都开一个线程去ping,ping成功之后,放入sortServerIpList
for (final String serverIp : serverIpList) {
new Thread(new Runnable() {
public void run() {
Socket socket = null;
try {
//线程等待,等所有的线程都准备好了之后,同时去ping
cyclicBarrier.await();
socket = new Socket();
//ping服务器
socket.connect(new InetSocketAddress(serverIp, 8888), 5000);
//ping完之后,放入list
sortServerIpList.add(serverIp);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (null != socket) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
});
}
//获取到客户端与服务端进行长连接的ip,即ping的最快的一个服务器ip
String chooseIp = sortServerIpList.get(0);