감옥이 있는 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 쪽에서는
maxIdleTime
2000으로 설정했습니다. 이전에는 모든 연결이 있었지만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()
호출 ) 다음과 같이 했습니다.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();
}
(클라이언트에게 최대 한 줄만 보내므로 화려한 것은 필요하지 않습니다.)
그러나 이로 인해 여전히 전체 서버가 LAST_ACK로 가득 차게 되었습니다. 결국 이를 사라지게 만든 것은 활성화 SO_LINGER
(그리고 시간 초과 없이 즉시 소켓을 강제로 닫도록 만드는 것) 였습니다.
connector.setSoLingerTime(0);