原文地址:https://zhuanlan.zhihu.com/p/22474724
作者的结论没写好,我来说两句。。
结论:
Docker swarm自己有个函数,叫setTcpUserTimeout,这个函数调用了conn.File()方法,将tcp的fd变成了blocking,而且没有关闭对应的fd。相当于每次设定tcpUserTimeout参数,再去read一下fd,都会产生一个新的线程。因为老的线程在读fd,而fd被设置成blocking了,于是golang的运行时只好再开一个新的。
解决方法:
不要用swarm的这个方法,或者提交到上游让swarm fixed掉,或者自己调用SetsockoptInt……
好奇八卦了一下TCP_USER_TIMEOUT是什么:根据RFC 5482,这个选项是用来跟对端沟通TCP超时时间的。顺带看了一下,有关TCP超时的RFC还包括:[RFC0793] [RFC1122]。之前,TCP有类似的超时选项TCP Keepalive。但是,TCP Keepalive是一个不建议打开的选项。因为委员会觉得这样会浪费带宽,引起不必要的网络中断。说白了,TCP是一组计时器组成的状态机,设计者是希望中间的电路中断、重新路由之类的变动,不会影响到两端的TCP状态。
待续
有疑问加站长微信联系(非本文作者)