前回はmod_mrubyを導入して簡単なRubyスクリプトでApacheの挙動を確認するところまでやりました。続いて今回もmrubyの話で、Cgroupを有効にしてその効果を確認するとこまでやろうかなっと思います。セミの声を聞きながら部屋でゴロゴロしていると気分だけは夏休み気分になるね〜。気分だけね。
cgroupって何づら?
LinuxKernelの機能の1つで、利用方法はいろいろとあります。が、難しい話はスルーしましょう。
cgroupを略さずに書くとコントールグループで、何のコントールかというとリソースです。
リソースっつうと、CPU、メモリ、ディスクI/Oとかですな。
コントロールと言っても色々ありそうだし説明文にするとややこしくなりそうなので、Wikipediaから抜粋して箇条書きにしてみますと。
- リソース制限
- 優先順位
- どれだけのリソースを使用しているか計上
- 隔離
- 一時停止・再開など
などなど。
こうして書き出しただけでも色々なことができるのだなぁと。
ただ今回の目的はまずはApacheに対してCPUの利用を50%にしまぁーす。するってーと、参考サイトのままですが挙動の確認なので良しとします。
Cgroupじたいは以前にも少し触ってて。
関連記事
Cでサーバー監視のプログラムを作ってみよう その4
もう1年以上も前になるんですなぁ、なつかしや。
インストール
まずはcgroupを有効にするにはmod_mrubyもリビルドしなければいけません。
やるべきことはコメントアウトを外すだけではなくて色々必要なのでした。
まずはCgroupをインストールしてApacheがアクセス可能なグループを作成しときます。
# yum install -y libcgroup libcgroup-devel
# chkconfig cgconfig on
# service cgconfig start
# mkdir /cgroup/cpu/apache
# chown -R apache:apache /cgroup/cpu/apache
# ls -l /cgroup/cpu/apache/
合計 0
--w--w--w-. 1 apache apache 0 7月 19 23:02 2015 cgroup.event_control
-rw-r--r--. 1 apache apache 0 7月 19 23:02 2015 cgroup.procs
-rw-r--r--. 1 apache apache 0 7月 19 23:02 2015 cpu.cfs_period_us
-rw-r--r--. 1 apache apache 0 7月 19 23:02 2015 cpu.cfs_quota_us
-rw-r--r--. 1 apache apache 0 7月 19 23:02 2015 cpu.rt_period_us
-rw-r--r--. 1 apache apache 0 7月 19 23:02 2015 cpu.rt_runtime_us
-rw-r--r--. 1 apache apache 0 7月 19 23:02 2015 cpu.shares
-r--r--r--. 1 apache apache 0 7月 19 23:02 2015 cpu.stat
-rw-r--r--. 1 apache apache 0 7月 19 23:02 2015 notify_on_release
-rw-r--r--. 1 apache apache 0 7月 19 23:02 2015 tasks
続いてmod_mrubyのリビルド。
常に新しくなっていると思われるのでgit pullしておいて良いかなと思われ。
# cd mod_mrubyのディレクトリ
# git pull
# git submodule init
# git submodule update
# vim build_config.rb
mruby-cgroup.git #このコメントアウトを外して有効化します。
# cd mruby
# rake CFLAGS="-fPIC"
# cd ..
# ./configure
# make
# make install
これで多分(検証で色々と動かしていたので多分ってことで。もしかしたら何か抜けてるかもしれん。)
動くはず。
下のような感じのスクリプトを用意してアクセスしてみて、cgroup::CPUで使えるメソッドが表示されてればOKです。
c = Cgroup::CPU.new("apache/mod_mruby_group")
Apache.echo c.methods
ちなみにちゃんと動いていると指定されていたファイルができてます。
たぶん動いてるかも??ということはありませんww
# ls /cgroup/cpu/apache/mod_mruby_group/
cgroup.event_control cpu.cfs_period_us cpu.rt_period_us cpu.shares notify_on_release
cgroup.procs cpu.cfs_quota_us cpu.rt_runtime_us cpu.stat tasks
ここで一息
そのうちやるであろう動的なコントールに備えて、Apache::Scoreboardを使ってみた時の話でもしますか。
まずは最初は全く動かなくて、フックのタイミングが良くないのか?とかとか思って色々試していたのですが、どうやら
ExtendedStatus On
にする必要があったようだ。
・・・ぐぬぬ。
初歩的な問題なようである。
上手くデータがとれていると以下のように表示がされます。
- idle worker = 6
- busy worker = 2
実験のためにMPMの設定を極端に変えてみます。
# httpd.conf prefork.c
StartServers 1
MinSpareServers 1
MaxSpareServers 20
ServerLimit 256
MaxClients 256
MaxRequestsPerChild 4000
ApacheBenchでつんつくつんと突っついて変化を見てみます。
まずは実行前です。
- idle worker = 0
- busy worker = 1
ApacheBenchしてみます。
途中経過ですがドカドカっと増えて減ったとこ。
- idle worker = 60
- busy worker = 65
終わった後です。
このあとMaxSpareServersの設定値まで減っていくはず。
- idle worker = 94
- busy worker = 2
終了だ。
- idle worker = 19
- busy worker = 1
微妙に長くなりましたが、これで上手くデータはとれていることは分かりました。
しかしスレッド数とかはちゃんと取れてるのに、ロードアベレージが取れないのはどこかミスってるのだろうか。。
では本題に戻りましょう。
mruby-cgroupの実験
参考サイト
人間とウェブの未来
リクエスト単位でApacheのリソースを制御するためのmrubyを使った制御DSLコードの紹介
単純に全てのリクエストをCPU50%に制御!というのをやってみます
以前作っていた円周率計算CGIをリクエストして挙動を見てみる。
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
2726 apache 20 0 38660 7720 2052 R 99.7 0.8 0:07.01 index.cgi
実行スパーン!これで成功です!
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
4165 apache 20 0 38660 7716 2052 R 49.9 0.8 0:14.88 index.cgi
いやぁ、分かりづれ〜!(^_^メ)
ということで
suexec環境で試してみる
少しはわかりやすくなるかと思うので、take、jiro、sayoの3人に試していただくとしよう。
設定はこんな感じで何でもOkになっています。
<Directory /home/*/public_html>
Options All
AllowOverride All
AddHandler cgi-script .cgi .pl .php
</Directory>
<VirtualHost *:80>
DocumentRoot /home/take/public_html
ServerName take.example.com
SuexecUserGroup take take
</VirtualHost>
<VirtualHost *:80>
DocumentRoot /home/jiro/public_html
ServerName jiro.example.com
SuexecUserGroup jiro jiro
</VirtualHost>
<VirtualHost *:80>
DocumentRoot /home/sayo/public_html
ServerName sayo.example.com
SuexecUserGroup sayo sayo
</VirtualHost>
ところがどっこいで、ここでひとつ問題が発生、suexecのDocrootが/var/wwwでした。
ググってみるとどうやらリビルドは不要で、バイナリで編集したら変更できるらしいので、生まれて初めてemacsを使ってみました。
生まれ〜て〜、はじめ〜て〜。
編集前
# /usr/sbin/suexec.org -V
-D AP_DOC_ROOT="/var/www"
-D AP_GID_MIN=100
-D AP_HTTPD_USER="apache"
-D AP_LOG_EXEC="/var/log/httpd/suexec.log"
-D AP_SAFE_PATH="/usr/local/bin:/usr/bin:/bin"
-D AP_UID_MIN=500
-D AP_USERDIR_SUFFIX="public_html"
編集後
[root@testcentos sbin]# suexec -V
-D AP_DOC_ROOT="/home"
-D AP_GID_MIN=100
-D AP_HTTPD_USER="apache"
-D AP_LOG_EXEC="/var/log/httpd/suexec.log"
-D AP_SAFE_PATH="/usr/local/bin:/usr/bin:/bin"
-D AP_UID_MIN=500
-D AP_USERDIR_SUFFIX="public_html"
じゃじゃーん。成功しました。
パーミッションも戻さないと、動かないの〜よ〜。
# chmod 4755 /usr/sbin/suexec
# ls -la /usr/sbin/suexec
-rwsr-xr-x. 1 root apache 13984 7月 20 01:17 2015 /usr/sbin/suexec
これでtakeとjiroに円周率計算CGIにアクセスしてみませう。
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
4866 take 20 0 38660 7720 2052 R 24.9 0.8 0:01.67 index.cgi
4868 jiro 20 0 38660 7716 2052 R 24.9 0.8 0:01.04 index.cgi
これが結果ですが、合計で50%なので2人で50%でちゃんと動いているってのがさっきよりは分かると思います。
3人用意する必要もなかったわけですがまぁいいでしょう。
余談になりますが、円周率計算もなかなかリソースが必要なようでこの結果はこうなっちゃいました。
とまぁ、せっかくなのでユーザー毎に制限をしてみますか。
条件はバーチャルホストだったらドキュメントルートかホストネームはユニークだと思うので、今回はドキュメントルートで指定。
分かりやすくするようにtakeさんの場合は5%なんて数字にしてみます。
s = Apache::Server.new
if s.document_root == "/home/take/public_html"
c = Cgroup::CPU.new("apache/mod_mruby_group")
c.cfs_quota_us = 5000
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
6051 jiro 20 0 38660 7716 2052 R 44.9 0.8 0:15.19 index.cgi
6055 sayo 20 0 38660 7720 2052 R 44.9 0.8 0:10.41 index.cgi
6053 take 20 0 38660 7720 2052 R 10.0 0.8 0:02.58 index.cgi
これで前回よりは使ってる感が出てまいりました。これで&条件でも付け足せばそれなりな形になると思われ。
元からこのプログラムにはリソースをあまり使いたくないなぁなんて時にも使えますね。
そんな感じで今回はおわり〜。
