Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AsyncWrite阻塞 event-loop 线程 #28

Closed
luyu6056 opened this issue Oct 21, 2019 · 6 comments
Closed

AsyncWrite阻塞 event-loop 线程 #28

luyu6056 opened this issue Oct 21, 2019 · 6 comments
Labels
help wanted Extra attention is needed question Further information is requested

Comments

@luyu6056
Copy link

你好,我实现了一个websocket服务器,客户端是异步收发信息,由于代码问题,客户端读取消息速度非常慢,发送消息很迅速。服务器每处理1个ws消息,就会回复一条十几字节的数据。
我的测试流程大概如下:
1.客户端打开一个tcp连接到gnet,预处理完毕后,连续发送1000次30字节的数据
2.服务器大概收到4次React,最后一次读取到1W字节(其实后面还有1W字节数据)
3.没有goroutine,顺序从1w字节里面一条一条消息解析,处理,并回复数据。
4.大概处理到200-300个消息的时候,整个server被阻塞,无法处理任何请求
打开pprof的goroutine查看,发现是gnet.(*conn).AsyncWrite->syscall.Syscall阻塞,代码如下

0x4ce654 syscall.Syscall+0x4 /data/server/go/src/syscall/asm_linux_amd64.s:18

0x9d3e99 golang.org/x/sys/unix.write+0x59 /mnt/e/sg_svr/src/golang.org/x/sys/unix/zsyscall_linux_amd64.go:1569

0x9d57d8 golang.org/x/sys/unix.Write+0x78 /mnt/e/sg_svr/src/golang.org/x/sys/unix/syscall_unix.go:173

0x9d579f github.com/panjf2000/gnet/netpoll.(*Poller).Trigger+0x3f /mnt/e/sg_svr/src/github.com/panjf2000/gnet/netpoll/epoll.go:58

0x9d795b github.com/panjf2000/gnet.(*conn).AsyncWrite+0x8b /mnt/e/sg_svr/src/github.com/panjf2000/gnet/connection.go:96

@panjf2000
Copy link
Owner

怎么你们提 issue 都不按 template 填的?不要删掉 template 内容自己填啊!这样缺少很多必要信息,

  1. 什么操作系统?
  2. Go 是哪个版本?
  3. gnet 是哪个版本?

还有,麻烦贴下完整代码,不然不太好具体分析。

@panjf2000 panjf2000 added the help wanted Extra attention is needed label Oct 21, 2019
@luyu6056
Copy link
Author

不好意思,这个是我疏忽了,我点提交issue 要求登录,登陆完返回的界面并没有template 的内容,是空的。
1.是wsl2 的ubuntu18.04
2.go 是1.13.1和1.13.3
3.版本是v1.0.0-beta.6
你那边想了解我go的项目代码,还是pprof打印的内容?

@panjf2000
Copy link
Owner

panjf2000 commented Oct 22, 2019

@luyu6056
代码和 pprof 输出都贴一下吧,要是不太方便发在 issue 里的话发我邮箱也行:panjf2000@gmail.com,
我现在看你描述现象,我的一个猜测是 eventfd 的写入数达到最大值了, 如 man 手册说的那样:

  write(2)
              A write(2) call adds the 8-byte integer value supplied in its
              buffer to the counter.  The maximum value that may be stored
              in the counter is the largest unsigned 64-bit value minus 1
              (i.e., 0xfffffffffffffffe).  If the addition would cause the
              counter's value to exceed the maximum, then the write(2)
              either blocks until a read(2) is performed on the file
              descriptor, or fails with the error EAGAIN if the file
              descriptor has been made nonblocking.

              A write(2) fails with the error EINVAL if the size of the
              supplied buffer is less than 8 bytes, or if an attempt is made
              to write the value 0xffffffffffffffff.

你代码里是不是大量调用 AsyncWrite ?导致把 eventfd 塞满了所以阻塞,不过它的最大值是很大的,正常来说不会触到最大值的,所以还是看下具体代码我再仔细分析下。

@panjf2000 panjf2000 added the question Further information is requested label Oct 22, 2019
@luyu6056
Copy link
Author

luyu6056 commented Oct 22, 2019

好消息是,我调用了goroutine去处理消息回调AsyncWrite,完成了连续1000个消息接发请求,我建议在代码上对AsyncWrite进行goroutine异步处理,等晚上回家我把问题代码发到你邮箱

@panjf2000
Copy link
Owner

panjf2000 commented Oct 22, 2019

@luyu6056
额。。。 AsyncWrite 方法本来就是设计来放到 goroutine 异步写的,README 也有相关说明:带阻塞逻辑的 Server,不过理论上就算是直接调用 AsyncWrite 也不应该会阻塞,所以先看看代码吧,我确认下是 bug 还是你的写法问题。

@panjf2000
Copy link
Owner

BTY, 温馨提示 v1.0.0-beta.7 已经 released 了,做了一些小优化,可以升级到这个版本😀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Extra attention is needed question Further information is requested
Projects
None yet
Development

No branches or pull requests

2 participants