nginx + Jetty - Tausende von Verbindungen stecken in LAST_ACK fest

nginx + Jetty - Tausende von Verbindungen stecken in LAST_ACK fest

Ich habe eine FreeBSD-Maschine mit Jails – zwei im Besonderen, eine, auf der nginx läuft, und eine andere, auf der ein Java-Programm läuft, das Anfragen über Jetty (eingebetteter Modus) akzeptiert.

Jetty empfängt ständig über 500 Anfragen/Sekunde und es gab in letzter Zeit ein Problem, bei dem ich ständig über60.000Verbindungen im LAST_ACK-Status zwischen Nginx und Jetty.

Verteilung aller Verbindungen (beinhaltet auch einige andere Dienste, insbesondere 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

Verteilung von Nginx -> Jetty-Verbindungen

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

Ich würde es vorziehen, wenn bei jeder Anfrage die Verbindung vollständig geschlossen wird. Die Clientanfragen liegen etwa 10 Minuten auseinander, daher müssen Verbindungen geschlossen werden.

Einige der Verbindungen,

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..
  • Auf Jettys Seite habe ich maxIdleTime2000 eingestellt - vorher waren alle Verbindungen vorhanden, ESTABLISHEDaber jetzt sind sieLAST_ACK
  • Auf Jettys Seite habe ich eingestellt Connection: close(dh response.setHeader(HttpHeaders.CONNECTION, HttpHeaderValues.CLOSE);)
  • Jetty meldet nie viele offene Verbindungen – immer sehr wenige.
  • PF/IPFW wird derzeit nicht verwendet
  • nginx - reset_timedout_connectionist eingeschaltet

Ich kann nicht herausfinden, wie ich Nginx oder Jetty dazu bringe, die Verbindung zwangsweise zu schließen. Ist das einfach etwas, das in Jetty behoben werden muss, damit es den Socket nach Abschluss der Anforderung vollständig schließt?

vielen Dank im Voraus

BEARBEITEN:habe meine Nginx-Konfiguration für das Proxy-Setup vergessen-

    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 zu zwingen, die Verbindung über zu schließen, request.getConnection().getEndPoint().close()bewirkt nichts – es ist offensichtlich, dass die Verbindung geschlossen WIRD (da sie in ist LAST_ACK), aber warum kommt sie nicht darüber hinaus? Hält Nginx aus irgendeinem Grund die Verbindung zum Backend offen?

Antwort1

OK, ich konnte Jetty endlich davon überzeugen, brav mitzuspielen.

Zur Wiederholung: So sehen meine Verbindungen jetzt maschinenweit aus:

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

Und zwischen nginx und Jetty

1 FIN_WAIT_2
3 LISTEN
14 ESTABLISHED

Ich habe bereits die gesamte Verbindung geschlossen und EndPoint( close()durch den Aufruf EndPointwird die zugrunde liegende Verbindung geschlossen SocketChannel) diese praktische Methode verwendet:

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();
}

(Ich sende maximal eine Zeile an den Client, es ist also nichts Ausgefallenes erforderlich)

Dies führte jedoch trotzdem dazu, dass der gesamte Server mit LAST_ACK gefüllt wurde ... Was diese schließlich verschwinden ließ, war die Aktivierung SO_LINGER(und das zwangsweise sofortige Schließen des Sockets, ohne Timeout).

connector.setSoLingerTime(0);

verwandte Informationen