目录
背景
目前的场景下,任务管理集群Apiserver有6个节点,agent集群的数量有36w+。之前的算法是agent通过注册中心获取Apiserver全量的节点数,并建立连接,所以每个Apiserver上维护了36w+的连接池。
当集群负载高时,扩容Apiserver节点并不能解决负载的问题,因为新节点并不能平摊其他节点的连接数,为此需要采用sharding的方式,让每个agent连接到部分的Apiserver节点,并且这个过程需要是幂等的,就是如果APiserver节点没有变更,那么agent节点获取到的Apiserver节点是不变的。
方案
采用的方案是<<SRE Google运维解密>>书中提到的子集选择算法二:确定性子集。
用golang实现了这个算法,在实际使用中,backends保存了Apiserver节点的Ip,clientId是将原client的Ip地址做了CRC处理,转成int,subsetSize就是子集的大小。
func Subset(backends []string, clientId int,subsetSize int) []string{
subSetCount := len(backends) / subsetSize
round := clientId / subSetCount
rand.Seed(int64(round))
rand.Shuffle(len(backends), func(i, j int) {
backends[i],backends[j]= backends[j],backends[i]
})
subsetId:= clientId%subSetCount
start := subsetId * subsetSize
return backends[start:start+subsetSize]
}