之前做项目的时候有个需求,需要把线上流量从主集群迁移到备用集群。由于线上的流量较高,如果直接把流量一下子全切到备用集群的话,会对备有集群有较大压力,同时也会对线上服务的接口性能有较大影响,造成耗时毛刺。
废话不多说,直接看代码
class Solution {
private Client clientA;
private Client clientB;
private Client currentClient = clientA;
/**
* 开始平滑切换流量的时间戳(默认为0,表示未开始切换)
*/
private AtomicLong startChangeTimeStamp = new AtomicLong(0);
/**
* 平滑切换的时间窗口,即在多长时间内从A集群切换到B集群
*/
private long changeClientDuration = 60000L;
public Client warmChangeClient(Client client) {
// 开始切换新 client
if (startChangeTimeStamp.get() != 0 && !currentClient.equals(client)) {
long exceptChangeEndTime = startChangeTimeStamp.get() + changeClientDuration;
if (System.currentTimeMillis() < exceptChangeEndTime) {
// 递进步长 (每多少毫秒概率增加1%)
long step = changeClientDuration / 100;
long passedTime = System.currentTimeMillis() - startChangeTimeStamp.get();
long percent = passedTime / step; // 随时间线性增长的数 [0, 100)
long random = Math.round(Math.random() * 100); // [0,100)
return random < percent ? client : currentClient;
} else {
startChangeTimeStamp.set(0);
lastClient = client;
}
}
return client;
}
}
总的来说还是基于随机数的算法,目前在线上运行稳定,简单粗暴。