QA@IT

ソケット通信アプリによるファイルディスクリプタのリークについて

25603 PV

java8(jreはoracle)にて、RHEL6上で動かすソケット通信アプリを作成しています。
特定のIPアドレスとしか通信しないという前提があり、ソケットサーバ側にあたる実装として、以下のように実装していました。
※ロードバランサー(≠特定のIPアドレス)によるソケットリスナーポートの監視(5秒毎)があるため、iptablesとかで特定のアドレスとポートのみ外から受け入れる、ということをしていません。

// 唯一受け入れるIPアドレス
String hostAddr = "192.168.0.100";
ServerSocket listener = new ServerSocket();
try {
    listener.bind(new InetSocketAddress(12345));
    while (true) {
        Socket acceptSocket = listener.accept();
        InetAddress inetAddress = acceptSocket.getInetAddress();
        // アクセス元が上記の唯一受け入れるIPアドレスかをチェックする
        if (inetAddress != null && inetAddress.getHostAddress().equals(hostAddr) {
            // 別スレッドを立ててそちらでデータ通信
        }
    }
} catch (IOException e) {
    e.printStackTrace();
}

これをロードバランサー配下に配置し動作させたとき、このロードバランサーによるポート監視によりacceptが発生し、ソケットが成立しますが、IPアドレスチェックのため処理されず立ち消えていく、、、という公算だったのですが、2,3週間動かしていると、ソケット接続がリークするようで、lsof -p で上記アプリが掴んでいるものを一覧してみると、sock が「can't identify protocol」となった行が大量(2,000~3,000)に出力されるようになり、最後には「Too many open files」のためエラーになるようになりました。

ネットで検索したところ、この状態では同時にCLOSE_WAITが大量に発生することで、試しに netstat -an | grep <ポート番号> して確認してみたものの、こちらは上記で確認した lsof の結果行より遙かに少ない(200とか)、という状況でした。

lsof の結果と netstat の結果を時系列で確認したところ、両方ともしばらく増え続け、そしてがくっと減る、を繰り返しています。
netstat で確認した CLOSE_WAIT の数はちゃんと減っているものの、傾向としてlsof で参照出来る sock の接続数が増減しながらも次第に増えていっているようでした。

てっきり、CLOSE_WAIT が消えてしまえば lsof で参照出来る sock の接続も減るものと考えておりましたが、このように、lsof で参照できる sock の接続数が増減しながらも次第に増えていく理由として考えられることはなにかありますでしょうか。

上記コードにて、accept した socket が、唯一受け入れるIPアドレスからのものかどうかは関係なく、ちゃんと close してやれば良いようにも思えるのですが、リリース後のため試験環境がなく、さらに開発環境にロードバランサーがないため同じ環境での試験がし辛い状況で、確実に修正した、と言い切れる状況でなく、お知恵を拝借できますでしょうか。

  • ロードバランサからの接続を受入れたのち、closeすることで、リークしなくなりました。問題解決しましたので、取下げさせて頂きます。 -

回答

ロードバランサからの接続を受入れたのち、closeすることで、リークしなくなりました。問題解決しましたので、取下げさせて頂きます。

編集 履歴 (0)
ウォッチ

この質問への回答やコメントをメールでお知らせします。