dpvs中conhash实现
原理
● 一个RS对应的虚拟节点(副本)的个数
replicas = Weight * REPLICA
● 虚拟节点的 hash_key
hash_key= rs的地址信息(af,addr,port) + vnode_index
(vnode_index 为 虚拟节点的索引,范围为 [0, replicas- 1] )
hash完后,基于hash_value,将虚拟节点插入到红黑树中。
● 调度选择RS
从数据包中提取hash因子(sip/cid/ktp等),hash后得到 hash_value,在svc的红黑树中查找,返回键值大于等于hash_value 的最接近的节点。
● 增删改VS
○ 添加VS
在每个线程(master/slave)中,创建一个红黑树,将VS下的每个RS对应的虚拟节点添加到红黑树中。
○ 删除VS
将红黑树删除,删除VS下的RS以及VS自身。
○ 更改VS调度算法
基于旧的调度算法,清理对应的数据结构;基于新的调度算法,初始化对应数据结构。
● 增删改RS
○ VS下添加RS
一个RS对应多个虚拟节点,添加到VS的红黑树中;
○ VS下删除RS
将RS对应的多个虚拟节点,从红黑树中摘除;
○ 更改RS权重
将RS对应的旧的虚拟节点从红黑树中摘除,再基于新的虚拟节点个数,重新将新的虚拟节点插入到红黑树中。
如果RS健康检查不通过,Keepalived 会将RS的权重设置为0,所以不会将不健康的RS的虚拟节点插入到红黑树中。
分析
优缺点
● 优点
○ 增删改RS生效速度快
■ 在原有红黑树的基础上,增删虚拟节点,而不需要重新构建红黑树;
● 缺点
○ 占用内存较大
■ 同一个SVC在每个线程都有一个调度结构(红黑树)
■ 每个虚拟节点需要申请一次内存,占用较多内存空间
○ Slave线程中生成/更新红黑树占用时间较多
■ Slave线程中生成/更新红黑树会进行多个虚拟节点的申请/释放(rte_malloc/rte_free调用),如果消耗时间过长可能会导致网卡出现Imiss问题。
内存占用分析
(gdb) p sizeof(struct util_rbtree_node_s)
$1 = 48
(gdb) p sizeof(struct conhash_node)
$2 = 96
(gdb) p sizeof(struct virtual_node_s)
$3 = 16
(gdb) p sizeof(struct dp_vs_dest)
$4 = 256
(gdb) p sizeof(struct dp_vs_service)
$5 = 384由于cache line对齐,rte_malloc 申请 struct util_rbtree_node_s 结构时, size 部分为 64B,每个申请的结构会额外申请 elem_header, 其也是cache_line对齐,占用64B, 所以一共消耗 128B。
同理,rte_malloc 申请 struct virtual_node_s,共占用 128B;
其他
1) svc中增加、删除 rs:
红黑树的插入,删除虚拟节点都是 O(lgn) 的时间复杂度; n为 svc下 所有真实rs 的虚拟rs的个数;
2)调整 rs的 权重
调整 rs weight 则会将 之前的 rs 的虚拟节点都给删除了,然后基于新的 rs的 虚拟节点的个数,重新加入到 红黑树中;
如果 rs 的 健康检查失败,weight 设置为0,则红黑树中不会存在 rs 的 虚拟节点;
所以:红黑树中存在的节点都是 rs 的 weight 不为0 的 rs 的 虚拟节点;
3) RS调度:
红黑树的查找的时间复杂度为: O(lgn);
从红黑树中查找到某个节点,对应rs的虚拟节点,进而得到rs;
找到 rs 后,判断 rs 是否有效,有效则直接返回 rs,不可用则返回 null, 没有进而 fallback (即找到的