Skip to content

Commit a5c5b53

Browse files
authored
Create 关于主动健康检查模块出现很多问题的原因分析以及优化方案.md
1 parent e0788d0 commit a5c5b53

1 file changed

+47
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
### 关于主动健康检查模块出现很多问题的原因分析以及优化方案
2+
3+
#### 主动健康检查模块出现很多问题的原因分析
4+
##### `结论在前`
5+
- 从代码提交记录以及实现上看,该模块一开始可能并没有考虑动态增删节点的情况,加上在本地和共享内存中使用动态数组存储探测节点,节点状态以及数组索引容易错乱,代码不容易理解和维护,所以会遇到很多问题。 回到需求本身,主动健康检查模块功能其实比较简单,就是增删节点以及查询节点状态,对应红黑树的增删查操作,底层存储结构更适合使用红黑树, 不存在本地和共享内存中节点数组索引混乱以及通过节点delete状态复用数组元素空间的需求,从根本上避免了下述第1点和第2点带来的已发现以及尚未发现的问题,针对第3点合理控制共享内存锁粒度即可。
6+
##### 具体原因分析
7+
- 该模块在本地和共享内存中使用动态数组存储探测节点,需要处理好以下几点,但实际代码并没有处理好,很多问题稍微测试就能发现
8+
- 第1点-如何复用数组节点空间
9+
- 第2点-多进程时,如何保证本地节点正确关联到共享内存节点,如果通过index,需要保证本地数组index以及共享内存数组index的有效性以及关联的正确性
10+
- 第3点-多进程并发读写共享内存节点数组需要保证互斥
11+
###### 针对第1点-如何复用数组节点空间
12+
- 共享内存节点数组元素使用delete成员变量表示节点状态(PEER_NORMAL|PEER_DELETING|PEER_DELETED),当状态为PEER_DELETED表示节点可复用,需要正确处理好状态切换,本地节点数组元素使用delete成员变量表示节点状态(0|1)表示节点是否可以复用,程序到处都是节点状态判断的逻辑,一旦出现问题就会导致指向错误的节点。 --- 实际上不需要这么复杂且容易出错的处理逻辑。
13+
- 已发现以下问题:
14+
- status接口显示的节点index应该是共享内存的Index,而不是本地数组的Index
15+
- [修复多进程时健康状态显示的节点index不一致问题](http://git.koal.com/gw-server/ngx_healthcheck_module/-/merge_requests/30)
16+
- 查询节点状态时传递的index是共享内存节点数组Index,不能用来索引本地节点数组元素
17+
- [修复健康检测状态节点删除期间被重用导致的segfault问题](http://git.koal.com/gw-server/ngx_healthcheck_module/-/merge_requests/19/diffs)
18+
- [修复实际存在可用节点时报no_live_upstream的问题](http://git.koal.com/gw-server/ngx_healthcheck_module/-/merge_requests/23/diffs#1a83ab4fa783ce842f1dc782ac2309f05b5ed010)
19+
- 多进程时,某个进程检测到节点不通时,会将共享节点状态标记为PEER_DELETING,所以进程都检测到节点不通时,才会标记状态为PEER_DELETED,会导致会向已经不通的节点转发请求,实际上此时不应该转发
20+
- status接口没有判断本地节点delete状态过滤已删除的节点
21+
- [动态upstream删减后查询status会出现Segment Fault的问题](http://git.koal.com/gw-server/ngx_healthcheck_module/-/merge_requests/2/diffs?commit_id=981ff041c7d4a8c6b194aa1a1760eb2c47256db8)
22+
- 检查节点状态时没有判断delete值
23+
- [避免向已删除的动态节点转发请求](http://git.koal.com/gw-server/ngx_healthcheck_module/-/merge_requests/12/diffs#1a83ab4fa783ce842f1dc782ac2309f05b5ed010)
24+
- [修复未启用主动健康检测功能时存在的segfault问题](http://git.koal.com/gw-server/ngx_healthcheck_module/-/merge_requests/17/diffs)
25+
- 误用节点index索引
26+
- [修复误用节点索引导致偶发无可用后端节点的问题](http://git.koal.com/gw-server/ngx_healthcheck_module/-/merge_requests/21/diffs)
27+
28+
###### 针对第2点-多进程时,如何保证本地节点正确关联到共享内存节点,如果通过index,需要保证本地数组index以及共享内存数组index的有效性以及关联的正确性
29+
- 在增加/删除节点时,使用index建立本地节点和共享内存节点对应关系,查询节点状态时,获取共享内存节点数组Index下标对应元素。因为多进程时,本地和共享内存节点数组元素顺序通常会不一致,本地节点Index和共享内存中的Index很容易混乱
30+
- 已发现以下问题:
31+
- [修复健康检测节点索引错乱的问题-返回的index指向的是刚复用的节点](http://git.koal.com/gw-server/ngx_healthcheck_module/-/merge_requests/24/diffs)
32+
- [删除不必要的判断共享内存index有效性条件](http://git.koal.com/gw-server/ngx_healthcheck_module/-/merge_requests/32)
33+
34+
###### 针对第3点-多进程并发读写共享内存节点数组需要保证互斥
35+
- 已发现以下问题:
36+
- [修复后端节点地址连接失败时存在的死锁问题](http://git.koal.com/gw-server/ngx_healthcheck_module/-/merge_requests/3/diffs)
37+
- [修复健康状态节点复用情况下出现segfault的问题](http://git.koal.com/gw-server/ngx_healthcheck_module/-/merge_requests/15/diffs)
38+
- [修复同时使用共享内存锁与节点锁导致不恰当的并发问题](http://git.koal.com/gw-server/ngx_healthcheck_module/-/merge_requests/26/diffs)
39+
###### 其他问题
40+
- 因为底层数组结构是数组,在增加节点以及查找可复用节点时都需要for循环,当节点数量较多时,使用数组并不高效
41+
- 代码冗余太多,尤其是status模块和探测模块的数据结构定义完全一致,只是结构体名称不一样,调整结构体成员变量时两边都需要修改,其实只需要共同包含一份定义即可
42+
- 不完全支持配置探测时使用长连接
43+
- 官方仓库最近一次提交日期是 Jun 4, 2021,一直没有更新
44+
45+
46+
### `优化方案`
47+
- 基于上述分析,我针对之前写的[健康探测模块](https://github.com/alexzzh/ngx_health_detect_module)做了拓展,使其能和upstream相结合,完全支持`主动健康检查模块`的功能,主要区别就是底层存储结构使用的是红黑树以及部分功能增强,代码也更容易理解和维护。

0 commit comments

Comments
 (0)