데이터베이스 서버가 사라지면 poll()
연결된 클라이언트에 대해 최대 2 시간 ( libpq 클라이언트 라이브러리에서 호출 대기 시간 이 길어짐) 이 발생하는 프로덕션 문제를 추적하는 데 꽤 오랜 시간을 보냈습니다 . 문제를 파고 들어, 끊어진 TCP 연결을 적시에 알 수 있도록 이러한 커널 매개 변수를 조정해야한다는 것을 깨달았습니다.
net.ipv4.tcp_keepalive_time = 7200
net.ipv4.tcp_keepalive_probes = 9
net.ipv4.tcp_keepalive_intvl = 75
net.ipv4.tcp_retries2 = 15
위의 4 가지 값은 Ubuntu 12.04 시스템의 값이며 이러한 기본값은 현재 Linux 커널 기본값 과 동일하지 않은 것 같습니다 .
이러한 설정은 기존 연결을 유지하고 keepalive 프로브에 매우 찌그러지는 경향이 있습니다. AIUI (기본값 tcp_keepalive_time
2 시간)는 원격 호스트에 대한 응답을 기다리는 경우 연결이 유효한지 확인하기 위해 keepalive 프로브를 시작하기 전에 2 시간 동안 참을성있게 기다립니다. 그런 다음 원격 호스트가 keepalive 프로브에 응답하지 않으면 해당 keepalive 프로브를 9 tcp_keepalive_probes
초 ( tcp_keepalive_intvl
) 간격으로 75 초 간격으로 재 시도 하므로 연결이 실제로 종료되기까지 11 분이 더 걸립니다.
예를 들어, psql
원격 PostgreSQL 인스턴스에 연결된 세션을 시작하고 일부 쿼리가 응답을 기다리는 경우와 같이이 필드에서 본 것과 일치합니다.
SELECT pg_sleep(30);
그런 다음 원격 서버가 끔찍한 죽음 (예 : 해당 시스템으로 트래픽을 떨어 뜨림)으로 죽게하면 psql 세션이 연결이 끊어지기 전에 최대 2 시간 11 분 동안 대기하는 것을 볼 수 있습니다. 아시다시피, 이러한 기본 설정은 데이터베이스 장애 조치 이벤트와 같이 데이터베이스와 통신하는 코드에 심각한 문제를 일으 킵니다. 이 노브를 낮추면 많은 도움이되었습니다! 그리고 나는 이 기본값을 조정하는 것이 혼자 가 아니라는 것을 알았습니다 .
그래서 내 질문은 :
- 기본값은 얼마입니까?
- 이러한 TCP 설정을 기본값으로 설정 한 원래의 근거는 무엇입니까?
- Linux 배포판에서 이러한 기본값을 변경합니까?
그리고 이러한 설정에 대한 이론적 근거에 대한 다른 역사나 관점은 높이 평가 될 것입니다.
TCP_KEEPIDLE
, TCP_KEEPCNT
하고 TCP_KEEPINTVL
.
TCP_USER_TIMEOUT
를 설정하는 대신 소켓 옵션을 지정할 수도 있습니다 net.ipv4.tcp_retries2
. 물론 많은 애플리케이션 (예 : PostgreSQL)은 TCP_USER_TIMEOUT
아직 지원하지 않습니다 .