現実的なWebサービス環境において、Raptor(Phusion Passenger 5)によるパフォーマンス向上がどの程度のものか調査するために、 ISUCON4 の予選問題のうち、Unicorn 部分を Raptor 化してベンチマークをとってみた。典型的なWebサービスシステムの3層構造(Proxy, App, DB)を構築し、ベンチマーカーにより高ワークロードを実現できるので、ISUCON の予選問題は適当な題材といえる。
EDIT: Unicornの2倍のパフォーマンスを実現したRackサーバ「Rhebok」をリリースしました - blog.nomadscafe.jp を参考に unicorn の worker_processes を 4 に調節しました。念のため、あわせて raptor の min-instances も 4 に調節して再計測しました (2014/12/19)
ベンチマーク条件
基本的に、ISUCON4予選のレギュレーションに則る。
インスタンスタイプ: m3.xlarge CPU: Xeon E5-2670 v2 @ 2.50GHz 4 vCPU メインメモリ: 16GB RAM ストレージ: EBS Magnetic volumes OS: Amazon Linux 3.14.19-17.43
* ここまで y_uuk1 テンプレ
- ISUCON4 予選のデフォルト状態(unicorn)
- ISUCON4 予選のデフォルト状態(raptor standalone に変更)
- kazeburo の術 を適用(unicorn)
- kazeburo の術 を適用(raptor standalone に変更)
- kazeburo の術 を適用(raptor on nginx に変更)
で比較する
kazeburo の術 Ruby 版
ISUCON4 予選でアプリケーションを変更せずに予選通過ラインを突破するの術 から以下の3つを除外した形
- memcached
- perl 関連 (cpanfile や app.psgi の変更)
- /etc/supervisord.conf の変更
init.sh に以下を追加
$ cat init.sh
cat <<'EOF' | mysql -h ${myhost} -P ${myport} -u ${myuser} ${mydb}
alter table login_log add index ip (ip), add index user_id (user_id);
EOF
/etc/sysctl.conf に以下を追加。
$ cat /etc/sysctl.conf
net.ipv4.tcp_max_tw_buckets = 2000000
net.ipv4.ip_local_port_range = 10000 65000
net.core.somaxconn = 32768
net.core.netdev_max_backlog = 8192
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 10
sudo /sbin/sysctl -p
で適用
/etc/nginx/nginx.conf の設定
$ cat /etc/nginx/nginx.conf
worker_processes 1;
events {
worker_connections 10000;
}
http {
include mime.types;
access_log off;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
etag off;
upstream app {
server unix:/dev/shm/app.sock;
}
server {
location / {
proxy_pass http://app;
}
location ~ ^/(stylesheets|images)/ {
open_file_cache max=100;
root /home/isucon/webapp/public;
}
}
}
/etc/my.conf の設定
$ cat /etc/my.cnf
innodb_buffer_pool_size = 1G
innodb_flush_log_at_trx_commit = 0
innodb_flush_method=O_DIRECT
Ruby 専用の追加設定
env.sh に以下を追加
export RACK_ENV=production
unicorn_config を以下のように変更(2012/12/19 追加)
worker_processes 4
preload_app true
Procfile を以下のように変更
unicorn: bundle exec unicorn -c unicorn_config.rb -l /dev/shm/app.sock
再起動して適用
$ sudo service mysqld restart
$ sudo supervisorctl restart isucon_ruby
$ sudo service nginx restart
Raptor への切り替え(standalone)
Gemfile
- gem "unicorn"
+ gem "passenger", "= 5.0.0.beta1"
Procfile (unicorn_config.rb で worker_processes 4
としたので --min-instances を 4 にしてみた)
- unicorn: bundle exec unicorn -c unicorn_config.rb -l /dev/shm/app.sock
+ passenger: bundle exec passenger start --min-instances 4 -S /dev/shm/app.sock
Raptor on Nginx
passenger を nginxに組み込んで動かす
2.5. Generic installation, upgrade and downgrade method: via RubyGems の手順で
gem install passenger --pre -v 5.0.0.beta1
nginx を passenger module 付きでビルドしなおす。nginx は消さなくてもいいよ、と書いてあったがいちおう消しておいた
sudo yum remove nginx
g++ がない、と怒られたのでいれておく. インストール先ディレクトリも作っておく
sudo yum -y install gcc-c++
sudo mkdir /opt/nginx
sudo chmod a+w /opt/nginx
passenger gem に入っている以下のコマンドでビルド&インストール
$ passenger-install-nginx-module --auto
/opt/nginx/conf/nginx.conf を以下のように変更 (kazeburo の術仕様)
worker_processes 1;
events {
worker_connections 10000;
}
http {
passenger_root /home/isucon/.local/ruby/lib/ruby/gems/2.1.0/gems/passenger-5.0.0.beta1;
passenger_ruby /home/isucon/.local/ruby/bin/ruby;
include mime.types;
access_log off;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
etag off;
server {
listen 80;
root /home/isucon/webapp/ruby/public;
passenger_enabled on;
passenger_min_instances 4;
location ~ ^/(stylesheets|images)/ {
open_file_cache max=100;
}
}
}
public ディレクトリが config.ru と同じ階層にないとダメなので、symbolic link をはってごまかす
ln -s /home/isucon/webapp/public /home/isucon/webapp/ruby/
起動
sudo /opt/nginx/sbin/nginx
ベンチマーク結果
- benchmarker の workload 指定は全て 8 (一定)
構成 | スコア |
---|---|
unicorn(default) | 2433 |
raptor standalone(default) | 2483 |
unicorn(kazeburo) | 40983 |
raptor standalone(kazeburo) | 40359 |
raptor on nginx(kazeburo) | 40358 |
unicorn の場合は kazeburo の術で4万超えていなかったが Raptor で 4万超えの結果となった。Introducing Phusion Passenger 5 beta 1, codename “Raptor” の記事で彼らが「Hello World ベンチの結果なんてたいして意味がないんだよ」と言っていた通り現実に近いアプリで評価すると確かに4倍とはならなかったが、それでも ISUCON 民としてこの結果はうれしい。
(2014/12/19) unicorn とあまり変わらない結果となった。Introducing Phusion Passenger 5 beta 1, codename “Raptor” の記事で彼らが「Hello World ベンチの結果なんてたいして意味がないんだよ」と言っていたのでそんなものかもしれない。後述するが fail があったので、その影響は大きそう。
passenger module 組み込みの nginx をビルドして動かしてみたが、スコアは変わらなかった。
Raptor のエラー
なお、Raptor で以下のようなエラーが出ていた。こちらの Issue で対応中のようだ。
03:33:52 passenger.1 | App 6297 stderr: /home/isucon/.local/ruby/lib/ruby/gems/2.1.0/gems/passenger-5.0.0.beta1/lib/phusion_passenger/config/system_metrics_command.rb:32:in `exec'
03:33:52 passenger.1 | App 6297 stderr: : No such file or directory - /home/isucon/.local/ruby/lib/ruby/gems/2.1.0/gems/passenger-5.0.0.beta1/buildout/support-binaries/PassengerAgent (Errno::ENOENT)
03:33:52 passenger.1 | App 6297 stderr: from /home/isucon/.local/ruby/lib/ruby/gems/2.1.0/gems/passenger-5.0.0.beta1/lib/phusion_passenger/config/system_metrics_command.rb:32:in `run'
03:33:52 passenger.1 | App 6297 stderr: from /home/isucon/.local/ruby/lib/ruby/gems/2.1.0/gems/passenger-5.0.0.beta1/lib/phusion_passenger/config/main.rb:75:in `run!'
03:33:52 passenger.1 | App 6297 stderr: from /home/isucon/.local/ruby/lib/ruby/gems/2.1.0/gems/passenger-5.0.0.beta1/bin/passenger-config:37:in `<main>'
また、これとはおそらく原因が別だと思われるが benchmarker では以下のような結果がでて、ちょくちょく fail していた。
04:57:45 type:fail reason:Expected selector is not found: //*[@id='notice-message'] method:GET uri:/
04:57:45 type:fail reason:Expected html text is match: This account is locked., got Wrong username or password method:GET uri:/
画面を直接さわると正常に動いているように見えるので、並列で高負荷をかけた時の問題だろうか、と推測している。
04:45:33 type:score success:185820 fail:5584 score:40141
stable 版になって、全てが success に転じるともっと得点が伸びる期待がある。