이 문서를 통해 아래 질문들에 답할 수 있게 됩니다.
Socket Port File Descriptor에서 붙잡아야 할 핵심 판단 기준은 무엇인가?네트워크 연결도 열린 OS 자원이다라는 기준은 어떤 JVM/OS 신호로 확인되는가?- Java/Spring 코드에서
Socket Port File Descriptor판단 기준은 어떤 장애 신호로 드러나는가?
개요
이 문서의 주제는 Socket Port File Descriptor이다. Socket, port, file descriptor가 서버 네트워크 연결에서 어떤 관계를 갖는지 설명한다.
먼저 붙잡을 기준은 다음 문장이다. 네트워크 연결도 열린 OS 자원이다. 같은 8080 port로 서비스하더라도 listen socket, accepted connection, outbound connection은 서로 다른 file descriptor로 잡힌다. 따라서 연결 수 문제는 포트 하나가 열렸는지가 아니라 어떤 process가 어떤 FD를 얼마나 오래 들고 있는지로 확인해야 한다.
핵심 모델
- 판단 기준: 네트워크 연결도 열린 OS 자원이다.
- Port는 주소의 일부이고, socket은 OS가 관리하는 통신 객체이며, FD는 process가 그 객체를 다루는 핸들이다.
bind와listen으로 만든 수신 socket도 FD이고,accept로 생긴 연결 socket도 별도 FD다.- HTTP keep-alive, WebClient, DB driver connection은 모두 FD를 오래 점유할 수 있다.
Too many open files는 파일만이 아니라 socket 증가로도 발생한다.ss,lsof,/proc/<pid>/fd를 같은 PID와 같은 시각으로 묶어 봐야 port와 FD 수를 혼동하지 않는다.
문서별 핵심 구분
- socket은 OS 통신 객체이고 Linux에서는 FD로 다뤄진다.
- port는 endpoint 번호이며 connection 자체와 다르다.
- socket 수 증가는 FD limit과 직접 연결된다.
원리
Port는 0.0.0.0:8080처럼 endpoint를 식별하는 번호이고, socket은 그 endpoint에서 대기하거나 통신하는 OS 객체다. FD는 process가 socket을 읽고 쓰기 위해 받은 정수 핸들이다.
Java 서버가 port를 열면 먼저 listen socket FD가 생긴다. client 연결을 accept하면 연결마다 accepted socket FD가 추가된다. outbound HTTP client나 DB client도 remote endpoint로 향하는 socket FD를 만든다.
따라서 “8080 port는 하나”라는 사실만으로 연결 비용을 판단하면 안 된다. 장애 중에는 listen port가 어느 PID에 붙어 있는지, 그 PID의 FD 수가 얼마나 늘었는지, FD 대부분이 inbound인지 outbound인지 나눠야 한다.
FD limit에 가까워지면 새 파일 열기, socket accept, log 파일 생성, heap dump 생성이 함께 실패할 수 있다. 이때 Application 로그의 Too many open files만 보고 파일 I/O 문제로 단정하면 socket 고갈을 놓친다.
Java/Spring 연결
- Spring MVC Controller가 직접 FD를 다루지 않아도 Tomcat, JDBC driver, HTTP client는 모두 socket FD를 연다.
- WebClient, RestTemplate, DB pool에서 response나 connection 반환이 늦으면 outbound socket FD가 오래 남는다.
- Linux/Micrometer 환경에서는
process.files.open,process.files.max같은 process FD metric을/proc/<pid>/fd와 비교할 수 있다. Too many open files가 Controller error로 보이더라도 원인은 inbound accept, outbound client, log/dump 파일 중 하나일 수 있다.- 서버 인스턴스를 늘리면 inbound FD는 분산되지만 각 인스턴스가 downstream으로 여는 outbound FD 총합은 늘 수 있다.
- Spring 코드 리뷰에서는
Socket Port File Descriptor판단 기준이 어떤 thread, pool, timeout, resource 설정으로 드러나는지 확인한다.
코드와 설정 예시
PID 1234 java
fd=120 LISTEN 0.0.0.0:8080
fd=121 ESTABLISHED 10.0.1.10:8080 -> 10.0.2.15:53122
fd=122 ESTABLISHED 10.0.1.10:43210 -> 10.0.3.20:5432첫 번째 FD는 서버가 요청을 받기 위해 열어 둔 listen socket이고, 두 번째 FD는 accept된 inbound 연결이며, 세 번째 FD는 DB 같은 외부 시스템으로 나가는 outbound 연결이다. 같은 Java process 안에서도 방향과 상대 endpoint가 다르므로 lsof와 ss 출력에서 local/remote address를 함께 읽어야 한다.
관찰 명령
ss -tanp | head
lsof -i -P -n | head
ls /proc/<pid>/fd | wc -lSocket Port File Descriptor 관찰 명령은 결론이 아니라 가설 확인 도구다. 운영 중에는 반복 간격, 대상 PID, 수집 시각을 함께 남기고 출력이 큰 명령은 범위를 제한한다.
지표 해석
| 신호 | 먼저 의심할 것 | 다음 확인 |
|---|---|---|
| 같은 PID의 FD 수 증가 | socket leak, keep-alive 과다, 파일 미해제 | /proc/<pid>/fd, lsof -p |
Too many open files | FD limit 초과 | ulimit -n, LimitNOFILE, socket 수 |
| LISTEN은 하나인데 ESTABLISHED가 많음 | 연결 유지, client 폭주, outbound leak | local/remote address 분류 |
| port bind 실패 | 이미 다른 process가 사용 중이거나 권한 부족 | ss -ltnp, service user |
Socket Port File Descriptor에서는 핵심 신호와 보조 지표를 같은 시간축에서 맞춘다. 먼저 변한 신호와 뒤따라 포화된 신호를 분리해야 원인과 결과를 구분할 수 있다.
장애 상황에서 보는 순서
- 장애 대상 port가 어떤 PID에 붙어 있는지
ss -ltnp로 확인한다. - 해당 PID의 전체 FD 수를
/proc/<pid>/fd와lsof -p로 확인한다. - socket FD를 LISTEN, ESTABLISHED, TIME_WAIT 방향으로 나눈다.
- inbound local port와 outbound remote address를 분리해 어느 쪽이 증가했는지 본다.
LimitNOFILE, container limit, systemd limit이 실제 process에 적용됐는지 확인한다.
이 순서는 Socket Port File Descriptor 후보를 빠르게 좁히기 위한 기본 루틴이다. 결론을 내리기 전에는 애플리케이션 증거와 JVM/OS 증거를 최소 한 번 이상 맞춘다.
실전 팁
- port 하나에 연결 하나만 붙는다고 생각하지 않는다. listen socket과 accepted socket을 분리해 센다.
- FD 수를 볼 때는
lsof결과만 남기지 말고 PID, service user, limit 값을 같이 남긴다. - inbound 장애처럼 보여도 outbound DB/HTTP connection leak이 FD를 먼저 소모했을 수 있다.
- FD limit을 키우기 전에 왜 socket이 닫히지 않는지, timeout과 pool 반환이 정상인지 확인한다.
- 장애 회고에는 어떤 endpoint가 FD를 많이 차지했는지 local/remote address 기준으로 남긴다.
주니어 팁
- 포트 하나와 연결 하나를 같은 것으로 보지 말고 “port는 번호, socket은 객체, FD는 핸들”로 구분한다.
lsof -i출력에서 PID, FD, local address, remote address를 한 줄씩 읽어 본다.Too many open files가 보이면 파일만 찾지 말고 socket FD도 반드시 같이 센다.
시니어 팁
- 서버의
LimitNOFILE은 Tomcat connection 수, DB pool, HTTP client pool, log/dump 파일 수를 더한 운영 상한으로 잡는다. - socket 증가가 정상 트래픽 증가인지 leak인지 보려면 connection lifetime과 pool 반환 지표를 같이 본다.
- container와 systemd를 함께 쓰는 환경에서는 host limit, service limit, container limit이 모두 같은 의도인지 확인한다.
Guru급 팁
Socket Port File Descriptor주제는 단일 snapshot보다 변화 방향이 중요하다. 같은 명령을 간격을 두고 실행해 상태가 증가, 유지, 회복 중 어디인지 본다.- 고급 도구는
Socket Port File Descriptor가설을 좁힐 때만 사용하고 기본 지표와 모순되는지 먼저 확인한다. Socket Port File Descriptor조치 후에는 CPU, memory, socket, disk, pool 중 다음 포화 지점이 어디로 이동했는지 확인한다.
위험 신호!
8080 port는 하나니까 socket도 하나라고 판단한다.- FD limit 초과를 보고
ulimit만 키우고 socket 증가 원인을 확인하지 않는다. - inbound ESTABLISHED와 outbound ESTABLISHED를 합쳐 세고 어느 방향이 늘었는지 남기지 않는다.
lsof를 대량 실행하면서 PID와 시간대를 남기지 않아 장애 전후 비교가 안 된다.- 재시작 후 FD 수가 줄었다는 이유로 어떤 연결이 누수됐는지 기록하지 않는다.
확인 질문
확인 질문
- port, socket, file descriptor는 각각 무엇을 뜻하는가?
- Port는 endpoint 번호, socket은 OS 통신 객체, FD는 process가 그 socket을 다루는 핸들이다.
Too many open files가 났을 때 socket 문제를 의심하려면 어떤 증거를 봐야 하는가?
/proc/<pid>/fd개수,lsof -p <pid>,ss -tanp에서 socket FD와 remote endpoint 분포를 확인해야 한다.- FD limit을 올리기 전에 무엇을 분리해야 하는가?
- 정상 traffic 증가와 connection leak, inbound 연결 증가와 outbound client pool 누수를 분리해야 한다.