브로커 로그에 아래가 찍히고 이후 파티션이 오프라인으로 떨어지거나 브로커가 죽는다.
java.io.IOException: Too many open files
ERROR Error while accepting connection (kafka.network.Acceptor)
Kafka 브로커가 여는 파일 기술자는 대략 다음의 합이다.
.index, .timeindex) — 파티션 하나에 세그먼트가 여러 개다파티션이 수천 개 규모면 세그먼트만으로도 기술자가 수만 개가 된다. 리눅스 기본값인 1024 는 개발 장비에서도 금방 넘어선다. 운영 브로커는 100000 이상을 잡아 두는 것이 일반적이다.
한도와 실제 사용량을 같이 본다. 한도만 올리고 넘어가면 원인이 세그먼트 폭증인지 소켓 누수인지 구분하지 못한다.
PID=$(pgrep -f kafka.Kafka)
cat /proc/$PID/limits | grep 'open files' # 실제 적용된 한도
ls /proc/$PID/fd | wc -l # 지금 열린 수
lsof -p $PID | awk '{print $5}' | sort | uniq -c | sort -rn | head
마지막 줄에서 REG 가 압도적이면 세그먼트, IPv4·sock 가 많으면 접속 문제다.
systemd 로 띄운 서비스에는 /etc/security/limits.conf 가 적용되지 않는다. PAM 을 거치는 로그인 세션에만 걸리기 때문이다. 서비스 유닛에 직접 적는다.
# /etc/systemd/system/kafka.service.d/limits.conf
[Service]
LimitNOFILE=200000
systemctl daemon-reload
systemctl restart kafka
cat /proc/$(pgrep -f kafka.Kafka)/limits | grep 'open files'
셸에서 스크립트로 띄우는 구성이라면 그쪽에 걸어 준다.
# /etc/security/limits.d/90-kafka.conf
kafka soft nofile 200000
kafka hard nofile 200000
시스템 전체 상한도 확인한다. 프로세스 한도를 아무리 올려도 이 값을 넘지 못한다.
sysctl fs.file-max
sysctl -w fs.file-max=2000000 # 영구 적용은 /etc/sysctl.d/
한도를 올리는 것은 응급 처치다. 파티션과 세그먼트 수 자체를 줄여야 한다.
log.segment.bytes 가 작으면 세그먼트가 많아지고 그만큼 파일도 늘어난다. 기본값 1GiB 를 특별한 이유 없이 낮추지 않는다.log.retention.hours · log.retention.bytes 를 실제 필요에 맞춘다. 오래된 세그먼트가 지워지면 파일도 닫힌다.# server.properties
log.segment.bytes=1073741824
log.retention.hours=168
log.retention.bytes=-1
log.retention.bytes 는 파티션 단위 상한이다. 토픽 전체가 아니라는 점을 자주 혼동한다.
소켓 쪽이 원인이면 클라이언트가 연결을 닫지 않고 새로 맺는 패턴을 의심한다. 프로듀서·컨슈머를 요청마다 새로 만드는 코드가 대표적이다.