31.2. IRQ 밸런싱 튜닝
멀티 코어 호스트에서는 Red Hat Enterprise Linux가 인터럽트를 CPU 코어 간에 분산하도록 인터럽트 대기열(IRQ)의 균형을 조정할 수 있으므로 성능을 향상시킬 수 있습니다.
31.2.1. 처리기 중단 및 중단
NIC(네트워크 인터페이스 컨트롤러)가 들어오는 데이터를 수신하면 DMA(직접 메모리 액세스)를 사용하여 데이터를 커널 버퍼에 복사합니다. 그런 다음 NIC는 하드 인터럽트를 트리거하여 커널에 이 데이터에 대해 알립니다. 이러한 인터럽트는 다른 작업이 이미 중단되고 처리기가 중단될 수 없으므로 최소한의 작업을 수행하는 인터럽트 처리기에 의해 처리됩니다. 특히 커널 잠금을 사용하는 경우 CPU 사용량 측면에서 하드 인터럽트는 비용이 많이 들 수 있습니다.
그런 다음 하드 인터럽트 처리기는 대부분의 패킷 수신을 소프트웨어 인터럽트 요청(SoftIRQ) 프로세스에 남겨 둡니다. 커널은 이러한 프로세스를 보다 공정하게 예약할 수 있습니다.
예 31.1. 하드웨어 인터럽트 표시
커널은 인터럽트 카운터를 /proc/interrupts
파일에 저장합니다. enp1s0
과 같은 특정 NIC의 카운터를 표시하려면 다음을 입력합니다.
# egrep "CPU|enp1s0" /proc/interrupts CPU0 CPU1 CPU2 CPU3 CPU4 CPU5 105: 141606 0 0 0 0 0 IR-PCI-MSI-edge enp1s0-rx-0 106: 0 141091 0 0 0 0 IR-PCI-MSI-edge enp1s0-rx-1 107: 2 0 163785 0 0 0 IR-PCI-MSI-edge enp1s0-rx-2 108: 3 0 0 194370 0 0 IR-PCI-MSI-edge enp1s0-rx-3 109: 0 0 0 0 0 0 IR-PCI-MSI-edge enp1s0-tx
각 큐는 할당된 첫 번째 열에서 인터럽트 벡터를 갖습니다. 커널은 시스템이 부팅되거나 사용자가 NIC 드라이버 모듈을 로드할 때 이러한 벡터를 초기화합니다. 각 수신(RX
) 및 전송(TX
) 큐에는 인터럽트가 발생하는 NIC 또는 큐를 알리는 고유한 벡터가 할당됩니다. 열은 모든 CPU 코어에 대해 들어오는 인터럽트 수를 나타냅니다.
31.2.2. 소프트웨어 중단 요청
소프트웨어 인터럽트 요청(SoftIRQ)은 네트워크 어댑터의 수신 링 버퍼를 지웁니다. 커널은 다른 작업이 중단되지 않을 때 한 번에 실행되도록 IRQIRQ 루틴을 예약합니다. Red Hat Enterprise Linux에서 ksoftirqd/cpu-number
라는 프로세스는 이러한 루틴을 실행하고 드라이버별 코드 함수를 호출합니다.
각 CPU 코어에 대한 IRQIRQ 카운터를 모니터링하려면 다음을 입력합니다.
# watch -n1 'egrep "CPU|NET_RX|NET_TX" /proc/softirqs'
CPU0 CPU1 CPU2 CPU3 CPU4 CPU5 CPU6 CPU7
NET_TX: 49672 52610 28175 97288 12633 19843 18746 220689
NET_RX: 96 1615 789 46 31 1735 1315 470798
명령은 출력을 동적으로 업데이트합니다. Ctrl+C 눌러 출력을 중단합니다.
31.2.3. NAPI 폴링
새로운 API(NAPI)는 들어오는 네트워크 패킷의 효율성을 개선하기 위해 장치 드라이버 패킷 처리 프레임워크를 확장한 것입니다. 일반적으로 커널 공간에서 사용자 공간으로 컨텍스트를 전환하고 다시 중단할 수 없기 때문에 하드 인터럽트는 비용이 많이 듭니다. 인터럽트 병합을 사용하더라도 인터럽트 처리기는 CPU 코어를 완전히 독점합니다. NAPI를 사용하면 드라이버는 수신된 모든 패킷에 대해 커널에서 하드 인터렉션하는 대신 폴링 모드를 사용할 수 있습니다.
일반 작업에서는 커널이 초기 하드 인터럽트를 실행한 다음 NAPI 루틴을 사용하여 네트워크 카드를 폴링하는 소프트 인터럽트 요청(SoftIRQ) 핸들러가 있습니다. IRQIRQ가 CPU 코어를 독점화하는 것을 방지하기 위해 폴링 루틴은 IRQIRQ가 사용할 수 있는 CPU 시간을 결정하는 예산이 있습니다. IRQIRQ 폴링 루틴이 완료되면 커널은 루틴을 종료하고 나중에 다시 실행되도록 예약하여 네트워크 카드에서 패킷을 수신하는 프로세스를 반복합니다.
31.2.4. irqbalance 서비스
NUMA(Non-Uniform Memory Access) 아키텍처가 있고 사용하지 않는 시스템에서 irqbalance
서비스는 시스템 조건에 따라 CPU 코어 간에 인터럽트의 균형을 효과적으로 조정합니다. irqbalance
서비스는 백그라운드에서 실행되며 10초마다 CPU 부하를 모니터링합니다. CPU 부하가 너무 높은 경우 서비스는 다른 CPU 코어로 인터럽트를 이동합니다. 결과적으로 시스템은 제대로 작동하고 부하를 더 효율적으로 처리합니다.
irqbalance
가 실행되지 않으면 일반적으로 CPU 코어 0은 대부분의 인터럽트를 처리합니다. 중간 부하에도 이 CPU 코어는 시스템의 모든 하드웨어의 워크로드를 처리하려고 할 수 있습니다. 결과적으로 인터럽트 또는 인터럽트 기반 작업이 누락되거나 지연될 수 있습니다. 이로 인해 네트워크 및 스토리지 성능, 패킷 손실 및 기타 문제가 발생할 수 있습니다.
irqbalance
를 비활성화하면 네트워크 처리량에 부정적인 영향을 미칠 수 있습니다.
단일 CPU 코어만 있는 시스템에서 irqbalance
서비스는 이점을 제공하지 않고 자체적으로 종료됩니다.
기본적으로 irqbalance
서비스는 Red Hat Enterprise Linux에서 활성화되어 실행됩니다. 서비스를 비활성화한 경우 서비스를 다시 활성화하려면 다음을 입력합니다.
# systemctl enable --now irqbalance
추가 리소스
- irqbalance가 필요하십니까? (Red Hat Knowledgebase)
- 네트워크 인터페이스 IRQ 채널을 구성하려면 어떻게 해야 합니까? (Red Hat Knowledgebase)
31.2.5. CPU에서 실행할 수 있는 시간 늘리기
CloudEventIRQ가 충분히 오래 실행되지 않으면 들어오는 데이터의 속도가 버퍼를 충분히 빠르게 드레이닝하는 커널의 기능을 초과할 수 있습니다. 결과적으로 NIC(네트워크 인터페이스 컨트롤러) 버퍼 오버플로 및 패킷이 손실됩니다.
softirqd
프로세스에서 하나의 NAPI 폴링 주기의 인터페이스에서 모든 패킷을 검색할 수 없는 경우, IRQIRQ에 CPU 시간이 충분하지 않음을 나타냅니다. 이는 빠른 NIC가 있는 호스트의 경우(예: 10Gbps 및 더 빠릅니다)일 수 있습니다. net.core.netdev_budget
및 net.core.netdev_budget_usecs
커널 매개변수 값을 늘리면 폴링 주기에서 패킷 수와 패킷 수를 제어할 수 있습니다.
절차
net.core.netdev_budget
매개변수 튜닝이 필요한지 여부를 확인하려면/proc/net/softnet_stat
파일에 카운터를 표시합니다.# awk '{for (i=1; i<=NF; i++) printf strtonum("0x" $i) (i==NF?"\n":" ")}' /proc/net/softnet_stat | column -t 221951548 0 0 0 0 0 0 0 0 0 0 0 0 192058677 0 20380 0 0 0 0 0 0 0 0 0 1 455324886 0 0 0 0 0 0 0 0 0 0 0 2 ...
이
awk
명령은/proc/net/softnet_stat
의 값을 16진수에서 10진수 형식으로 변환하고 테이블 형식으로 표시합니다. 각 행은 코어 0으로 시작하는 CPU 코어를 나타냅니다.관련 열은 다음과 같습니다.
- 첫 번째 열: 수신된 총 프레임 수입니다.
-
세 번째 열: 하나의 NAPI 폴링 주기의 인터페이스에서 모든 패킷을 검색할 수 없는
softirqd
프로세스 수입니다. - 마지막 열: CPU 코어 번호입니다.
/proc/net/softnet_stat
파일의 세 번째 열에 있는 카운터가 시간에 따라 증가하면 시스템을 조정합니다.net.core.netdev_budget_usecs
및net.core.netdev_budget
매개변수의 현재 값을 표시합니다.# sysctl net.core.netdev_budget_usecs net.core.netdev_budget net.core.netdev_budget_usecs = 2000 net.core.netdev_budget = 300
이러한 설정을 통해
softirqd
프로세스는 하나의 폴링 주기로 NIC에서 최대 300개의 메시지를 처리할 수 있는 최대 2000마이크로초를 갖습니다. 폴링은 어떤 조건이 먼저 충족되는지에 따라 종료됩니다.다음 콘텐츠를 사용하여
/etc/sysctl.d/10-netdev_budget.conf
파일을 만듭니다.net.core.netdev_budget = 600 net.core.netdev_budget_usecs = 4000
매개변수를 현재 값의 double로 설정합니다.
/etc/sysctl.d/10-netdev_budget.conf
파일에서 설정을 로드합니다.# sysctl -p /etc/sysctl.d/10-netdev_budget.conf
검증
/proc/net/softnet_stat
파일에서 세 번째 열을 모니터링합니다.# awk '{for (i=1; i<=NF; i++) printf strtonum("0x" $i) (i==NF?"\n":" ")}' /proc/net/softnet_stat | column -t
값이 여전히 증가하는 경우
net.core.netdev_budget_usecs
및net.core.netdev_budget
를 더 높은 값으로 설정합니다. 카운터가 더 이상 증가하지 않을 때까지 이 프로세스를 반복합니다.