apache / servicecomb-java-chassis

ServiceComb Java Chassis is a Software Development Kit (SDK) for rapid development of microservices in Java, providing service registration, service discovery, dynamic routing, and service management features
Apache License 2.0
1.91k stars 812 forks source link

客户端和服务端建立连接的timeout是否设置大于1s更可靠一些? #2656

Closed fanjiwang1992 closed 2 years ago

fanjiwang1992 commented 2 years ago

https://github.com/apache/servicecomb-java-chassis/blob/8207a76ecb0620f989173ce5c5a776aaaea0af4d/transports/transport-rest/transport-rest-client/src/main/java/org/apache/servicecomb/transport/rest/client/TransportClientConfig.java#L125

当客户端和服务端建立连接第一次握手的时候,假设说服务器侧发生了全/半连接队列溢出而导致的丢包。那么从转换到客户端视角来看就是 SYN 包没有任何响应。 但是由于客户端在发出握手包的时候,开启了一个重传定时器。如果收不到预期的 synack 的话,超时重传的逻辑就会开始执行。 image 服务器在 connect 发出 syn 后就开启了重传定时器。 image

在定时器设置中传入的 inet_csk(sk)->icsk_rto 是超时时间,一般服务器的内核,重传定时器的初始值设置为了 1 秒。 image 服务器端发生了丢包,那么定时器到时后会进行回调函数 tcp_write_timer 中进行重传。 按照目前设置1s的话,当服务端发生了丢包,当前处理请求直接报错,可能不会触发进行握手重传

fanjiwang1992 commented 2 years ago

2654

develpoerX commented 2 years ago

按照现在这个逻辑,应该每次握手失败,一定会触发请求直接报错。正常请求失败,一般是有重试逻辑。这里的场景确实存在,但是正常前面的重试逻辑可以覆盖到这种场景。目前这个参数是可配置的,我建议保持这个默认值。

fanjiwang1992 commented 2 years ago

按照现在这个逻辑,应该每次握手失败,一定会触发请求直接报错。正常请求失败,一般是有重试逻辑。这里的场景确实存在,但是正常前面的重试逻辑可以覆盖到这种场景。目前这个参数是可配置的,我建议保持这个默认值。

应用层的请求重试 需要保证接口的幂等性,第一次握手失败丢包触发tcp层的重试能力可能会更合理一些,我这边也看了很多应用层的连接超时设置,很多都是设置大于1秒的,有3秒的,netty默认的是30s,我们框架设计的确是可配置的,主要很多业务很少会主动去配置它

liubao68 commented 2 years ago

看设计目标。 网络条件大部分情况都是非常好了,需要重传保证建连成功的场景越来越少, 保持较小的连接超时时间设置也是大量经验结果。 这样更适合于解决在网络确实不可达的一些情况下,快速失败的问题,这种情况反而更加频繁。

如果网络环境确实不好,可以考虑调大,但默认值1s应该是目前最合适的值的。 netty等三方件是很多年前设计的默认值,一直没修改,现实产品一般也会设置为较小的值,不具备参考意义。