nginx + Jetty - 수천 개의 연결이 LAST_ACK에 멈췄습니다.

nginx + Jetty - 수천 개의 연결이 LAST_ACK에 멈췄습니다.

감옥이 있는 FreeBSD 시스템이 있습니다. 특히 두 개는 nginx를 실행하는 것과 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 배포 -> 부두 연결

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
  • 부두 끝에서 나는 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

좋아, 드디어 Jetty가 잘 플레이하도록 설득할 수 있었어요.

요약하자면, 현재 컴퓨터 전체의 연결은 다음과 같습니다.

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()호출 ) 다음과 같이 했습니다.EndPointSocketChannel

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

(클라이언트에게 최대 한 줄만 보내므로 화려한 것은 필요하지 않습니다.)

그러나 이로 인해 여전히 전체 서버가 LAST_ACK로 가득 차게 되었습니다. 결국 이를 사라지게 만든 것은 활성화 SO_LINGER(그리고 시간 초과 없이 즉시 소켓을 강제로 닫도록 만드는 것) 였습니다.

connector.setSoLingerTime(0);

관련 정보