libgo icon indicating copy to clipboard operation
libgo copied to clipboard

tcp socket write大数据量时会阻塞

Open shuai132 opened this issue 4 years ago • 4 comments

在发送大量数据的时候,协程会直接阻塞,而不会切换协程。sys/socket和asio都有这个问题:

复现步骤: sample4_echo: https://github.com/yyzybb537/libgo/blob/781720f7ca6cf0de2d82e5a791a9c775cbad5aa3/tutorial/sample4_echo.cpp#L78-L82 修改buf部分:

    const int len = 1024*1024*10; // 10M
    char *buf = new char[len];

将会阻塞在write。

sample5_asio: https://github.com/yyzybb537/libgo/blob/781720f7ca6cf0de2d82e5a791a9c775cbad5aa3/tutorial/sample5_asio.cpp#L72-L73 修改为:

    std::string msg = "1234";
    msg.resize(1024*1024*10);

将会阻塞在write_some。

shuai132 avatar Jul 26 '19 16:07 shuai132

@yyzybb537 出现类似问题,连续调用write写入大量数据的时候,有时候会阻塞住,netstat 可以看到send buf 和 recv buf 都有大量数据,但是上层应用没有读走。

dearbird avatar Aug 07 '19 03:08 dearbird

@dearbird 你可以试试一帧大数据,我测得是必然阻塞,原因未知。 @yyzybb537 请问会是什么原因?感觉这个问题很严重哎。

shuai132 avatar Aug 16 '19 08:08 shuai132

我感觉是 epoll 边沿触发处理有问题。 我这边的例子,客户端是用原生socket实现的,服务端用libgo实现。 异常发生后,客户端进程退出,服务端无法感知,仍然是established状态,接收队列里有很大的值,应该是已经没有在读取数据了。 猜想应该是边沿触发后,数据没读完,之后就没在触发了。

dearbird avatar Aug 16 '19 08:08 dearbird

可能就是epoll的一些问题。必现的条件是:write的数据量要比较大(如1024102410) 最后会阻塞在这里: https://github.com/yyzybb537/libgo/blob/781720f7ca6cf0de2d82e5a791a9c775cbad5aa3/libgo/netio/unix/hook.cpp#L200

shuai132 avatar Aug 16 '19 11:08 shuai132