1 概述
Dubbo-Getty 1.4.10 版本带来了一些重要的改进和修复,旨在提高性能和稳定性,不过依然坚持 “Getty 只考虑使用 Go 语言原生的网络接口,如果遇到网络性能瓶颈也只会在自身层面寻找优化突破点” 【Go 语言网络库 getty 的那些事】。
以下是本次发布的主要亮点和更新。
2 主要更新
2.1 Timer 优化算法禁用
2016 年开始构建 getty 网络库时,当时 Go 语言的 timer 实现很低效,有一个有名的 “一把全局大锁” 的问题 (the global timers mutex),详见 issue https://github.com/golang/go/issues/15133 。Getty 借鉴当时 fasthttp 的实现,在使用 SetReadDeadline 和 SetWriteDeadline 两个函数时,有如下类似代码:
// Optimization: update read deadline only if more than 25%
// of the last read deadline exceeded.
// See https://github.com/golang/go/issues/15133 for details.
currentTime = time.Now()
if currentTime.Sub(t.rLastDeadline.Load()) > t.rTimeout.Load()>>2 {
if err = t.conn.SetReadDeadline(currentTime.Add(t.rTimeout.Load())); err != nil {
// just a timeout error
return 0, perrors.WithStack(err)
}
t.rLastDeadline.Store(currentTime)
}
2021 年拼多多的朋友发现这项 “优化” 会造成超时时间 “漂移” 问题,详见 https://github.com/AlexStocks/getty/issues/14#issuecomment-972583219。
近几年随着 Go Timer 的性能优化,Go 1.1x 版本能做到把每个 timer 绑定多核减小锁粒度,Go 1.2x 已经通过 “时间轮” 进一步优化,timer 已经没有了 CPU 使用率过高的问题,详见 https://github.com/golang/go/issues/15133#issuecomment-271571395 。
所以在 PR https://github.com/apache/dubbo-getty/pull/109 中禁用了 SetReadDeadline 和 SetWriteDeadline 优化算法。这个更改将有助于减少不必要的性能开销,并确保应用程序能够更高效地处理 I/O 操作。
2.2 Go 版本升级
PR https://github.com/apache/dubbo-getty/pull/112/files 将 Go 语言版本从 1.14 升级到 1.20。这个升级不仅带来了 Go 语言的新特性和改进,还提高了整体的安全性和稳定性:
- 使用 os.ReadFile 替换了 ioutil.ReadFile
- 使用 net.Timeout 替换了 net. Temporary
2.3 添加网络任务处理时先 check 连接是否关闭
当请求过多时,Getty 一直在调用 encode 或者 decode 逻辑导致 CPU 飙升,从消息和请求时间结合看的话,应该是请求过多。
在 PR https://github.com/apache/dubbo-getty/pull/108 中,在 conn close 的时候直接把相关过时的网络请求抛掉,不做这些耗 CPU 的逻辑。
2.4 修复 TLS 死循环 bug
Getty 支持 TCP/UDP/Websocket 三种通信协议,在 TCP 之上还提供了 TLS 安全通信,近期杭州一家公司的朋友在使用 TLS 时发现一个死循环 bug:把 demo/hello/tls/server/server.go 服务跑起来,然后用 telnet 127.0.0.1 8090服务端程序就会陷入死循环,把一个 CPU 打满。
其原因是 TLS 握手时没有设置超时时间。这位朋友在 PR https://github.com/apache/dubbo-getty/pull/115 中修复了该 bug。
3 贡献者
感谢以下贡献者对 Dubbo-Getty 1.4.10 版本的支持和贡献【排名不分先后,依据字母序列】:
- DMwangnima
- hongshengjie
- Lvnszn
alexstocks/getty 作为 dubbo-getty 的上游仓库,已经在 PR https://github.com/AlexStocks/getty/pull/79 中吸收了本次更新,将要发布的 alexstocks/getty v1.3.3 中将会包含这些更新。