TCP User Timeout (翻译)gRpc deadline 相关

原文

摘要

提供一个选项来设置Linux内核2.6.37及更高版本的TCP套接字选项TCP_USER_TIMEOUT。

背景

TCP_USER_TIMEOUT是一个套接字选项,从内核版本2.6.37开始在Linux上可用。如Linux手册页所述,“此选项将uint作为参数。当该值大于0时,它指定在TCP强制关闭相应的连接并将ETIMEDOUT返回给应用程序之前,传输的数据可能保持未确认的最大时间(毫秒)。如果将选项值指定为0, TCP将使用系统默认设置。"

在编写此提议时, gRPC Core面临着一个问题:数据可能在gRPC TCP层停留很长时间。对于网络中断,套接字无法接受更多的数据写入的情况,RPC可能被长时间阻塞。即使这样RPC的deadline已过期, GRRPC核心也无法关闭RPC ,因为TCP层仍然会引用用户数据。将TCP_USER_TIMEOUT设置为一个合理的值,将限制TCP层等待TCP数据包确认的最大时间,如果数据包没有及时确认,则关闭连接。这将最终释放gRPC TCP层对用户数据的引用,从而允许RPC及时失败。

Related Proposals:

Client-side Keepalive Server-side Connection Management

Proposal

gRPC已经有了一个检测连接失败的机制,称为keepalive。KEEPALIVE_TIMEOUT配置选项控制gRPC等待HTTP/2 ping确认的时间量。由于KEEPALIVE_TIMEOUT的有效目的类似于TCP_USER_TIMEOUT,因此建议重用该配置选项来设置套接字选项TCP_USER_TIMEOUT。由于TCP_USER_TIMEOUT仅在Linux内核2.6.37及更高版本上可用,因此此建议仅限于这些平台。

重用KEEPALIVE_TIMEOUT配置会有一些影响。

  • 保活超时值还将影响通过TCP发送的所有字节,而不仅仅是HTTP/2 ping。

  • KEEPALIVE_TIME配置为infinite将禁用保活,并且TCP_USER_TIMEOUT也不会被设置。系统默认值将继续有效。

  • 如果启用保活(KEEPALIVE_TIME不是无限长),TCP_USER_TIMEOUT的默认值将与保活超时相同,为20秒。

过小的TCP_USER_TIMEOUT值会影响高时延或丢包路径上的TCP传输。如果超时, 在确认到达之前发生,则连接将被断开。该值非常大,另一方面会增加gRPC检测断开连接所需的时间。因此,应用程序有责任在设置此选项时谨慎(prudent )行事。

相关议题

  1. #15889 - gRPC可能会无限期地被阻塞,而不遵守RPC的deadline。
  2. #15871 -重载网络 会阻止 keepalives 销毁连接。 注意,两个问题都发生在网络丢失时。#15889中第一个问题也可以通过修改这个问题解决。

这可以通过以下方式实现:

  • 制作用户数据的副本-这将导致巨大的用户成本
  • 添加API到gRPC-core 的TCP层,以便能够取消对某些流的写入-这将需要gRPC的TCP层理解流,这会打破层,更不用说这样做会增加的额外记账和开销。

即使采用目前已知的两个解决方案之一,#15871中提到的问题仍将存在,因为我们要求在某些场景下在关闭连接之前发送HTTP2 GOAWAY帧。

除了解决上述两个问题之外,TCP_USER_TIMEOUT还提供了一种相当可靠的方法,可以在不增加任何成本的情况下检测TCP连接中断,或者需要引入另一个可配置选项。

实现

  • C-Core - #16419设置TCP_USER_TIMEOUT套接字选项。

  • 对于JAVA,我们使用的OkHttp库不支持设置这样的选项。Netty with NIO也不支持此特性。Netty with epoll/kqueue允许设置此选项,并且用户已经能够配置此选项。

  • GO #2307设置TCP_USER_TIMEOUT套接字选项。

对于非Linux内核和2.6.37之前的Linux内核,我们还没有一个适用于所有人的替代方案。

c++ 客户端用法

   ChannelArguments channelArgs;
   channelArgs.SetInt(GRPC_ARG_KEEPALIVE_TIME_MS, KEEPALIVE_TIME_MS);
   channelArgs.SetInt(GRPC_ARG_KEEPALIVE_TIMEOUT_MS, KEEPALIVE_TIMEOUT_MS);
   channelArgs.SetInt(GRPC_ARG_KEEPALIVE_PERMIT_WITHOUT_CALLS, 1);
   channelArgs.SetInt(GRPC_ARG_SERVER_HANDSHAKE_TIMEOUT_MS, HANDSHAKE_TIMEOUT_MS);
   channelArgs.SetCompressionAlgorithm(GRPC_COMPRESS_GZIP);
   std::shared_ptr<grpc_impl::ChannelCredentials> channelCreds  = grpc::InsecureChannelCredentials();
   auto channel = grpc::CreateCustomChannel(address, channelCreds, channelArgs);

GRPC_ARG_KEEPALIVE_TIMEOUT_MS 其中 同时设置了 keepalive/TCP_USER_TIMEOUT timeout

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值