一次HTTP connect-timeout的排查(上)

问题描述

公司的支付系统,支付核心调用网关系统时候,Tomcat接口服务偶尔会出现连接超时,以下为问题现象:

  1. 出现连接超时的时间点,该机器仍有正常的请求到网关系统,只是部分请求异常
  2. 偶发性质,一天或2天一次,且出现连接超时的时间段比较短暂
image.png

初步排查分析

  1. JVM GC情况:正常,分析GC日志,在发生连接超时时间段,系统只发生过几次YGC,每次STW时间在0.02 sec 左右
  2. 系统资源:CPU、I/O、磁盘使用率和平常一样,无异常
  3. Tomcat 线程数:在出现连接超时的时间段,活动线程数增长了100多个,当仍远低于1500最大工作线程数。
  4. 检查网络,发下在出现连接超时的时间段,TCP全连接队列发生了溢出


    image.png

    PS:只是临时找了个类似的图,当时时间的溢出图没找着

基于以上分析,初步怀疑是TCP全连接队列溢出导致出现了客户端连接超时的情况
接着查看溢出后,OS怎么处理:

# cat /proc/sys/net/ipv4/tcp_abort_on_overflow
0

tcp_abort_on_overflow 为0表示如果三次握手第三步的时候全连接队列满了那么server扔掉client 发过来的ack(在server端认为连接还没建立起来)

接着检查服务端的全连接队列长度,发现仅为100。 而出现连接超时情况时,全连接队列已经堆积了超过100个请求

采用ss -lnt | grep {server_port} 查看
[root@localhost ~]# ss -lnt | grep 10007
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 100 :::10007 :::*

解释一下上诉Recv-Q Send-Q的含义:

  • LISTEN 状态: Recv-Q 表示的当前等待服务端调用 accept 完成三次握手的 listen backlog 数值,也就是说,当客户端通过 connect() 去连接正在 listen() 的服务端时,这些连接会一直处于这个 queue 里面直到被服务端 accept();Send-Q 表示的则是最大的 listen backlog 数值
  • 非LISTEN状态:
    recv-Q 表示网络接收队列,表示收到的数据已经在本地接收缓冲,但是还有多少没有被进程取走
    send-Q 表示网路发送队列
    对方没有收到的数据或者说没有Ack的,还是本地缓冲区.
    如果发送队列Send-Q不能很快的清零,可能是有应用向外发送数据包过快,或者是对方接收数据包不够快。

检查tomcat的配置的backlog,确实默认的是100,关键代码如下:

   NioEndpoint.java
   serverSock.socket().bind(addr,getAcceptCount());
   /**
     * Allows the server developer to specify the acceptCount (backlog) that
     * should be used for server sockets. By default, this value
     * is 100.
     */
    private int acceptCount = 100;
    public void setAcceptCount(int acceptCount) { if (acceptCount > 0) this.acceptCount = acceptCount; }
    public int getAcceptCount() { return acceptCount; }

测试模拟

经过上诉分析,已经初步怀疑是由于tomcat backlog配置过小导致的客户端出现连接超时,在测试环境进行模拟(系统TCP相关参数与生产环境一致)

  • 将tomcat的backlog配置调小至1:(max-connections默认10000,max-threads默认1500)
-Dserver.tomcat.accept-count=1
  • 服务端接口:
    @ResponseBody
    @RequestMapping("/tomcatTest/{sleepSeconds}")
    public String testSMS(@PathVariable("sleepSeconds") long sleepMS) {
        try {
            TimeUnit.SECONDS.sleep(sleepMS);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "OK";
    }

并发10个http请求(连接超时时间配置为3s,服务端处理时长为10s),出现3个连接超时的情况

第3次异常:I/O error on GET request for "http://xxxx:19966/tomcatTest/10": connect timed out; nested exception is java.net.SocketTimeoutException: connect timed out exec: 3001
第5次异常:I/O error on GET request for "http://xxxx:19966/tomcatTest/10": connect timed out; nested exception is java.net.SocketTimeoutException: connect timed out exec: 3001
第4次异常:I/O error on GET request for "http://xxxx:19966/tomcatTest/10": connect timed out; nested exception is java.net.SocketTimeoutException: connect timed out exec: 3003
第0次正常 exec: 10020
第1次正常 exec: 10019
第7次正常 exec: 10018
第2次正常 exec: 10023
第9次正常 exec: 10020
第8次正常 exec: 10022
第6次正常 exec: 10327

在执行期间观察全连接队列情况,确实有出现溢出

netstat -s | grep -i "listen"
366 times the listen queue of a socket overflowed
366 SYNs to LISTEN sockets ignored

netstat -s | grep -i "listen"
368 times the listen queue of a socket overflowed
368 SYNs to LISTEN sockets ignored

将tomcat backlog调大后,在继续压测,没有在出现连接超时的情况。
依此测试结果,将线上的tomcat backlog增大至500后,观察一周均无在出现connect timeout的情况。

未完待续

  • 疑惑1:按道理全连接队列满了,但是客户端的连接请求是已经接收到SYN+ACK了,所以对于客户端来说该连接已经建立了,为啥会报connect timeout ? 应该是read timeout或者connect reset 。
  • 疑惑2:全连接队列满了,但客户端的请求认为连接ESTABLISH状态,可以继续发送数据请求。这时候服务端如何处理?
    带着这2个问题,后续将会模拟测试全连接队列满的情况,通过TCPDUMP抓包观察下
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,921评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,635评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,393评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,836评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,833评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,685评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,043评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,694评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,671评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,670评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,779评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,424评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,027评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,984评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,214评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,108评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,517评论 2 343