转载请注明出处:https://oldnoop.tech/c/197.html
编写Server类
封装服务器的地址和权重信息
定义 服务器列表 和服务器 轮询列表
服务器列表是真实的有几台服务器
服务器轮询列表,按照权重数据,每个服务器在列表中设置多次
轮询操作
先获取当前的服务器轮询列表,
采用AtomicInteger原子操作类,先获取到当前存储的索引编号,加1操作,
为了防止累加超过上限,加1后对轮询的服务器个数取模,获取下一个服务器的索引编号,
然后使用原子类的CAS操作,防止此时有其他线程并发执行,
如果CAS操作成功,则从服务器轮询列表中取 索引编号 对应的 服务器
如果不成功,采用自旋,避免锁竞争
添加和删除服务器
采用Copy-And-Write模式
先复制当前的服务器列表,得到一个新的集合,
然后进行修改,
最后将修改后的数据设置回去
修改服务器列表
修改服务器列表的同时,修改轮询的列表,按照权重数字,分配 指定的次数
修改的时候,采用读写锁,目前暂时用到了写锁,
为了扩展考虑,如果有操作需要先读取并且要求防止并发的情形,可以采用读锁,减少锁竞争
为了避免 同一个服务器 被连续分布,造成瞬间压力过大,采用平滑分布的算法
先计算所有 服务器 的 配置权重 之和,然后将每个服务器的 当前权重设置为 0
然后轮询一遍,
每次轮询的时候,将每个服务器的 当前权重 加上 配置权重
找到本次轮询时,当前权重最大的服务器,本次返回这个服务器,
然后 将这个服务器的当前权重减去 配置权重之和
这样每次轮询,
最开始 加了一遍 配置权重之和(每个服务器加各自的配置权重),
最后 选中的服务器减了一次 配置权重之和
最后加到服务器轮询列表的服务器 是 平滑分布的,避免了同一服务器连续分布