それほどCPU負荷も高くないはずなのになんとなく「もっさり」してる…という事案に直面している方のお役に立てるかもしれません。
困っていたこと
状況の把握
対象となるサーバ群はApache/PHPでサービスを提供しています。
AWS/ParaVirtual/c3.2xlargeという構成ですので、8coreが利用できる状態です。
稼働中の問題点は以下のようなものです。
- 特定のコアに負荷が偏っている
- CPU負荷としてはそれほど高くないはずなのに、ネットワーク転送などが時々詰まる
top - 19:29:57 up 9:08, 1 user, load average: 0.92, 0.70, 0.69
Tasks: 427 total, 3 running, 424 sleeping, 0 stopped, 0 zombie
Cpu0 : 54.6%us, 5.7%sy, 0.0%ni, 25.7%id, 0.0%wa, 10.8%hi, 3.2%si, 0.0%st
Cpu1 : 21.4%us, 2.4%sy, 0.0%ni, 76.3%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu2 : 18.9%us, 1.7%sy, 0.0%ni, 79.5%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu3 : 16.8%us, 1.3%sy, 0.0%ni, 81.9%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu4 : 48.5%us, 5.1%sy, 0.0%ni, 46.4%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu5 : 3.0%us, 0.7%sy, 0.0%ni, 96.3%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu6 : 0.3%us, 0.0%sy, 0.0%ni, 99.7%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu7 : 0.3%us, 0.0%sy, 0.0%ni, 99.7%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Mem: 15429800k total, 6926292k used, 8503508k free, 116324k buffers
Swap: 1048568k total, 0k used, 1048568k free, 4033932k cached
この場合、CPU0/CPU4が比較的負荷が高く、他のものはそれほどでもないという状態で負荷の偏りが確認できます。この状態を改善することを目的としてます。
先人の叡智
このような状態に対し、以下のような知見を公開されている方がいらっしゃったので参考にします。
http://yuuki.hatenablog.com/entry/linux-networkstack-tuning-rfs
RPS/RFS/XPSで解決してみる
RPS/RFS/XPSとはナニか
https://access.redhat.com/documentation/ja-JP/Red_Hat_Enterprise_Linux/6/html/Performance_Tuning_Guide/main-network.html
https://access.redhat.com/documentation/ja-JP/Red_Hat_Enterprise_Linux/6/html/6.2_Release_Notes/networking.html
ネットワーク送受信キューを分散させることで特定コアへの負荷の偏りをなくし、全体のスループットを向上させることを目的としています。
関連しそうなQiitaエントリー
古めのCentOS(HVM)でSR-IOVに対応させる
LinuxでRPS/RFS/XPSを使いたい方へのシェルスクリプト
事例: とあるサービスサーバ群での実証試験
LinuxでRPS/XPSを使いたい方へのシェルスクリプトを適用しました。
OS再起動などでも適用できるように、init script化/rc.localへの記述/cloud-initでの実施などで対応することをおすすめします。
RPS/XPS適用後
hiの部分の偏りが残っていますが、ハードウェア割り込みの部分なので致し方ないものです。
他の負荷については概ね平均的に分散できています。
top - 19:29:30 up 9:00, 1 user, load average: 0.53, 0.66, 0.69
Tasks: 421 total, 2 running, 419 sleeping, 0 stopped, 0 zombie
Cpu0 : 12.9%us, 0.9%sy, 0.0%ni, 75.1%id, 0.0%wa, 10.7%hi, 0.3%si, 0.0%st
Cpu1 : 13.7%us, 1.7%sy, 0.0%ni, 84.0%id, 0.0%wa, 0.0%hi, 0.7%si, 0.0%st
Cpu2 : 16.9%us, 1.3%sy, 0.0%ni, 79.8%id, 0.0%wa, 0.0%hi, 2.0%si, 0.0%st
Cpu3 : 10.4%us, 1.0%sy, 0.0%ni, 87.6%id, 0.0%wa, 0.0%hi, 1.0%si, 0.0%st
Cpu4 : 17.0%us, 1.0%sy, 0.0%ni, 80.7%id, 0.0%wa, 0.0%hi, 1.3%si, 0.0%st
Cpu5 : 13.7%us, 1.3%sy, 0.0%ni, 83.7%id, 0.0%wa, 0.0%hi, 1.3%si, 0.0%st
Cpu6 : 14.9%us, 1.3%sy, 0.0%ni, 82.1%id, 0.0%wa, 0.0%hi, 1.7%si, 0.0%st
Cpu7 : 12.0%us, 1.3%sy, 0.0%ni, 85.3%id, 0.0%wa, 0.0%hi, 1.3%si, 0.0%st
Mem: 15429800k total, 7038160k used, 8391640k free, 117932k buffers
Swap: 1048568k total, 0k used, 1048568k free, 4179812k cached
ToDo
サービスプロセスを特定コアに固定させた上で「それ以外のコア」へのネットワーク処理割り当てを行うなどの方法論もあるかもしれません。
Redisなどシングルコアで動くものなどが特に有効ではないかと思うのでいずれ試験したいと考えています。