【问题标题】:TCP parameter tuning on a per connection basis基于每个连接的 TCP 参数调整
【发布时间】:2015-09-30 15:57:11
【问题描述】:
我在具有高容量/高速互联网连接的 Linux 服务器上安装了监听程序,该程序接受并插入通过 GPRS/GSM 从远程监控站上传的 SQL 数据库数据。
问题是由于这些连接固有的缓慢高延迟特性,许多连接超时并且未完全插入 SQL 数据库。
我无法调整服务器 TCP 参数,以便可以使这些连接正常工作,因为其他服务器活动会受到影响。
我有什么方法可以调整 Linux 上的网络堆栈,以使高/低延迟连接同样正常工作?
【问题讨论】:
标签:
linux
performance
networking
tcp
【解决方案1】:
您通常无法确保您已在可能失败的 tcp 连接上完成事务。在 tcp 连接中实现这种协议的唯一方法是向commit(一个确认的命令)添加一个简单的命令,并将其放在每批命令的末尾(这些可以是由 tcp 分组缓冲)。该命令必须是两次握手命令 (commit -> ack),并且您必须在收到 command 时提交所有事务,如果在收到 commit 消息之前超时则回滚。移动设备在接收到ack 消息时必须考虑已提交(好吧,您不需要对事务进行编号,因为 TCP 确保了到达顺序和数据包的顺序)并考虑提交了它所针对的所有事务已收到ack 消息。考虑到 tcp 会超时并重新发送,因此您只需对每条消息使用一次发送,并且永远不要重新发送已发送的消息。如果您超时,只需断开连接并重新打开它,考虑到最后一个事务已中止。
事务编号可以很好地解决服务器丢失最后一个ack 的问题。如果下一个连接上的第一个事务 id 与最后一个连接的最后一个事务 id 相同,则可以假设客户端丢失了他的最后一个超时并再次重复最后一个事务。在这种情况下,你必须用ack 来回答它,并忽略客户端发出的所有命令(因为它们已经被服务器执行了。)
这对于在两个地方(服务器和客户端)都是正确的,并且不要尝试保存某些内容,否则您会丢失数据。
最后要注意的是,您没有 tcp 连接超时之类的东西,您必须在协议中自己实现它。一个 tcp 连接可以处于 READY 状态数周甚至数年而无需交换一个数据包,只是因为双方没有什么可说的。有一个 KEEP_ALIVE 选项,但您只能激活它,您无法修复超时延迟以使其失败。
所有这些检测故障的协议的一个很好的例子是 X 协议。这是一个基于事务的协议,其中有客户端发出的命令(有两种样式,带有响应的命令和不请求此类响应的命令),还有异步事件(从服务器到没有确认或命令请求它们的客户端)
在此协议中,您有一个所谓的SYNC 命令/服务,它允许客户端与服务器同步(当您想确保服务器已处理所有到现在为止的命令)。此外,服务器始终使用 最后执行的客户端请求的 隐式 请求 id(每个客户端命令递增)发送响应/事件,因此这节省了很多 @987654330 @ 命令(和往返延迟)到客户端。
【解决方案2】:
首先,我不得不说我不知道调整单个TCP连接参数的方法(如果有人知道方法,请分享!)。您可以为单个连接设置套接字选项,但我所知道的堆栈设置是全局的,在内核中设置。
其次,如果客户端是超时的,我认为服务器调整甚至没有帮助(我认为是这种情况,因为不清楚)。假设您调整服务器;您增加超时值并添加频繁的保活。如果客户端期望在给定的时间范围内得到服务器的响应,它会有什么好处?这是客户端在应用程序级别施加的限制(除非 TCP 连接本身超时,这是不太可能的,因为默认情况下它们非常健壮且持久)。