InfluxDB TCP 连接数过多问题

公司使用了 InfluxDB 作为监控系统的存储后端, 在一次上线后,发现与InfluxDB 使用的 8086 端口相关的 TCP 连接数竟然多大 6K+ ,有时候甚至会逼近 1w ,这个数量对于一个只是在内部使用的监控系统来说, 无论如何都是无法接受的, 于是开始一系列的排查过程. 本文记录了这个问题的主要解决过程,算是对这一次杀 bug 过程的一个总结.

问题描述

因为业务的需要, client 对 InfluxDB 做 query 时, 会经过 server 的一个 proxy , 再由 proxy 发起到 Influxdb 的 query (http) 请求. 在我们的部署架构中, proxy 与 InfluxDB 是部署在同一个 server 上的. 使用命令

netstat -apn | grep 8086

可以看到大量处于 TIME_WAIT状态的 tcp 连接

...
tcp6       0      0 127.0.0.1:8086          127.0.0.1:58874         TIME_WAIT   -               
tcp6       0      0 127.0.0.1:8086          127.0.0.1:59454         TIME_WAIT   -               
tcp6       0      0 127.0.0.1:8086          127.0.0.1:59084         TIME_WAIT   -               
tcp6       0      0 127.0.0.1:8086          127.0.0.1:59023         TIME_WAIT   -               
tcp6       0      0 127.0.0.1:8086          127.0.0.1:59602         TIME_WAIT   -               
tcp6       0      0 127.0.0.1:8086          127.0.0.1:59027         TIME_WAIT   -               
tcp6       0      0 127.0.0.1:8086          127.0.0.1:59383         TIME_WAIT   -               
tcp6       0      0 127.0.0.1:8086          127.0.0.1:59053         TIME_WAIT   -               
tcp6       0      0 127.0.0.1:8086          127.0.0.1:58828         TIME_WAIT   -               
tcp6       0      0 127.0.0.1:8086          127.0.0.1:58741         TIME_WAIT   -               
tcp6       0      0 127.0.0.1:8086          127.0.0.1:59229         TIME_WAIT   -               
tcp6       0      0 127.0.0.1:8086          127.0.0.1:58985         TIME_WAIT   -               
tcp6       0      0 127.0.0.1:8086          127.0.0.1:59289         TIME_WAIT   -               
tcp6       0      0 127.0.0.1:8086          127.0.0.1:59192         TIME_WAIT   -               
tcp6       0      0 127.0.0.1:8086          127.0.0.1:59161         TIME_WAIT   -               
tcp6       0      0 127.0.0.1:8086          127.0.0.1:59292         TIME_WAIT   -               
tcp6       0      0 127.0.0.1:8086          127.0.0.1:59242         TIME_WAIT   -               
tcp6       0      0 127.0.0.1:8086          127.0.0.1:59430         TIME_WAIT   -   
...    

使用命令

netstat -apn | grep 8086 | grep TIME_WAIT | wc -l

进行计数, 会发现连接数会不断增加, 经过多次测试, 在公司环境中连接数至少都会达到 6k+. 这个问题必须要解决, 一方面是因为每条 tcp 连接都会占用内存, 另一方面系统的动态端口数也是有限的.

很明显这些连接几乎都处在 TIME_WAIT 状态,所以在继续往下走之前, 需要了解下 TIME_WAIT 这个关键字

TIME_WAIT

我们知道 一条 tcp 连接从开始到结束会经历多个状态, 换句话说, 可以把 一条 tcp 连接看成是一个 状态机. 这个状态图如下:

Paste_Image.png

可以看到, 凡是主动进行关闭 tcp 连接的一方, 都会经过 TIME_WAIT 这个状态.接下来再经过 2MSL 的时间后内核再完全释放相应的文件描述符和端口. (顺便提一下, MSL 是最大分段寿命, 是一个 TCP 分段可以存在于互联网系统中的最大时间, 在 Linux 下可以用命令

cat /proc/sys/net/ipv4/tcp_fin_timeout

查看 MSL的数值)

到这个地方可以推断出, 是 8086 端口(即 InfluxDB) 主动关闭了 tcp 连接, 导致挤压了大量的处于 TIME_WAIT 状态下的连接在等待内核释放. 于是自然而然得会想到, 能不能限制 InfluxDB 能打开的最大连接数, 让它尽可能复用每一条 tcp 连接?

果不其然, 在 InfluxDB 的配置文件中, 有这么一个配置项

# The maximum number of HTTP connections that may be open at once. connections that                                                  
# would exceed this limit are dropped.  Setting this value to 0 disables the limit.
max-connection-limit = 0 

我将其该为100, 然后重启数据库.

然而并没有什么卵用, 看来还是得继续想办法.

查看 InfluxDB 源码

接下来使用 curl 查看 Influxdb 返回的 http header

HTTP/1.1 200 OK
Connection: close
Content-Type: application/json
Request-Id: 95e5b54b-6af3-11e7-8001-000000000000
X-Influxdb-Build: OSS
X-Influxdb-Version: 1.3.0rc1
Date: Mon, 17 Jul 2017 13:26:48 GMT
Transfer-Encoding: chunked

可以看到 Connection 字段被设置为 close .
因为已经确定我们用 Go 编写的用于对 InfluxDB 发起 http 请求的 proxy 已经正确复用了 tcp 连接 , 所以就感觉问题应该是处在了 InfluxDB 上, 所以接下来就开始翻开 InfluxDB 的源码查看究竟.

文章中提到的 InfluxDB 版本为 1.2 , 处理 query 请求的代码在services/httpd/handler.go 中, 函数签名为

func (h *Handler) serveQuery(w http.ResponseWriter, r *http.Request, user meta.User)

在其中发现一句代码

rw.Header().Add("Connection", "close")

看到这里感觉一切豁然开朗了, 确实是 Influxdb 主动关闭的连接, 并且通知 client (也就是文中提到的 proxy ) 在请求完成后也关闭连接.

为了验证这一点, 我将上面那句代码注释掉后重新编译 InfluxDB, 在 client 正确复用连接的情况下, 连接数确实可以保持在 10 以内.

现在问题就变成, InfluxDB 为何要这样设计 ?

Paste_Image.png

后续

在 Github 的一个 issue 上, 我向 InfluxDB 的官方反映了这个问题, 官方也注意到了, 可能在接下来的 1.3 版本会修复这个问题, 拭目以待.

--------- 更新 ------
Influxdb 之所以会强制关闭连接, 是因为 Go 对复用的连接使用

ResponseWriter.CloseNotify()

获取通知的时候会有问题, 于是他们强制 client 在后续请求中重新建立连接而不是选择复用.不过 InfluxDB 对连接的关闭通知做了一些另外的处理, 所以上面的那句代码可以去掉.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,968评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,601评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,220评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,416评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,425评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,144评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,432评论 3 401
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,088评论 0 261
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,586评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,028评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,137评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,783评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,343评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,333评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,559评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,595评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,901评论 2 345

推荐阅读更多精彩内容