java.io.IOException: Too many open files
NiFi 는 저장소 파일과 소켓을 동시에 많이 연다. 콘텐츠 저장소의 클레임 파일, 프로비넌스 색인, 각 프로세서의 네트워크 연결이 전부 파일 디스크립터를 쓰므로, 배포판 기본값인 1024 로는 금방 모자란다.
/etc/security/limits.d/nifi.conf 에 실행 계정 기준으로 적는다.
nifi hard nofile 50000
nifi soft nofile 50000
nifi hard nproc 10000
nifi soft nproc 10000
RHEL 계열은 /etc/security/limits.d/20-nproc.conf 가 nproc 을 별도로 제한하므로 그 파일도 함께 확인한다.
systemd 로 기동한다면 limits.conf 가 적용되지 않는다. PAM 을 거치지 않기 때문이다. 유닛 파일에 직접 적어야 한다.
[Service]
LimitNOFILE=50000
LimitNPROC=10000
적용 여부는 실제 프로세스에서 확인한다. 로그인 셸의 ulimit -n 이 아니라 데몬 프로세스의 값을 봐야 한다.
cat /proc/$(pgrep -f org.apache.nifi.NiFi)/limits | grep -E 'open files|processes'
/etc/sysctl.d/99-nifi.conf 에 둔다.
fs.file-max = 1000000
vm.swappiness = 1
net.ipv4.ip_local_port_range = 10000 65000
net.core.somaxconn = 4096
net.ipv4.tcp_max_syn_backlog = 4096
vm.swappiness 를 낮추는 것은 JVM 힙이 스왑으로 밀려나는 것을 막기 위해서다. 힙이 스왑에 들어가면 GC 가 그 영역을 훑는 순간 응답이 몇 초씩 멈춘다.
ip_local_port_range 는 짧은 연결을 많이 맺는 흐름(InvokeHTTP, 사이트 투 사이트)에서 임시 포트가 마르는 것을 막는다.
sysctl --system
sysctl fs.file-max vm.swappiness net.ipv4.ip_local_port_range
저장소 디렉터리는 noatime 으로 마운트한다. 접근 시각 기록을 줄여 쓰기 부하를 낮춘다.
/dev/sdb1 /data2 xfs defaults,noatime 0 0
저장소를 NFS 에 두지 않는다. 잠금 동작과 지연 특성이 달라 데이터 손상과 정체를 부른다.
Kubernetes 에서는 노드의 한계값이 그대로 컨테이너에 적용된다. 파일 디스크립터 상한이 낮으면 노드 수준에서 조정해야 하며, Pod 스펙으로 nofile 을 올릴 수는 없다. 컨테이너 런타임 설정(LimitNOFILE 이 지정된 containerd·docker 유닛)을 확인한다.
sysctl 중 네임스페이스 대상 항목은 Pod 의 securityContext.sysctls 로 지정할 수 있으나, 안전하지 않은 항목으로 분류된 것은 kubelet 에 허용 목록이 필요하다.