Skip to content

Commit 5d52260

Browse files
committed
更新README
1 parent 80b85df commit 5d52260

File tree

2 files changed

+100
-85
lines changed

2 files changed

+100
-85
lines changed

README.md

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
- 并发协程间的资源竞争
4343

4444
- 连接关闭时的任务执行完整性问题
45-
45+
4646
改进方案 :
4747

4848
- 状态管理 :
@@ -81,12 +81,46 @@
8181
8282
- 管道关闭时无残留数据
8383
84-
- 经验总结:
84+
经验总结:
85+
86+
- 协程同步应优先使用简单同步原语
87+
88+
- 资源释放需保证执行完整性
89+
90+
- 异常处理应区分系统级和业务级容错
91+
92+
- 避免过度设计,当前方案在代码复杂度和功能需求间取得平衡
93+
94+
3. 服务端异步启动后 stop 在大量并发连接下的死锁问题
8595
86-
- 协程同步应优先使用简单同步原语
96+
现象:服务端在异步启动后调用 Stop 方法时,面对大量并发连接场景,程序因死锁异常退出。
97+
98+
问题本质 :
99+
100+
- 锁竞争与链式调用 :
101+
102+
- 原connmanager模块使用sync.Mutex保护连接集合(map),Stop操作需遍历所有连并逐个调用conn.Stop()。
87103
88-
- 资源释放需保证执行完整性
104+
- conn.Stop()内部可能再次申请锁(如连接自身的状态锁),导致嵌套锁竞争 。
105+
106+
- 当connmanager的锁未释放时,调用conn.Stop()可能因等待连接内部锁而阻塞,形成死锁链。
107+
- 资源清理顺序缺陷 :
89108
90-
- 异常处理应区分系统级和业务级容错
109+
- 未明确资源释放的优先级,导致连接关闭时可能仍在处理旧任务或接收新请求。
110+
111+
解决方案 :
112+
113+
- 数据结构优化 :
114+
- 替换为sync.Map :
115+
将连接集合从普通map+Mutex替换为sync.Map,利用其无锁并发特性,避免遍历时的锁竞争。
116+
- 原子状态管理 :
117+
使用atomic包标记服务端状态,确保状态变更的原子性,避免竞态。
91118
92-
- 避免过度设计,当前方案在代码复杂度和功能需求间取得平衡
119+
经验总结 :
120+
121+
- 避免嵌套锁 :优先使用并发安全的数据结构(如sync.Map)减少锁粒度。
122+
- 资源生命周期管理 :明确资源创建、使用、销毁的顺序,避免循环依赖。
123+
- 优雅退出设计 :
124+
- 分阶段关闭(先停读,再停写,最后清理)。
125+
- 通过原子状态和WaitGroup确保执行完整性。
126+
- 压测验证必要性 :高并发场景必须通过压力测试暴露隐藏的竞态和死锁问题。

log.md

Lines changed: 60 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -26,109 +26,90 @@
2626

2727
问题本质 :
2828

29-
- 连接异常处理机制缺陷
30-
31-
- 并发协程间的资源竞争
32-
33-
- 连接关闭时的任务执行完整性问题
29+
- 连接异常处理机制缺陷
30+
31+
- 并发协程间的资源竞争
3432

33+
- 连接关闭时的任务执行完整性问题
34+
3535
改进方案 :
3636

37-
- 状态管理 :
38-
39-
- 新增原子变量标记连接状态
40-
41-
- 使用sync.WaitGroup跟踪任务执行
37+
- 状态管理 :
4238

43-
- 执行流程优化 :
39+
- 新增原子变量标记连接状态
40+
41+
- 使用sync.WaitGroup跟踪任务执行
42+
43+
- 执行流程优化 :
4444

