nginx + Jetty - 数千の接続が LAST_ACK で停止

nginx + Jetty - 数千の接続が LAST_ACK で停止

私はjailを備えたFreeBSDマシンを持っています。具体的には、1つはnginxを実行し、もう1つはJetty(埋め込みモード)経由でリクエストを受け入れるJavaプログラムを実行します。

Jettyは常に500件/秒以上のリクエストを受信して​​おり、最近は常に60,000nginx と jetty 間の LAST_ACK 状態の接続。

すべての接続の分散(他のサービス、特に php-fpm を含む)

root@host:/root # netstat -an > conns.txt
root@host:/root # cat conns.txt | awk '{print $6}' | sort | uniq -c | sort -n
18 LISTEN
112 CLOSING
485 ESTABLISHED
650 FIN_WAIT_2
1425 FIN_WAIT_1
3301 TIME_WAIT
64215 LAST_ACK

nginx -> jetty 接続の分散

root@host:/root # cat conns.txt | grep '10.10.1.57' | awk '{print $6}' | sort | uniq -c | sort -n
1 
3 CLOSE_WAIT
3 LISTEN
18 FIN_WAIT_2
125 ESTABLISHED
64193 LAST_ACK

すべてのリクエストで接続を完全に閉じることを希望します。クライアントのリクエストは互いに約 10 分間隔で行われるため、接続を閉じる必要があります。

いくつかのつながりは、

tcp4       0      0 10.10.1.50.46809       10.10.1.57.9050        LAST_ACK
tcp4       0      0 10.10.1.50.46805       10.10.1.57.9050        LAST_ACK
tcp4       0      0 10.10.1.50.46797       10.10.1.57.9050        LAST_ACK
tcp4       0      0 10.10.1.50.46794       10.10.1.57.9050        LAST_ACK
tcp4       0      0 10.10.1.50.46790       10.10.1.57.9050        LAST_ACK
tcp4       0      0 10.10.1.50.46789       10.10.1.57.9050        LAST_ACK
tcp4       0      0 10.10.1.50.46771       10.10.1.57.9050        LAST_ACK
etc..
  • Jetty側ではmaxIdleTime2000に設定しました。これ以前はすべての接続が入っていましたESTABLISHEDが、今はLAST_ACK
  • Jetty側ではConnection: close(つまりresponse.setHeader(HttpHeaders.CONNECTION, HttpHeaderValues.CLOSE);)を設定しました
  • Jetty は開いている接続を多数報告することはなく、常にごく少数です。
  • PF/IPFWは現在使用されていません
  • nginx -reset_timedout_connectionオン

nginx または jetty で接続を強制的に閉じる方法がわかりません。これは、リクエストが完了した後にソケットを完全に閉じるように Jetty で修正する必要があるだけなのでしょうか?

よろしくお願いします

編集:プロキシ設定用の nginx 設定を忘れてしまいました。

    proxy_pass              http://10.10.1.57:9050;
    proxy_set_header        HTTP_X_GEOIP $http_x_geoip;
    proxy_set_header        GEOIP_COUNTRY_CODE $geoip_country_code;
    proxy_set_header        X-Real-IP $remote_addr;
    proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header        Host $http_host;
    proxy_set_header        Connection "";
    proxy_http_version      1.1;

編集2:Jetty に 経由で接続を閉じるように強制してもrequest.getConnection().getEndPoint().close()何も起こりません。接続が閉じられていることは明らかです ( にあるようにLAST_ACK) が、なぜこれを超えないのでしょうか。何らかの理由で Nginx がバックエンドへの接続を開いたままにしているのでしょうか。

答え1

さて、ついにジェティを説得して優しく遊ばせることができました。

要約すると、マシン全体の接続は現在次のようになります。

24 LAST_ACK
36 CLOSING
117 FIN_WAIT_2
175 ESTABLISHED
351 FIN_WAIT_1
4725 TIME_WAIT

そしてnginxとJettyの間で

1 FIN_WAIT_2
3 LISTEN
14 ESTABLISHED

私はすでに、この便利なメソッドを使用して、接続全体を閉じておりEndPoint( を呼び出すclose()と、EndPoint基になる が閉じられますSocketChannel)、

private void finishRequest(String message, Request baseRequest, HttpServletResponse response) throws IOException {
    ByteArrayISO8859Writer writer = new ByteArrayISO8859Writer(1500);
    writer.write(message);
    writer.flush();

    // set the content length
    response.setContentLength(writer.size());

    // write the response
    OutputStream outputStream = response.getOutputStream();
    writer.writeTo(outputStream);

    // close the streams
    outputStream.close();
    writer.close();
    baseRequest.getConnection().getEndPoint().close();
}

( クライアントに送信するのは最大 1 行だけなので、特別な処理は必要ありません )

しかし、それでもサーバー全体がLAST_ACKでいっぱいになってしまうのです...これらを最終的に消すことができたのは、有効にすることでしたSO_LINGER(そしてタイムアウトなしでソケットを強制的にすぐに閉じるようにしました)

connector.setSoLingerTime(0);

関連情報