apache / apache/servicecomb-java-chassis

connection was closed问题指引

Open
#2,603 9 comments 0 reactions 0 assignees View on GitHub
connection&timeout
Dominant language
Java
Stars
1.9k
Forks
814
Avg merge
8d 23h
Merged PRs (30d)
1

Description

日志中出现类似错误比较常见,有些场景属于配置错误,有些场景属于性能问题,有些场景属于无法彻底解决的问题。这个 issue 主要帮助更好的定位和分析类似问题。

类似问题通过 label 做了标记: [查看](https://github.com/apache/servicecomb-java-chassis/issues?q=is%3Aissue+label%3Aconnection%26timeout+)

# 原理性介绍和定位技巧相关文章

[快速失败和重试](https://servicecomb.apache.org/references/java-chassis/zh_CN/references-handlers/fail-retry.html) : 介绍了随机故障发生的原理,以及在超时时间设置很短(需要快速失败的)的场景下的方案建议。
[性能问题分析和调优](https://servicecomb.apache.org/references/java-chassis/zh_CN/featured-topics/performance.html): 这类问题一般伴随性能问题发生。 介绍了如何分析性能问题,以及如何收集性能问题有关的日志。

# 关于 HTTP 连接
[TCP和HTTP连接的一些原理性介绍](https://blog.csdn.net/vikeyyyy/article/details/80760804)
微服务内部采用HTTP连接的情况下, 一般会复用连接,如果一个连接长时间不使用,则会回收。 常见的配置项有:

| 配置项 | 含义 |
| -- | -- |
|servicecomb.rest.client.connection.idleTimeoutInSeconds|客户端连接闲置时间。当客户端连接在规定的时间内,没有任何数据读入和写入,则会触发客户端主动关闭连接。[配置参考][client_config]|
|servicecomb.rest.client.connection.timeoutInMillis|连接建立的超时时间。如果在规定的时间内,没有成功建立连接,那么会关闭连接。[配置参考][client_config]|
|servicecomb.request.timeout|请求超时时间。客户端发出请求后,会等待服务端响应,如果在规定的时间内没有收到响应,那么客户端请求失败,并且会关闭连接。[配置参考][client_config]|
|servicecomb.rest.server.connection.idleTimeoutInSeconds|服务端连接闲置时间。当服务端连接在规定的时间内,没有任何数据读入和写入,则会触发服务端主动关闭连接。当服务端使用vert.x作为HTTP服务器的时候有效,如果使用其他web容器,比如Tomcat,相关配置请参考对应web容器的文档。[配置参考][server_config]|

建议 5<= servicecomb.request.timeout (毫秒 -> 秒) <= servicecomb.rest.client.connection.idleTimeoutInSeconds <= servicecomb.rest.server.connection.idleTimeoutInSeconds - 10 以避免随机故障和连接管理导致的随机失败概率。

# 关于随机故障

为了更好的理解随机故障,建议运行一下[最简单的性能测试用例](https://github.com/huaweicse/cse-java-chassis-benchmark),并打开metrics观察各个环节的耗时情况。 这里只提供一些简单的结论和随机故障发生的原理描述。

* 在端到端平均时延为1ms左右的情况下,仍然有一些请求的最大时延超过700ms。***超时随机故障在高并发场景下,是必然会出现的一个故障,超时时间设置越短,发生故障的概率越高***。
* 时延抖动最厉害的环节有
* 获取连接(getConnect):不可控因素包括网络故障、请求流量的突发性、大规模连接的管理。从metrics看出,平均获取连接时间小于1ms,但是最大可能等待100ms。
* 等待响应(waitResponse):不可控因素包括服务端请求排队和派发的随机性;网络排队和传输的随机性。从Server和Client的metrics可以看出,Server的最大时延是100ms左右,而Client等待响应的最大时延有超过500ms的。
* 唤醒等待线程(wakeConsumer):收到响应后,需要唤醒等待线程,等待线程进行后续处理。不可控因素主要体现为线程调度,CPU本身是被竞争的资源,CPU资源无法按照一个请求已经处理了多长时间进行分配。从metrics看出,平均唤醒等待线程时间小于1ms,但是最大可能等待200ms。
* 锁竞争:Client调用Server的handlersReq也有100ms左右的波动,这是因为启用了流控功能,流控功能存在锁。
* CPU竞争、内存竞争:对于一些纯CPU计算的逻辑,也存在时延波动,这些波动相对较小。比如Server端的执行逻辑,只是echo结果,平均时延可以忽略不计,最大时延也存在60ms的波动。这些波动的主要原因是CPU分时计算、垃圾回收等。可以看出,只要涉及到资源竞争:网络、线程池、连接池、CPU、锁等,就可能出现一个请求的处理被延迟。这个延迟的时间在平均时延小于1ms的情况下,可能高达500ms。 延迟的时间和并发请求数、TPS有很强的关联性。

***欢迎补充其他类似问题定位和处理经验***

[client_config]: https://servicecomb.apache.org/references/java-chassis/zh_CN/config-reference/rest-transport-client.html
[server_config]: https://servicecomb.apache.org/references/java-chassis/zh_CN/transports/rest-over-vertx.html

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.