동시 접속이 늘자 Too many open files 에러가 난 이유
문제 발생
동시 접속자가 늘어난 어느 날부터 서버 로그에 Too many open files 에러가 반복적으로 찍히며 새 연결을 받지 못하는 문제가 발생했습니다.
원인 분석
리눅스는 각 프로세스가 동시에 열 수 있는 파일 디스크립터(file descriptor) 개수에 제한(ulimit -n)을 둡니다. 파일 디스크립터는 이름 그대로 파일뿐 아니라 네트워크 소켓, 파이프도 포함합니다 — 서버가 받는 각 클라이언트 연결, DB 커넥션 풀의 각 연결도 전부 파일 디스크립터 하나씩을 소비합니다.
기본 제한값(흔히 1024)은 개발 환경 기준으로는 충분하지만, 동시 접속자가 많은 프로덕션 서버에서는 금방 도달할 수 있는 낮은 값입니다. 이 제한에 도달하면 새로운 연결(소켓)이나 파일을 열 수 없어, 새 클라이언트 연결이 거부되거나 로그 파일 쓰기 같은 정상적인 동작까지 실패하기 시작합니다.
해결 방안
- 현재 제한값과 실제 사용량을 먼저 확인합니다.
ulimit -n # 현재 셸의 soft limit
cat /proc/<pid>/limits | grep "open files" # 특정 프로세스의 제한
ls /proc/<pid>/fd | wc -l # 그 프로세스가 실제로 열고 있는 fd 수- 일시적 조치로 현재 셸 세션의 제한을 올릴 수 있지만, 이건 그 세션이 끝나면 사라지고 systemd로 관리되는 서비스에는 적용되지 않습니다.
ulimit -n 65536- 영구적으로 올리려면
/etc/security/limits.conf(일반 프로세스)와, systemd로 서비스를 관리한다면 해당 유닛 파일에도 별도로 지정해야 합니다 — systemd 서비스는limits.conf를 그대로 상속받지 않는 경우가 흔해서, 이 둘을 따로 챙기지 않으면 "설정했는데 왜 안 먹히지"라는 흔한 함정에 빠집니다.
# /etc/systemd/system/myapp.service
[Service]
LimitNOFILE=65536- Docker 컨테이너로 실행 중이라면 컨테이너 자체의 제한(
docker run --ulimit nofile=65536:65536)도 별도로 확인해야 합니다 — 호스트의 제한을 올려도 컨테이너 안에서는 다른 값이 적용될 수 있습니다. - 제한을 무작정 올리기보다, 실제로 필요한 수치를 계산(예상 동시 연결 수 + DB 커넥션 풀 크기 + 로그/기타 파일)해서 근거 있는 값으로 설정하고, 연결이 제대로 닫히고 있는지(connection leak이 없는지)도 함께 점검하는 것이 근본적인 해결에 더 가깝습니다 — 제한을 올리는 것만으로는 커넥션 누수가 있다면 언젠가 다시 그 상한에 도달합니다.
댓글0
댓글을 남기려면 로그인이 필요해요. 로그인
아직 댓글이 없어요. 첫 의견을 편하게 남겨 보세요.