tcp socketファイルのハンドルが漏れています。

3802 ワード

回転:http://www.178linux.com/2468
今日は一台のレディスマシンにsocketの個数が警告されているのを発見しました。これはとても奇妙な現象です。一つのredisサーバにいくつかのredisのインスタンスが展開されているので、開いているポートは限られているはずです。
1、netstat表示のtcp接続数は正常です。
netstat -n | awk '/^tcp/ {++state[$NF]} END {for(key in state) print key,"\t",state[key]}'
TIME_WAIT        221
ESTABLISHED      103
 
netstat  -nat |wc -l
368
確立されたtcp接続数は多くないです。
2、s s-sは大量のclosed接続を表示します。
ss -s
Total: 158211 (kernel 158355)
TCP:   157740 (estab 103, closed 157624, orphaned 0, synrecv 0, timewait 173/0), ports 203
 
Transport Total     IP        IPv6
*         158355    -         -        
RAW       0         0         0        
UDP       9         6         3        
TCP       116       80        36       
INET      125       86        39       
FRAG      0         0         0
closed 15624、多くのsocketはclosed状態にあります。
私のシステム監視カメラの値を取る方法は:
cat /proc/net/sockstat | grep sockets | awk '{print $3}'
158391
 
cat /proc/net/sockstat
sockets: used 158400
TCP: inuse 89 orphan 2 tw 197 alloc 157760 mem 16
UDP: inuse 6 mem 0
UDPLITE: inuse 0
RAW: inuse 0
FRAG: inuse 0 memory 0
多くのsocketはalloc状態にあり、すでにsk_が割り当てられています。buffer、しかもclosedにあります。
redisのfile discriptesは漏れがあって、カーネルに回収されていません。
3、真犯人の上の情報を追跡してsocket fdが漏れていると説明したら、lsof命令でシステムsockのファイルをチェックします。
lsof | grep sosck
java        4684      apps *280u     sock                0,6       0t0 675441359 can't identify protocol
java        4684      apps *281u     sock                0,6       0t0 675441393 can't identify protocol
java        4684      apps *282u     sock                0,6       0t0 675441405 can't identify protocol
java        4684      apps *283u     sock                0,6       0t0 675441523 can't identify protocol
java        4684      apps *284u     sock                0,6       0t0 675441532 can't identify protocol
java        4684      apps *285u     sock                0,6       0t0 675441566 can't identify protocol
Name列の値は「an’t identify protocol」であり、開いているファイルが見つからないことが分かります。
この表示は、javaプロセス(pid=4684)がsocket fdのリークが発生した状況です。
ps auxww | grep 4684
発見はredisマシン上のログ収集ツールflumeです。
4、解決策に良い方法がなく、簡単で乱暴なキルがscoket fdのプロセスを占有します。今日はflume agentを再開した後も、このような大量のclosed socket現象が発生することを発見しました。strace flumeプロセスは、flumeプロセスがすでにハングアップされていることを発見しました。
sudo strace -p 36111
Process 36111 attached - interrupt to quit
futex(0x2b80e2c2e9d0, FUTEX_WAIT, 36120, NULL
まず、ファイルの文脈が足りないのではないかと疑っています。googleが検索した資料もファイルのfdが足りないため、このような問題を引き起こしました。
私のマシンでは、最大で開くことができるファイルの数は1313137272で、ファイルのfd個数はまだ1/4近くが使われていません。
  lsof | wc -l 
10201
 
ulimit -a 
ulimit  -n
131072
この時、同僚に注意されました。他の大量の機械もこのような問題が発生しました。
これは、flumeの日誌を思い出しました。確認できます。flumeの日誌を見て、flumeにbrook 5が見つからないことをヒントを与えます。ナミは、kafkaクラスタではなく、4つのbrookしかないのではないです。この間のメールを思い出して、spark開発の同僚に来て、kakfクラスタを拡大しました。新しいクラスタノード9092ポートは、このredisが存在するマシンルームに対してアクセス権限を開放していません。
 [SinkRunner-PollingRunner-DefaultSinkProcessor] (kafka.utils.Logging$class.warn:89)  - Failed to send producer request 
with correlation id 63687539 to broker 5 with data for partitions [titan,4]
5、問題の再現
lsof: can’t identify protocolという文章では、pythonコードでこの状況を再現しています。
:
問題を解決する時、google検索は比較的早い方法です。Googleが出てきた結果が、逆に調査の方向に影響を与えることがあります。googleの検索結果を見て、まず感じたのは操作システムのmax open filesパラメータが小さすぎるからです。この原因ではないと発見した後。私の考えはまだカーネルパラメータが合理的に構成されているかどうかの考え方にとどまっています。他のマシンに展開されているflumeが同じ状況にあると知っていますが、flume自体に問題があったと気づき、strace flumeプロセスの状態とflumeのログを見に行きました。
回転:http://mdba.cn/?p=762