Linux 네트워크가 느릴 때는 용어를 많이 아는 것보다 데이터가 어느 큐에서 기다리고 어느 계층에서 다시 보내지는지를 순서대로 확인하는 편이 유용하다. 애플리케이션 → 소켓 → TCP → qdisc → NIC → 네트워크 경로로 내려가며 같은 시각의 지표를 모으면 “네트워크가 느리다”는 증상을 구체적인 후보로 바꿀 수 있다.
브렌던 그렉의 시스템 성능 관점으로 네트워크 용어를 정리하다 보니 ICMP, CIDR, 쿠키, backlog와 오프로드가 한 글에 섞였다. 다시 보니 이 개념들은 같은 진단 단계에 있지 않았다. 여기서는 Linux 호스트의 지연·손실·연결 실패를 좁히는 흐름에 필요한 내용만 남긴다.
증상을 먼저 네 종류로 나눈다
측정 전에 사용자가 겪는 실패를 구분한다.
- 연결 자체가 느리거나 실패한다: SYN queue, accept queue, 방화벽, DNS와 경로를 본다.
- 연결 뒤 응답이 느리다: 애플리케이션 off-CPU, socket buffer, RTT와 재전송을 본다.
- 처리량만 낮다: cwnd·rwnd, 손실, RTT, NIC와 qdisc를 본다.
- 부하가 있을 때만 지연이 튄다: queueing delay와 bufferbloat를 의심한다.
평균 응답 시간 하나만 보면 이 네 문제가 섞인다. 요청 시작 시각, 연결 시간, 첫 바이트와 전체 전송 시간을 나눠 기록한다.
전체 데이터 경로를 한 번에 그린다
송신 경로를 단순화하면 다음과 같다.
애플리케이션 write()
→ TCP 송신 버퍼
→ 혼잡·수신 윈도우
→ qdisc
→ NIC 드라이버와 하드웨어 큐
→ 링크와 라우터
→ 상대 호스트
수신 쪽은 반대 방향으로 NIC에서 커널 socket receive buffer를 거쳐 애플리케이션의 read()로 올라온다.
| 계층 | 대표 질문 | 먼저 볼 도구 |
|---|---|---|
| 애플리케이션 | CPU를 쓰는가, I/O·락을 기다리는가 | profiler, tracing, off-CPU 분석 |
| listen socket | 연결을 accept하지 못하고 쌓였는가 | ss -lntp |
| established TCP | RTT·재전송·윈도우가 어떻게 변하는가 | ss -tin |
| qdisc | 송신 큐에 backlog·drop이 생기는가 | tc -s qdisc |
| NIC | error·drop·offload 상태가 어떤가 | ip -s link, ethtool |
| 경로 | 손실·MTU·홉 변화가 있는가 | ping, tracepath, packet capture |
한 도구의 한 시점 출력만으로 원인을 확정하지 않는다. 같은 부하 구간에서 애플리케이션 지연과 호스트·네트워크 지표의 변화가 맞물리는지 본다.
연결 실패는 listen queue부터 본다
ss -lntp
LISTEN socket에서 queue가 설정된 한계에 계속 가까워지면 애플리케이션이 완성된 연결을 충분히 빨리 accept()하지 못하는지 확인한다. listen()의 backlog는 Linux에서 주로 완성된 연결의 대기열에 영향을 받고 net.core.somaxconn의 상한을 받는다. SYN이 아직 완성되지 않은 연결은 별도의 정책과 tcp_max_syn_backlog 영향을 받는다.
sysctl net.core.somaxconn
sysctl net.ipv4.tcp_max_syn_backlog
sysctl net.ipv4.tcp_syncookies
queue가 찬다고 설정값만 늘리면 대기 공간이 커질 뿐 처리율 병목은 남을 수 있다. 다음을 함께 확인한다.
- accept loop와 worker가 CPU·락·GC에 막히는가
- 프로세스 file descriptor 제한에 닿았는가
- upstream load balancer의 재시도와 연결 폭주가 있는가
- SYN flood 또는 비정상적인 연결 패턴인가
SYN cookie는 SYN queue 고갈을 완화하는 방어 수단이지 완성된 연결 폭주나 느린 애플리케이션을 해결하는 기능은 아니다.
연결된 TCP는 ss -tin으로 읽는다
ss -tin dst 203.0.113.10
ss -i는 Linux TCP 내부 정보에서 다음 값을 보여 줄 수 있다.
rtt와rttvar: 왕복 시간과 변동rto: 재전송 timeoutretrans: 재전송 관련 상태cwnd: 혼잡 윈도우ssthresh: slow start thresholdwscale: 송·수신 윈도우 scalepmtu: 추정한 path MTUsend: 추정 송신률
송신자가 새로 보낼 수 있는 양은 수신자가 광고한 윈도우와 혼잡 제어가 허용하는 윈도우의 제약을 모두 받는다.
실제 전송 가능량 ≈ min(rwnd, cwnd)에서 이미 미확인인 데이터 제외
cwnd가 작다고 혼잡 제어만 탓하지 않는다. 애플리케이션이 데이터를 충분히 쓰지 않는지, 수신 윈도우가 닫히는지, RTT·손실과 재전송이 같이 변하는지 봐야 한다. TCP 혼잡 제어의 단계는 cwnd·slow start·fast recovery에서 더 자세히 정리했다.
qdisc에서 대기와 drop을 확인한다
Linux 송신 경로의 queueing discipline(qdisc)은 패킷을 언제 NIC로 보낼지 결정한다.
tc -s qdisc show dev eth0
부하 전후의 backlog, dropped, overlimits, requeues를 비교한다. 출력 필드와 의미는 qdisc 종류에 따라 다르므로 숫자 하나를 모든 환경에서 같은 뜻으로 해석하지 않는다.
부하가 없을 때 RTT가 낮은데 업로드나 다운로드 중 RTT가 크게 오르면 bufferbloat 후보가 된다. 큰 unmanaged queue는 손실을 늦추는 대신 패킷을 오래 기다리게 할 수 있다.
FQ-CoDel은 flow queueing과 CoDel active queue management를 결합한다. CoDel은 queue 길이만이 아니라 패킷이 머문 시간을 이용해 지속적인 지연을 감지한다. Linux의 BQL(Byte Queue Limits)은 더 아래의 device driver ring에 과도한 바이트가 쌓이지 않도록 돕는다.
그렇다고 모든 서버에 fq_codel을 즉시 설정하면 되는 것은 아니다. 실제 병목 링크가 호스트 바깥에 있거나, 클라우드 가상 NIC·traffic shaping 구조가 다르면 효과와 설정 지점이 달라진다. 먼저 어느 인터페이스와 계층에서 queue가 생기는지 측정한다.
NIC error와 drop을 분리한다
ip -s link show dev eth0
ethtool -S eth0
확인할 항목은 드라이버와 장치마다 이름이 다르지만 다음 범주로 나눌 수 있다.
- RX/TX packet과 byte 증가량
- error, dropped, missed, timeout
- ring buffer 또는 queue별 drop
- link speed·duplex와 carrier 변화
counter는 누적값이다. 값이 0이 아닌 사실보다 문제 구간에서 증가하는 속도가 중요하다. 컨테이너·bond·bridge·가상 NIC를 쓰면 애플리케이션이 보는 인터페이스와 실제 물리 NIC를 모두 따라가야 한다.
오프로드 때문에 packet capture가 다르게 보일 수 있다
ethtool -k eth0
TSO(TCP Segmentation Offload)는 큰 TCP payload를 NIC가 실제 송신 직전에 여러 frame으로 나누도록 맡긴다. GSO는 소프트웨어에서 비슷한 분할을 늦추고, GRO는 수신한 여러 패킷을 커널에서 큰 단위로 합친다.
이 때문에 호스트에서 캡처한 tcpdump에 MTU보다 큰 TCP segment처럼 보이는 데이터가 있어도 wire에 그 크기 그대로 나갔다고 단정할 수 없다. 캡처 지점이 분할 전이거나 병합 후일 수 있다.
tcpdump -ni eth0 host 203.0.113.10
오프로드를 끈 비교는 진단에 도움이 될 수 있지만 처리량과 CPU 사용에 영향을 준다. 운영 인터페이스에서 무심코 변경하지 말고 검증 환경이나 짧고 통제된 창에서 적용한다.
MTU와 경로 문제는 ICMP까지 본다
일반 Ethernet MTU 1500에서 IPv4·옵션 없는 TCP header를 빼면 흔히 MSS 1460을 떠올린다. 하지만 IPv6, TCP option, tunnel과 VPN encapsulation이 있으면 실제 값이 달라진다. 고정된 1460만 기준으로 삼지 않는다.
tracepath example.com
ping -c 10 example.com
Path MTU Discovery는 ICMP 메시지에 의존할 수 있다. ICMP를 일괄 차단하면 큰 패킷에서만 통신이 멈추는 black hole 문제가 생길 수 있다. ping 성공이 TCP 서비스의 정상 동작을 보장하지도 않는다. 실제 서비스의 주소·포트와 packet size를 기준으로 본다.
traceroute 결과도 경로의 힌트다. ECMP, 정책 라우팅, ICMP rate limit과 비대칭 경로 때문에 요청마다 또는 방향마다 다를 수 있다. IP 경로 선택 자체는 라우팅과 포워딩 차이에서 이어서 볼 수 있다.
on-CPU와 off-CPU를 네트워크 지표와 맞춘다
요청이 200ms이고 CPU time이 5ms라면 남은 시간을 모두 네트워크라고 부를 수는 없다. socket read, DNS, TLS, connection pool, lock, scheduler run queue와 downstream 응답 대기가 섞일 수 있다.
trace에서 다음 구간을 나눈다.
DNS
→ TCP connect
→ TLS handshake
→ connection pool 대기
→ 요청 전송
→ first byte 대기
→ body 수신
→ 애플리케이션 처리
호스트의 ss, tc, NIC counter를 같은 시간축에 놓았을 때 RTT·재전송·queue 증가가 보이지 않으면 애플리케이션이나 downstream 처리부터 다시 본다. 시스템 성능의 관측·실험 순서는 시스템 성능 엔지니어링 1장 노트와 연결된다.
최소 진단 체크리스트
# listen queue와 프로세스
ss -lntp
# 연결별 RTT, RTO, cwnd, 재전송
ss -tin
# qdisc 상태
tc -s qdisc show dev eth0
# 인터페이스·드라이버 통계
ip -s link show dev eth0
ethtool -S eth0
# offload 상태
ethtool -k eth0
# 경로와 MTU 힌트
tracepath example.com
이 명령은 원인을 자동으로 알려 주는 체크박스가 아니다. 문제 전후의 변화, 애플리케이션 trace와 요청 특성을 함께 모을 때 의미가 생긴다. 네트워크 성능 분석의 핵심은 모든 용어를 한 번에 외우는 것이 아니라 기다림이 시작되는 첫 계층을 찾는 것이다.
참고 자료
'배움과 성장 > 네트워크·보안' 카테고리의 다른 글
| EKS NLB 트래픽 경로: instance·IP target과 conntrack 진단 (0) | 2025.10.16 |
|---|---|
| AWS WAF는 어디서 동작하나: CloudFront·ALB 연결과 검사 한계 (0) | 2025.10.15 |
| AWS ALB와 NLB 함께 쓰기: 지원되는 2가지 패턴과 피할 연결 (0) | 2025.10.14 |
| AWS ALB 요청 흐름: Listener Rule·Target Group·TLS (0) | 2025.10.13 |
| AWS NLB 동작 원리: 대상 선택부터 EKS Pod 경로까지 (0) | 2025.10.12 |
댓글