네트워크 라우터의 TCP 연결 타임아웃과 Postgres keep-alive 설정에 대한 흥미로운 사례를 공유하고자 한다.
부제는 "Cisco와 Windows의 조합으로 만들어진 혼돈" 정도로 하고자 한다.
문제 상황
Windows 환경에서 Postgres 클라이언트와 DB 서버를 사용하던 중, 90분이 지나면 연결이 끊어지는 현상이 발생했다. 이 문제를 해결하기 위해 Cisco 공식 문서를 찾아보면서 원인을 파악할 수 있었다.
라우터의 연결 상태 관리 방식
라우터는 로컬 상태 테이블에서 연결들을 추적하며, 이를 통해 라우팅 결정을 내리고 유효하지 않은 패킷을 필터링한다. 이 상태 정보는 다음과 같은 경우에 제거된다:
- 양쪽 중 한 쪽이 연결을 종료할 때
- 연결이 너무 오랫동안 유휴 상태일 때 (클라이언트와 서버가 모두 충돌했다고 가정)
특히 두 번째 경우는 제한된 라우터 메모리를 효율적으로 사용하기 위한 조치다.
실제 발생한 상황
- Postgres 클라이언트가 서버에 연결하여 쿼리를 실행
- 클라이언트에서 데이터 처리를 시작 (90분 소요)
- 처리 중에는 클라이언트와 서버 간 패킷 교환이 없음
- DB와 클라이언트 사이의 게이트웨이 라우터는 60분의 기본 유휴 타임아웃 설정을 가짐
- 60분 후 라우터가 연결 정보를 삭제
- 90분 후 클라이언트가 쿼리를 시도했으나, 라우터가 해당 연결을 인식하지 못해 패킷을 드롭
- 결과적으로 연결 실패 발생
해결 방법
Postgres는 keep-alive 메시지를 설정할 수 있는 옵션을 제공한다. 문제는 Windows의 기본 tcp_keepalives_idle 값이 0으로 설정되어 있어, Windows 기본값인 2시간을 사용한다는 점이었다.
해결책은 간단했다. tcp_keepalives_idle 값을 Cisco 라우터의 TCP 유휴 시간(1시간)보다 작게 설정하는 것이다. 이렇게 하면 Postgres 서버가 라우터의 타임아웃이 발생하기 전에 keep-alive TCP 메시지를 보내, 연결이 계속 유지되도록 할 수 있다.
교훈
네트워크 문제를 해결할 때는 단순히 애플리케이션 레벨뿐만 아니라, 네트워크 인프라의 동작 방식도 고려해야 한다. 특히 장시간 실행되는 작업이 있는 경우, 네트워크 연결 유지에 대한 설정을 신중히 검토할 필요가 있다.
'DB > PostgreSQL' 카테고리의 다른 글
PostgreSQL Vacuum 관련 쿼리 간단 모음 (2) | 2024.02.07 |
---|