LoginSignup
265

More than 5 years have passed since last update.

Linux ネットワークパフォーマンスの機能強化

Posted at

ソフトウェア割り込みが偏る?

Linuxを利用していて、ネットワーク負荷が高いサーバを運用していると、特定のCPU負荷が高くなっている事があるのですが、そのようなケースを経験されたことはないでしょうか?

topでみると特定CPU(topを起動して1を押すとCPU単位で確認できる)の%si(software interrupt)がやたら高くなっている場合、それはネットワークの負荷が原因かも知れません。(実際のtopを貼り付けたかったのですが、持ち合わせがなかった・・・。)何も設定していない場合はネットワークの割り込みは特定のCPUで行われるため、ネットワークの割り込みに関連づいたCPUの%siが高くなります。ソフトウェア割り込みを確認するには、/proc/interruptsを確認しましょう。

# cat /proc/interrupts 
           CPU0       CPU1       CPU2       CPU3       
  0:        129          0          0          0   IO-APIC-edge      timer
  1:          7          1          0          0   IO-APIC-edge      i8042
  7:          0          0          0          0   IO-APIC-edge      parport0
  8:          0          0          0          0   IO-APIC-edge      rtc0
  9:          0          0          0          0   IO-APIC-fasteoi   acpi
 12:        108          1          0          1   IO-APIC-edge      i8042
 14:         22          1         39         21   IO-APIC-edge      ata_piix
 15:          0          0          0          0   IO-APIC-edge      ata_piix
 16:          0          0          0          0   IO-APIC-fasteoi   vmci
 17:     129013     482231      35345      34170   IO-APIC-fasteoi   ioc0
 18:   21809010          8          0          0   IO-APIC-fasteoi   eth0
 24:          0          0          0          0   PCI-MSI-edge      pciehp
<< snip >>

※ 下から2行目でeth0がCPU0で処理されていることがわかります。

要するに、これを各CPUで分散させればOKなわけです。これらを分散させるにはハードウェア的に行う方法(高級?なNICが必要。Multi-Queue NICと言われている奴になります。詳細は「Receive Side Scaling (RSS)」で検索しましょう。ちなみにvmwareのvmxnet3はmulti-queue対応です。)とソフトウェアで実現する方法があるのですが、今回はソフトウェア的に分散させる方法をご紹介します。

RPS,RFSを設定しよう

機能的には「Receive Packet Steering(RPS)」と「Receive Flow Steering(RFS)」を利用します。RHELのドキュメントでは、下記に記載が有ります。6.1以降と記載が有りますね。(なので、CentOS6.1以降であれば使える。)
https://access.redhat.com/documentation/ja-JP/Red_Hat_Enterprise_Linux/6/html/Performance_Tuning_Guide/main-network.html#s-network-future
RPSがRSSをソフトウェア的に実現したもので、分散先をより最適にするのがRFSとなります。

具体的な設定方法は、先のRHELのドキュメントにもありますがRPSの設定は「/sys/class/net/ethX/queues/rx-N/rps_cpus」へどのCPUへ分散させるかを指定します。ちなみにCentOS6.6で確認すると、rx-Nに加えてtx-Nも確認できます。きっと受信に加えて送信でも分散させることが出来るのでしょう。(ちゃんと調べてない) rx-Nはmulti-queue nicの場合は複数存在することになります。(つまりはrx-0しか無いケースが多い。)

rps_cpusに指定する値ですが、CPU数を2進数の10で表現し、それを16進数に直した値を指定します。わかりづらいですね。例えば4CPUであれば、4bitで1111(16進数でf)で全CPUで処理。0011(16進数で3)で2個のCPUで処理、と言った感じです。1001(9)なんかも行けます(これも2個のCPUだけど、1番目と4番目を使う)。

# echo f > /sys/class/net/eth0/queues/rx-0/rps_cpus
# echo f > /sys/class/net/eth0/queues/tx-0/xps_cpus

RFSの方は「/proc/sys/net/core/rps_sock_flow_entries」と「/sys/class/net/ethX/queues/rx-N/rps_flow_cnt」を設定する必要が有ります。rps_sock_flow_entriesはシステム全体のエントリー数、rps_flow_cntはNICのqueue毎のエントリー数を設定し、合計がrps_sock_flow_entriesを超えてはいけないようです。どれぐらいが適切かは、アプリやミドルウェア、使い方によってきそうですが、Unbreakable Linuxのドキュメントが参考になるかも知れません。

RFSを有効にするには、rps_sock_flow_entriesの値を現在アクティブな接続の最大予測数に設定し、rps_flow_cntの値をrps_sock_flow_entries/Nqに設定します(Nqはデバイス上の受信キューの数です)。入力値は、すべて2の最も近い累乗値に切り上げられます。適度な負荷のサーバーに対して推奨されるrps_sock_flow_entriesの値は、32768です。

# echo 32768 > /proc/sys/net/core/rps_sock_flow_entries
# echo 32768 > /sys/class/net/eth0/queues/rx-0/rps_flow_cnt

設定したらtopで%siがばらけているか確認してみましょう!
実際効果があるかなどは実機で確認した方が良いです。ちゃんと確認しましょう。ばらけたのは確認できても、パフォーマンス自体は変わらないとかもありえますね。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
265