15장. Kafka 소켓 버퍼 크기 설정
Kafka는 네트워크를 통해 데이터를 주고받는 시스템입니다. 이때 Kafka 브로커는 보내거나 받는 데이터를 일시적으로 담아두는 소켓 버퍼(Socket Buffer) 를 사용합니다. 이 버퍼가 충분하지 않으면 빠른 네트워크에서도 데이터를 처리하지 못해 성능 저하나 데이터 유실이 발생할 수 있습니다.
15.1 소켓 버퍼란?
소켓 버퍼는 TCP 통신에서 데이터를 임시로 저장하는 공간입니다. Kafka는 데이터를 주고받을 때 이 공간을 거쳐 송수신을 하며, 버퍼가 작으면 처리 속도가 줄어들고, 버퍼가 충분하면 성능을 안정적으로 유지할 수 있습니다.
15.2 최소, 기본, 최대 버퍼 크기란?
TCP에서는 버퍼 크기를 다음 세 단계로 나눠서 관리합니다.
| 항목 | 설명 |
|---|---|
| 최소 (min) | 절대 보장해야 하는 가장 작은 버퍼 크기 (일반적으로 4KB) |
| 기본 (default) | 연결이 시작할 때 사용하는 기본 버퍼 크기 (Kafka에서는 512KB 권장) |
| 최대 (max) | 네트워크 상황이 좋을 때 확장 가능한 최대 버퍼 크기 (안정적인 값은 2MB이지만, 실제 작업 부하에 근거하여 BDP 계산 기반으로 더 크게 설정 가능) |
15.3 Kafka에서 기본 버퍼를 512KB로 설정하는 이유
- Kafka는 1MB 이상의 데이터를 한 번에 주고받는 경우가 많습니다.
- 기본 버퍼가 너무 작으면 TCP Slow Start 구간이 길어져 Throughput이 제대로 나오지 않습니다.
- 512KB로 설정하면 1Gbps~10Gbps 환경에서 빠른 네트워크 부하에도 초기 성능이 안정적으로 유지됩니다.
- 실무에서는 안정성을 중시해서 128KB로도 기본값을 줄일 수 있지만, Kafka의 대량 메시지 처리 특성상 512KB 이상을 기본으로 설정하는 것이 권장됩니다.
15.4 버퍼 크기는 어떻게 정할까? (BDP 기반)
버퍼 크기를 정할 때 사용하는 기준이 바로 BDP(Bandwidth Delay Product) 입니다.
📘 BDP란?
BDP는 “네트워크 대역폭과 지연 시간(RTT)을 고려하여, 버퍼에 저장할 수 있는 최적의 데이터 양“입니다.
공식:
BDP = (네트워크 속도(Gbps) × 왕복 지연 시간(RTT, 초)) ÷ 8
bit 단위 대역폭을 byte로 바꾸기 위해 ÷ 8을 합니다.
네트워크를 충분히 활용하려면 최소 BDP만큼의 버퍼가 필요하고, 실무에서는 BDP × 1.5~2배 여유를 주는 것이 일반적입니다.
15.5 버퍼 크기 결정 흐름
TCP 소켓 버퍼 크기는 다음 흐름으로 결정됩니다.
-
소켓 생성 시 기본값 적용
net.core.rmem_default(수신 버퍼 기본값)net.core.wmem_default(송신 버퍼 기본값)
-
TCP 연결 후 네트워크 상황에 따라 자동 확장
net.ipv4.tcp_rmem(수신 버퍼 최소/기본/최대 범위)net.ipv4.tcp_wmem(송신 버퍼 최소/기본/최대 범위)
-
소켓 버퍼 크기 확장 시 최대 한도 제한
net.core.rmem_max,net.core.wmem_max값을 넘지 못함
-
서버 전체 TCP 메모리 총량 제한
net.ipv4.tcp_mem에 설정된 값 이상으로는 전체 TCP 소켓 메모리를 사용할 수 없음tcp_mem값은 페이지 단위(보통 4KB)로 설정되며, 경고선(soft limit)과 절대 한계(hard limit)를 초과할 경우 새 소켓 생성이나 버퍼 확장이 거부될 수 있음- TCP 소켓 하나는 송신(wmem) 버퍼와 수신(rmem) 버퍼를 모두 사용합니다.
- 서버 전체의 모든 소켓의 송신/수신 버퍼 사용량 합계를 기준으로
net.ipv4.tcp_mem리밋이 적용됩니다.
net.ipv4.tcp_mem 세 값의 의미 및 설정 기준
| 값 | 의미 | 설정 기준 |
|---|---|---|
| 첫 번째 값 (경고 없이 허용) | 이 범위까지는 정상 운영 | 예상 TCP 메모리 사용량 |
| 두 번째 값 (소프트 리밋) | 초과 시 커널이 버퍼 회수(cleanup) 시작 | 경고 없이 허용 × 1.5배 |
| 세 번째 값 (하드 리밋) | 초과 시 소켓 생성 실패, 버퍼 확장 거부 | 소프트 리밋 × 2배 |
📘 Kafka 환경에서는 어떻게 설정할까?
Kafka는 송신과 수신 트래픽이 대체로 비슷하게 발생하는 구조입니다.
따라서 전체 TCP 메모리 소모량을 다음 기준으로 예상하고 설정합니다.
- NIC 속도와 RTT를 기반으로 BDP를 계산한다.
- 활성 소켓 수를 고려하여 예상 TCP 메모리 소비량을 구한다.
- 송수신 합산을 고려해 예상량 × 2배로 계산한다.
- 여유를 주기 위해 예상 사용량의 1.5배 이상으로 소프트 리밋을 설정한다.
- 소프트 리밋의 약 2배를 하드 리밋으로 설정한다.
이렇게 설정하면 Kafka 브로커가 다수의 프로듀서와 컨슈머를 동시에 처리할 때에도 안정적인 네트워크 성능을 유지할 수 있습니다.
15.6 다수의 소켓 연결 시 버퍼 크기 조정
Kafka는 여러 프로듀서 및 컨슈머와 동시에 TCP 연결을 유지합니다. 따라서 단일 소켓이 NIC의 전체 대역폭을 모두 사용할 수 없으므로, 연결된 소켓 수를 고려하여 버퍼를 조정해야 합니다.
- NIC 속도가 10Gbps라면 송신과 수신 각각 10Gbps이며, 동시에 사용 가능합니다.
- 총 예상되는 프로듀서 및 컨슈머 소켓 수로 NIC 속도를 나누어 단일 소켓당 버퍼 크기를 산정해야 합니다.
예시 (RTT 50ms, NIC 10Gbps):
- BDP = 1250MB/s × 0.05초 = 62.5MB
- 프로듀서 소켓 100개: 단일 소켓당 수신 버퍼 최소 크기 ≈ 62.5MB ÷ 100 ≈ 0.625MB
- 컨슈머 소켓 200개: 단일 소켓당 송신 버퍼 최소 크기 ≈ 62.5MB ÷ 200 ≈ 0.3125MB
15.7 설정 방법
Linux 커널 설정 (/etc/sysctl.conf)
# 소켓 기본 버퍼 크기 (512KB)
net.core.rmem_default = 524288
net.core.wmem_default = 524288
# 소켓 최대 버퍼 크기 (2MB)
net.core.rmem_max = 2097152
net.core.wmem_max = 2097152
# TCP 동적 버퍼 크기 (min, default, max)
net.ipv4.tcp_rmem = 4096 524288 2097152
net.ipv4.tcp_wmem = 4096 524288 2097152
# TCP 메모리 총량 제한 (페이지 단위)
net.ipv4.tcp_mem = 65536 131072 262144
tcp_mem설정은 순서대로 (경고 없이 허용되는 값, 소프트 리밋, 하드 리밋)이며, 각 값은 페이지 수입니다. 예를 들어65536페이지는 약 256MB(65536 × 4KB)입니다.
적용 명령어:
sudo sysctl -p
Kafka 설정 (server.properties)
# Kafka 소켓 버퍼 크기 설정
socket.receive.buffer.bytes=2097152
socket.send.buffer.bytes=2097152
BDP에 따라 더 큰 값을 적용할 수도 있습니다.
※ 참고: Kafka 브로커 설정(
socket.receive.buffer.bytes,socket.send.buffer.bytes)은 OS 커널 설정(net.core.rmem_max,net.core.wmem_max)의 최대값을 초과할 수 없습니다. Kafka가 요청한 값이 커널 최대값을 넘으면 커널이 강제로 잘라 적용합니다. 따라서 OS와 Kafka 설정을 함께 조정해야 합니다.
15.8 확인 및 측정 팁
- RTT 측정:
ping [IP주소] - NIC 속도 확인:
ethtool [인터페이스명] - 현재 소켓 버퍼 확인:
ss -tnm명령어로 소켓별 버퍼 크기 확인 가능
※ 인터페이스명은 ip addr 또는 ip link show 명령어로 실제 서버에 설정된 이름을 확인한 후 사용해야 합니다. (예: eth0, ens5 등)
15.9 추가적으로 고려해야 할 TCP 관련 설정
net.ipv4.tcp_window_scaling
TCP 윈도우 스케일링 기능을 활성화하는 옵션입니다.
net.ipv4.tcp_window_scaling = 1
이 값을 1로 설정하면 클라이언트가 데이터를 더 효율적으로 전송할 수 있으며, 브로커도 수신 데이터를 더 잘 버퍼링할 수 있습니다. 빠른 네트워크 환경에서는 필수로 켜야 하는 옵션입니다.
net.ipv4.tcp_max_sync_backlog
브로커가 동시에 처리할 수 있는 TCP 연결 요청 대기열 크기를 설정하는 옵션입니다.
net.ipv4.tcp_max_sync_backlog = 4096
기본값은 1024로 작기 때문에, Kafka 브로커처럼 많은 클라이언트 연결을 받을 경우 4096 이상으로 설정하는 것이 좋습니다.
net.core.netdev_max_backlog
네트워크 인터페이스가 처리하지 못한 패킷을 임시로 커널 큐에 쌓아두는 최대 수를 정하는 옵션입니다.
net.core.netdev_max_backlog = 5000
기본값은 1000인데, 멀티 기가비트 NIC 환경에서는 큐 길이를 크게 늘려야 네트워크 트래픽 급증 시에도 패킷 손실을 방지할 수 있습니다.