私はjailを備えたFreeBSDマシンを持っています-特に2つはnginxを実行し、もう1つはJetty(組み込みモード)を介してリクエストを受け入れるJavaプログラムを実行します
Jettyは常に500リクエスト/秒以上を受信しますが、最近、nginxとjettyの間のLAST_ACK状態で常に接続が60,0を超えるという問題が発生しています。
すべての接続の配布(他のいくつかのサービス、特に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の分布->桟橋接続
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..
maxIdleTime
を2000に設定しました。これまではすべての接続がESTABLISHED
にありましたが、現在はLAST_ACK
になっています。Connection: close
(つまり、response.setHeader(HttpHeaders.CONNECTION, HttpHeaderValues.CLOSE);
)を設定しました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;
EDIT2: Jettyにrequest.getConnection().getEndPoint().close()
を介して接続を強制的に閉じることは何もしません-接続ISが閉じられていることは明らかです(LAST_ACK
にあるため)がなぜこれを超えないのですか?Nginxは何らかの理由でバックエンドへの接続を開いたままにしていますか?
さて、私はついに桟橋に上手にプレーするよう説得することができました。
要約すると、マシン全体での接続は次のようになります。
_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
(EndPoint
でclose()
を呼び出すと、基になる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);
_