45-
```
46-
// 连接异常处理流程
47-
reader检测异常 -> 设置关闭状态 -> 触发stop流程 ->
48-
wg.Wait等待已接收任务 -> workpool继续执行遗留任务 ->
49-
writer无脑发送(忽略错误) -> wg.Done -> 清理资源(关闭msg管道等)
50-
```
45+
```
46+
// 连接异常处理流程
47+
reader检测异常 -> 设置关闭状态 -> 触发stop流程 ->
48+
wg.Wait等待已接收任务 -> workpool继续执行遗留任务 ->
49+
writer无脑发送(忽略错误) -> wg.Done -> 清理资源(关闭msg管道等)
50+
```
5151
52-
- 容错设计 :
53-
- 任务提交阶段不进行连接状态检查
52+
- 容错设计 :
53+
- 任务提交阶段不进行连接状态检查
54+
55+
- 写协程统一处理发送异常
5456
55-
- 写协程统一处理发送异常
56-
57-
- 提供用户级熔断接口(通过handler提前return实现)
57+
- 提供用户级熔断接口(通过handler提前return实现)
58+
59+
- 性能考量 :
5860
59-
- 性能考量 :
61+
- 采用"尽力而为"策略处理异常连接的任务
62+
63+
- 通过wg.Wait()保证已接收任务执行完毕
64+
65+
- 优雅关闭时确保:
6066
61-
- 采用"尽力而为"策略处理异常连接的任务
67+
- reader先行退出
6268
63-
- 通过wg.Wait()保证已接收任务执行完毕
69+
- writer处理完消息队列
6470
65-
- 优雅关闭时确保:
66-
67-
- reader先行退出
68-
69-
- writer处理完消息队列
70-
71-
- 管道关闭时无残留数据
71+
- 管道关闭时无残留数据
7272
7373
经验总结:
7474
75-
- 协程同步应优先使用简单同步原语
76-
77-
- 资源释放需保证执行完整性
78-
79-
- 异常处理应区分系统级和业务级容错
80-
81-
- 避免过度设计,当前方案在代码复杂度和功能需求间取得平衡
75+
- 协程同步应优先使用简单同步原语
76+
77+
- 资源释放需保证执行完整性
78+
79+
- 异常处理应区分系统级和业务级容错
80+
81+
- 避免过度设计,当前方案在代码复杂度和功能需求间取得平衡
8282
8383
3. 服务端异步启动后 stop 在大量并发连接下的死锁问题
8484
8585
现象:服务端在异步启动后调用 Stop 方法时,面对大量并发连接场景,程序因死锁异常退出。
8686
8787
问题本质 :
8888
89-
- 锁竞争与链式调用 :
89+
- 锁竞争与链式调用 :
9090
91-
- 原connmanager模块使用sync.Mutex保护连接集合(map),Stop操作需遍历所有连并逐个调用conn.Stop()。
92-
93-
- conn.Stop()内部可能再次申请锁(如连接自身的状态锁),导致嵌套锁竞争 。
91+
- 原connmanager模块使用sync.Mutex保护连接集合(map),Stop操作需遍历所有连并逐个调用conn.Stop()。
92+
93+
- conn.Stop()内部可能再次申请锁(如连接自身的状态锁),导致嵌套锁竞争 。
9494
95-
- 当connmanager的锁未释放时,调用conn.Stop()可能因等待连接内部锁而阻塞,形成死锁链。
96-
- 资源清理顺序缺陷 :
97-
98-
- 未明确资源释放的优先级,导致连接关闭时可能仍在处理旧任务或接收新请求。
95+
- 当connmanager的锁未释放时,调用conn.Stop()可能因等待连接内部锁而阻塞,形成死锁链。
96+
- 资源清理顺序缺陷 :
97+
98+
- 未明确资源释放的优先级,导致连接关闭时可能仍在处理旧任务或接收新请求。
9999
100100
解决方案 :
101101
102-
- 数据结构优化 :
103-
- 替换为sync.Map :
104-
将连接集合从普通map+Mutex替换为sync.Map,利用其无锁并发特性,避免遍历时的锁竞争。
105-
- 原子状态管理 :
106-
使用atomic包标记服务端状态(如isRunning),确保状态变更的原子性,避免竞态。
102+
- 数据结构优化 :
103+
- 替换为sync.Map :
104+
将连接集合从普通map+Mutex替换为sync.Map,利用其无锁并发特性,避免遍历时的锁竞争。
105+
- 原子状态管理 :
106+
使用atomic包标记服务端状态,确保状态变更的原子性,避免竞态。
107107
108-
流程控制优化 :
109-
```
110-
// 服务端Stop流程
111-
func (s *Server) Stop() {
112-
atomic.StoreInt32(&s.isRunning, 0) // 原子标记停止状态
113-
s.connManager.Range(func(conn Conn) {
114-
conn.Stop() // 并发安全地逐个关闭连接
115-
})
116-
// 等待所有连接关闭完成(通过WaitGroup或通道通知)
117-
}
118-
```
119-
- 连接关闭一致性 :
120-
拒绝新连接 :在Stop开始时立即关闭监听套接字。
121-
处理历史任务 :确保已接收的任务执行完毕(如通过sync.WaitGroup跟踪任务)。
122-
优雅退出 :
123-
先关闭读协程(reader),停止接收新数据。
124-
等待写协程(writer)处理完消息队列。
125-
最后清理资源(如关闭通道)。
126-
127-
经验总结 :
128-
129-
避免嵌套锁 :优先使用并发安全的数据结构(如sync.Map)减少锁粒度。
130-
资源生命周期管理 :明确资源创建、使用、销毁的顺序,避免循环依赖。
131-
优雅退出设计 :
132-
分阶段关闭(先停读,再停写,最后清理)。
133-
通过原子状态和WaitGroup确保执行完整性。
134-
压测验证必要性 :高并发场景必须通过压力测试暴露隐藏的竞态和死锁问题。
108+
经验总结 :
109+
110+
- 避免嵌套锁 :优先使用并发安全的数据结构(如sync.Map)减少锁粒度。
111+
- 资源生命周期管理 :明确资源创建、使用、销毁的顺序,避免循环依赖。
112+
- 优雅退出设计 :
113+
- 分阶段关闭(先停读,再停写,最后清理)。
114+
- 通过原子状态和WaitGroup确保执行完整性。
115+
- 压测验证必要性 :高并发场景必须通过压力测试暴露隐藏的竞态和死锁问题。

0 commit comments

Comments
 (0)