gnet
gnet copied to clipboard
UDP并发环境下一些问题
最近在为公司写高性能UDP服务,选择了gnet框架,目前发现2个比较明显的问题(都是针对于UDP的,TCP目前没有测过,也可能存在这些问题)。
- 在并发环境下,frame包错乱,需要同步的copy一份,大量的copy操作比较影响吞吐量;
- 在并发环境下,且在linux系统(乌班图),连接对象gnet.Conn的RemoteAddr()方法,有一定概率返回nil,在windows下是没有问题的(当时在本地开发完,一发布在测试环境就会因为空指针而挂掉);
截图如下:
复现案例 问题一在windows上就存在,linux是否有就没多考虑了,而问题二在windows上不存在,目前只在linux系统(乌班图)发现,复现案例的话其实一个简单demo就行了,重点是并发的去处理,而不是同步。
Thanks for opening a new issue. The team has been notified and will review it as soon as possible. For urgent issues and priority support, visit https://xscode.com/panjf2000/gnet
尽量按模板填 issue 内容,不然很多上下文信息都没有。gnet 版本?Go 版本?
在并发环境下,frame包错乱,需要同步的copy一份,大量的copy操作比较影响吞吐量;
这个是正常的,因为 gnet 底层的 buffer 是和 event-loop 绑定的,如果是在 event-loop 线程中同步操作则可以直接读取处理,否则如果是拿到 buffer 之后要异步去处理则需要 copy 一份出来。
在并发环境下,且在linux系统(乌班图),连接对象gnet.Conn的RemoteAddr()方法,有一定概率返回nil,在windows下是没有问题的(当时在本地开发完,一发布在测试环境就会因为空指针而挂掉);
你的客户端代码贴出来我看看?
gnet版本demo中有,go版本是1.16,复现的demo如下: https://gitee.com/lsm1998_admin/gnet_bug_demo
I am interested in your demo, so I did a test and fixed both issues. @lsm1998
Here is the working code.
func (*NetHandler) React(frame []byte, c gnet.Conn) (out []byte, action gnet.Action) {
rawPacket := append([]byte{}, frame...)
remoteAddr := c.RemoteAddr()
go func(packet []byte, addr net.Addr) {
// 模拟业务耗时
for i := 0; i < 10000; i++ {
_ = rand.Float64()
}
if checkFrameLength(&packet) {
/**
这个问题在windows和linux都有出现
异常结果见截图: 数据报打印异常结果.png
*/
fmt.Println(packet[0])
}
if addr == nil {
/**
在windows下没有问题,但是在linux会
异常结果见截图: RemoteAddr返回nil.png
*/
panic("RemoteAddr is nil!")
}
}(rawPacket, remoteAddr)
return
}
在并发环境下,frame包错乱,需要同步的copy一份,大量的copy操作比较影响吞吐量;
这个是正常的,因为 gnet 底层的 buffer 是和 event-loop 绑定的,如果是在 event-loop 线程中同步操作则可以直接读取处理,否则如果是拿到 buffer 之后要异步去处理则需要 copy 一份出来。
在并发环境下,且在linux系统(乌班图),连接对象gnet.Conn的RemoteAddr()方法,有一定概率返回nil,在windows下是没有问题的(当时在本地开发完,一发布在测试环境就会因为空指针而挂掉);
你的客户端代码贴出来我看看?
udp这块的异步处理要copy buffer吗? 我看字节的一篇文章, 他们实现了nocopy buffer, http://www.uml.org.cn/zjjs/202110201.asp 这样可以提高并发处理和较少gc压力, 不知道是否可以支持一下