31.5. 높은 처리량을 위해 TCP 연결 튜닝
Red Hat Enterprise Linux의 TCP 관련 설정을 조정하여 처리량을 늘리거나, 대기 시간을 줄이거나, 패킷 손실과 같은 문제를 방지합니다.
31.5.1. iperf3을 사용하여 TCP 처리량 테스트
iperf3
유틸리티는 두 호스트 간의 네트워크 처리량 테스트를 수행할 수 있는 서버와 클라이언트 모드를 제공합니다.
애플리케이션 처리량은 애플리케이션에서 사용하는 버퍼 크기와 같은 여러 요인에 따라 달라집니다. 따라서 iperf3
과 같은 테스트 유틸리티로 측정한 결과는 프로덕션 워크로드에 있는 서버의 애플리케이션과 크게 다를 수 있습니다.
사전 요구 사항
-
iperf3
패키지는 클라이언트와 서버 모두에 설치됩니다. - 두 호스트의 다른 서비스가 테스트 결과에 상당한 영향을 미치는 네트워크 트래픽을 유발하지 않습니다.
- 40Gbps 및 더 빠른 연결의 경우 네트워크 카드는 가속 Receive Flow hering (ARFS)을 지원하며 인터페이스에서 기능이 활성화됩니다.
절차
선택 사항: 서버와 클라이언트 모두에서 NIC(네트워크 인터페이스 컨트롤러)의 최대 네트워크 속도를 표시합니다.
# ethtool enp1s0 | grep "Speed" Speed: 100000Mb/s
서버에서 다음을 수행합니다.
firewalld
서비스에서 기본iperf3
TCP 포트 5201을 임시로 엽니다.# firewall-cmd --add-port=5201/tcp # firewall-cmd --reload
서버 모드에서
iperf3
을 시작합니다.# iperf3 --server
이제 서비스가 들어오는 클라이언트 연결을 대기 중입니다.
클라이언트에서 다음을 수행합니다.
처리량 측정을 시작합니다.
# iperf3 --time 60 --zerocopy --client 192.0.2.1
--time <seconds
> : 클라이언트가 전송을 중지할 때의 시간을 초 단위로 정의합니다.이 매개변수를 작업할 것으로 예상되는 값으로 설정하고 이후 측정에서 늘릴 수 있습니다. 서버가 전송 경로의 장치보다 빠른 속도로 패킷을 전송하거나 클라이언트가 처리할 수 있는 경우 패킷을 삭제할 수 있습니다.
-
--zerocopy
:write()
시스템 호출을 사용하는 대신 0 복사 메서드를 활성화합니다. 복사 가능 애플리케이션을 시뮬레이션하거나 단일 스트림에서 40Gbps에 도달하려는 경우에만 이 옵션이 필요합니다. -
--client <server
>: 클라이언트 모드를 활성화하고iperf3
서버를 실행하는 서버의 IP 주소 또는 이름을 설정합니다.
iperf3
가 테스트를 완료할 때까지 기다립니다. 서버와 클라이언트 모두 1초마다 통계를 표시하고 마지막에 요약을 표시합니다. 예를 들어 다음은 클라이언트에 표시되는 요약입니다.[ ID] Interval Transfer Bitrate Retr [ 5] 0.00-60.00 sec 101 GBytes 14.4 Gbits/sec 0 sender [ 5] 0.00-60.04 sec 101 GBytes 14.4 Gbits/sec receiver
이 예에서 평균 비트레이트는 14.4 Gbps였습니다.
서버에서 다음을 수행합니다.
-
Ctrl+C 눌러
iperf3
서버를 중지합니다. firewalld
에서 TCP 포트 5201을 닫습니다.# firewall-cmd --remove-port=5201/tcp # firewall-cmd --reload
-
Ctrl+C 눌러
추가 리소스
-
시스템의
iperf3(1)
도움말 페이지
31.5.2. 시스템 전체 TCP 소켓 버퍼 설정
소켓 버퍼는 커널이 수신하거나 전송해야 하는 데이터를 임시로 저장합니다.
- 읽기 소켓 버퍼에는 커널이 수신했지만 애플리케이션은 아직 읽지 않은 패킷이 있습니다.
- 쓰기 소켓 버퍼에는 애플리케이션이 버퍼에 기록되었지만 커널이 IP 스택 및 네트워크 드라이버에 아직 전달되지 않은 패킷이 있습니다.
TCP 패킷이 너무 커서 버퍼 크기 또는 패킷이 너무 빠른 속도로 전송되거나 수신되는 경우 커널은 버퍼에서 데이터를 제거할 때까지 새로 들어오는 TCP 패킷을 삭제합니다. 이 경우 소켓 버퍼를 늘리면 패킷 손실을 방지할 수 있습니다.
net.ipv4.tcp_rmem
(read) 및 net.ipv4.tcp_wmem
(write) 소켓 버퍼 커널 설정에는 세 가지 값이 포함됩니다.
net.ipv4.tcp_rmem = 4096 131072 6291456 net.ipv4.tcp_wmem = 4096 16384 4194304
표시된 값은 바이트 단위이며 Red Hat Enterprise Linux는 다음과 같은 방식으로 사용합니다.
- 첫 번째 값은 최소 버퍼 크기입니다. 새 소켓에는 크기가 더 작을 수 없습니다.
- 두 번째 값은 기본 버퍼 크기입니다. 애플리케이션에서 버퍼 크기를 설정하지 않으면 기본값입니다.
-
세 번째 값은 자동으로 튜닝된 버퍼의 최대 크기입니다. 애플리케이션에서
SO_SNDBUF
소켓 옵션과 함께setsockopt()
함수를 사용하면 이 최대 버퍼 크기가 비활성화됩니다.
net.ipv4.tcp_rmem
및 net.ipv4.tcp_wmem
매개변수는 IPv4 및 IPv6 프로토콜 모두에 대해 소켓 크기를 설정합니다.
31.5.3. 시스템 전체 TCP 소켓 버퍼 증가
시스템 전체 TCP 소켓 버퍼는 커널이 수신하거나 전송해야 하는 데이터를 임시로 저장합니다. net.ipv4.tcp_rmem
(read) 및 net.ipv4.tcp_wmem
(write) 소켓 버퍼 커널 설정에는 각각 최소, default, maximum 값의 세 가지 설정이 포함되어 있습니다.
버퍼 크기를 너무 크게 설정하면 메모리가 소모됩니다. 각 소켓은 애플리케이션에서 요청하는 크기로 설정할 수 있으며 커널은 이 값을 두 배로 늘립니다. 예를 들어 애플리케이션이 256KiB 소켓 버퍼 크기를 요청하고 1만 개의 소켓을 여는 경우 시스템은 최대 512GB RAM(512 KiB x 1 million)을 잠재적 소켓 버퍼 공간에만 사용할 수 있습니다.
또한 최대 버퍼 크기에 너무 큰 값은 대기 시간을 늘릴 수 있습니다.
사전 요구 사항
- TCP 패킷 삭제 속도가 크게 발생했습니다.
절차
연결 대기 시간을 확인합니다. 예를 들어 클라이언트에서 서버로 ping하여 평균 Round Trip Time(RTT)를 측정합니다.
# ping -c 10 server.example.com ... --- server.example.com ping statistics --- 10 packets transmitted, 10 received, 0% packet loss, time 9014ms rtt min/avg/max/mdev = 117.208/117.056/119.333/0.616 ms
이 예에서 대기 시간은 117ms입니다.
튜닝하려는 트래픽에 대해 다음 공식을 사용하여 BMC(Delay Product)를 계산합니다.
connection speed in bytes * latency in ms = BDP in bytes
예를 들어 117ms 대기 시간이 있는 10Gbps 연결에 대한 BDP를 계산하려면 다음을 수행합니다.
(10 * 1000 * 1000 * 1000 / 8) * 117 = 10683760 bytes
요구 사항에 따라
/etc/sysctl.d/10-tcp-socket-buffers.conf
파일을 만들고 최대 읽기 또는 쓰기 버퍼 크기를 설정합니다.net.ipv4.tcp_rmem = 4096 262144 21367520 net.ipv4.tcp_wmem = 4096 24576 21367520
값을 바이트 단위로 지정합니다. 환경에 최적화된 값을 식별하려고 할 때 다음 규칙을 사용합니다.
-
기본 버퍼 크기(초 값): 이 값을 약간만 늘리거나
524288
(512 KiB)으로 설정합니다. 너무 높은 기본 버퍼 크기는 버퍼가 충돌하여 결과적으로 대기 시간이 급증할 수 있습니다. - 최대 버퍼 크기(세번째 값): BDP의 곱셈에 두 번이면 충분한 경우가 많습니다.
-
기본 버퍼 크기(초 값): 이 값을 약간만 늘리거나
/etc/sysctl.d/10-tcp-socket-buffers.conf
파일에서 설정을 로드합니다.# sysctl -p /etc/sysctl.d/10-tcp-socket-buffers.conf
더 큰 소켓 버퍼 크기를 사용하도록 애플리케이션을 구성합니다.
net.ipv4.tcp_rmem
및net.ipv4.tcp_wmem
매개변수의 세 번째 값은 애플리케이션에서setsockopt()
함수에서 요청할 수 있는 최대 버퍼 크기를 정의합니다.자세한 내용은 애플리케이션 프로그래밍 언어 설명서를 참조하십시오. 애플리케이션 개발자가 아닌 경우 개발자에게 문의하십시오.
net.ipv4.tcp_rmem
또는net.ipv4.tcp_wmem
매개변수에서 두 번째 값을 변경한 경우 애플리케이션을 다시 시작하여 새 TCP 버퍼 크기를 사용합니다.세 번째 값만 변경한 경우 자동 조정이 이러한 설정을 동적으로 적용하므로 애플리케이션을 다시 시작할 필요가 없습니다.
검증
- 선택 사항: iperf3을 사용하여 TCP 처리량을 테스트합니다.
패킷이 삭제될 때 사용한 것과 동일한 방법을 사용하여 패킷을 모니터링합니다.
패킷이 계속 발생하지만 더 낮은 속도로 패킷이 발생하면 버퍼 크기를 더 늘립니다.
추가 리소스
- 소켓 버퍼 크기 변경에 미치는 영향은 무엇입니까?
-
시스템의 TCP(7)
및socket(7)
도움말 페이지
31.5.4. TCP 창 확장
Red Hat Enterprise Linux에서 기본적으로 활성화되어 있는 TCP 창 확장 기능은 처리량을 크게 개선하는 TCP 프로토콜의 확장입니다.
예를 들어 1.5ms Round Trip Time(RTT)와 1Gbps 연결의 경우:
- TCP Window Scaling을 사용하면 약 630Mbps가 실용적입니다.
- TCP Window Scaling을 비활성화하면 처리량이 380Mbps로 줄어듭니다.
TCP가 제공하는 기능 중 하나는 흐름 제어입니다. 흐름 제어를 사용하면 수신자가 수신할 수 있는 만큼의 데이터를 보낼 수 있지만 더 이상 보낼 수 없습니다. 이를 위해 수신자는 발신자가 전송할 수 있는 데이터 양인 창
값을 알립니다.
TCP는 원래 최대 64KiB의 창 크기를 지원되지만, 높은 bandwidth Delay 제품(BDP)에서 이 값은 발신자가 한 번에 64KiB 이상을 보낼 수 없기 때문에 제한이 됩니다. 고속 연결은 한 번에 64KiB 이상의 데이터를 전송할 수 있습니다. 예를 들어 시스템 간에 1ms의 대기 시간이 있는 10Gbps 링크에는 지정된 시간에 전송 중 1MiB 이상의 데이터가 있을 수 있습니다. 호스트가 64KiB만 전송하는 경우 비효율적이며 다른 호스트에서 64KiB를 수신할 때까지 일시 중지합니다.
이러한 병목 현상을 제거하기 위해 TCP 창 확장 확장 기능을 사용하면 TCP 창 값을 요약하여 64KiB 이상으로 창 크기를 늘릴 수 있습니다. 예를 들어 65535
의 가장 큰 창 값이 7자리를 왼쪽으로 이동했기 때문에 창 크기가 거의 8MiB가 됩니다. 이렇게 하면 주어진 시간에 훨씬 더 많은 데이터를 전송할 수 있습니다.
TCP 창 확장은 모든 TCP 연결을 여는 3방향 TCP 핸드셰이크 중에 협상됩니다. 발신자와 수신자 모두 기능이 작동하려면 TCP 창 스케일링을 지원해야 합니다. 둘 중 하나 또는 둘 다 핸드셰이크에서 창 스케일링 기능을 광고하지 않으면 연결은 원래 16 비트 TCP 창 크기를 사용하는 것으로 되돌아갑니다.
기본적으로 TCP 창 확장이 Red Hat Enterprise Linux에서 활성화됩니다.
# sysctl net.ipv4.tcp_window_scaling
net.ipv4.tcp_window_scaling = 1
서버에서 TCP 창 스케일링이 비활성화된 경우(0
) 설정한 것과 동일한 방식으로 설정을 되돌립니다.
31.5.5. TCP SACK에서 패킷 드롭 속도를 줄이는 방법
RHEL(Red Hat Enterprise Linux)에서 기본적으로 사용하도록 설정된 TCP 선택 승인(TCP SACK) 기능은 TCP 프로토콜의 향상된 기능이며 TCP 연결의 효율성을 높입니다.
TCP 전송에서 수신자는 수신되는 모든 패킷에 대해 ACK 패킷을 발신자에게 보냅니다. 예를 들어 클라이언트는 TCP 패킷 1-10을 서버로 전송하지만 패킷 번호 5 및 6은 손실됩니다. TCP SACK가 없으면 서버는 패킷 7-10을 삭제하고 클라이언트가 손실 시점에서 모든 패킷을 다시 전송해야 합니다. 이는 비효율적입니다. 두 호스트에서 TCP SACK를 활성화한 상태에서 클라이언트는 손실된 패킷 5와 6만 다시 전송해야 합니다.
TCP SACK를 비활성화하면 성능이 저하되고 TCP 연결의 수신자 측에서 더 높은 패킷 드롭 속도가 발생합니다.
기본적으로 RHEL에서는 TCP SACK가 활성화됩니다. 확인하려면 다음을 수행하십시오.
# sysctl net.ipv4.tcp_sack
1
서버에서 TCP SACK (0)
이 비활성화 된 경우 설정과 동일한 방식으로 설정을 되돌립니다.