Linux 下 tcp 通讯程序的阻塞问题

2016-02-19 20:31:31 +08:00
 eas

这个问题有些怪异。
我们之前有一些 win 下的 c++服务端程序,最近把他转到了 linux 下面。

服务端程序提供 tcp 接口来让客户端程序连接。服务端程序提供了一个简单的 echo 服务来确认双方正常连接(一般所说的心跳检测)。每个客户端 3 秒左右一个 echo 请求,服务端收到之后立刻回复一个 echo 回复包。

问题:
在差不过 200 个客户端程序连接上之后。 客户端发出的包,会有一定几率超过 1 秒才收到回复。

目前 c++ 底层是 epoll 直接操作的。为了防止 epoll 操作有问题。我们尝试了这个 echo 程序和客户端的程序的基础 echo 逻辑 都用 golang 重新实现了一遍。

目前,我们在公司内网\腾讯云、 centos6\centos7 、 裸 linux\docker 容器 NAT 。都测试过。
都或多或少,有这个现象。

我想问,这个是正常的吗? 还是 linux 下 tcp 有什么需要特殊设置的部分?

请大神略微指点一二。 或者略微指点一二关键字也可~~~。

6686 次点击
所在节点    Linux
39 条回复
yuuyuu
2016-02-19 22:17:53 +08:00
换个角度思考,不是 tcp 设置问题,是心跳协议设计的有问题?比如产生了伪心跳?
hncqp
2016-02-19 22:37:18 +08:00
貌似性能问题?压测过没
redsonic
2016-02-19 22:53:37 +08:00
如果是多核环境把服务器进程绑到靠后面的 cpu 上面再测。
zhicheng
2016-02-19 22:57:34 +08:00
nodelay ?
zado
2016-02-19 23:08:41 +08:00
我也遇到过类似的问题,后来发现传送的数据多一点延迟就会减少,以后就是每次传送都加上一定数量的无用数据.
billlee
2016-02-19 23:12:04 +08:00
@zado 你这个就真的是 TCP_NODELAY 的问题吧
skydiver
2016-02-19 23:12:19 +08:00
Nagle 算法?
Strikeactor
2016-02-19 23:13:48 +08:00
@zado Nagle 算法造成的?
redsonic
2016-02-19 23:16:28 +08:00
windows 也是缺省开 nagle 吧

在这里顺便问个问题,简单的心跳协议多数人会选择 tcp ? 为什么不用 udp 或 rawsocket ,简单而且延迟小。
k9982874
2016-02-19 23:27:06 +08:00
我觉得还是实现有问题,延迟一秒也太夸张了。检查一下线程有没有互锁或者资源竞争。
snnn
2016-02-19 23:30:12 +08:00
@redsonic TCP 不发心跳就会自动断。所以凡是用了 TCP 且需要保持长连接的,一定要加心跳!
snnn
2016-02-19 23:32:17 +08:00
楼主换 libevent 吧。因为你明显对 TCP 底层东西不熟,就不要自己抡 epoll 了。
redsonic
2016-02-19 23:44:48 +08:00
@snnn 我的意思是服务器程序另开一个线程用 udp 或 rawsocket 专门处理心跳,避开 tcp ,毕竟 tcp 是流,很多不熟悉的人会遇到 5 楼的那种问题,此外实际应用中还有 netfilter ,很多隐藏坑在等着新手。 其次 TCP 不设置 keepalive 的话根本不关心有没有数据来往。
billlee
2016-02-19 23:54:21 +08:00
@redsonic 很多时候另外用一个线程发心跳就不请作用了啊。不在 TCP 上用心跳 keep-alive, 服务器向给客户端发条消息,然后收到一个 reset, 原来这条连接被 NAT 网关丢掉了。
shakespark
2016-02-20 00:04:19 +08:00
1.抓包分析服务器端是否在收到后立刻发出响应,排除客户端和服务器之间的网络问题
2.如果抓包发现发送就慢,那就在收到和发出时加日志,先排除程序的问题
3.如果确定是程序收到后立刻发出答复了,那就要看 tcp 是啥原因没及时送出去了
redsonic
2016-02-20 00:04:26 +08:00
@billlee 嗯,我懂了,你说的心跳是业务心跳,就是如果业务代码跑顿了也算是丢心跳?
NAT 网关丢状态我确实没考虑到,受教。 之前一直没有遇到中间有 NAT 的情况,每台设备都有公网 ip 。
snnn
2016-02-20 00:16:40 +08:00
@redsonic 你没明白我的意思。你单开 UDP 做 keepalive 不解决 TCP 连接会断的问题啊。
redsonic
2016-02-20 00:44:30 +08:00
@snnn 14 楼说的那个和你的意思不一样吗? 其实就是客户发一些数据保持整条会话,防止中间丢状态,连接关闭。我已开始理解的是业务监控方面的问题。
skydiver
2016-02-20 04:10:38 +08:00
@snnn TCP 不发心跳不会断。发心跳只为了及时发现连接已经断了。要不然两边都不发数据,就发现不了断了。
redsonic
2016-02-20 04:54:58 +08:00
@skydiver 单纯从协议讲不会,但考虑到 NAT 还是有可能会断的,客户端的 NAT 发现长时间的会话空闲可能就会把该会话清除,另外运营商有一类叫做会话追踪的设备更不会长时间保持一个普通家用宽带用户的会话。简单讲就是连接保活。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/257745

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX