AMIが公開されたのでもう一度やってみた。
AMIについてはこちらのエントリに書かれています
ISUCON4 予選問題の解説と講評 & AMIの公開 : ISUCON公式Blog
まず ami-e3577fe2 を m3.xlargeで起動します。
CPUは
model name : Intel(R) Xeon(R) CPU E5-2670 v2 @ 2.50GHz
でした。
とりあえず、MySQLのindexを追加する。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
ベンチマークツールのhttp keepaliveが無効なので、sysctrl.conf でephemeral portを拡大したり、TIME_WAITが早く回収されるように変更する
$ 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
ついでに、backlogも増やしている。
適用は
sudo /sbin/sysctl -p
で行う。
セッション管理にmemcachedを使うのでいれる
sudo yum install -y wget libevent-devel perl-devel
cd /tmp
wget http://www.memcached.org/files/memcached-1.4.21.tar.gz
tar zxf memcached-1.4.21.tar.gz
cd memcached-1.4.21
./configure --prefix=/usr/local/memcached && make && sudo make install
Supervisord経由で起動
[program:memcahed]
directory=/
command=/usr/local/memcached/bin/memcached -p 11211 -U 0 -u nobody -m 256 -c 200000 -v -t 1 -C -B ascii
autostart = true
memcachedの起動オプションについてはこのエントリが詳しい
memcached おすすめ起動オプションまとめ - blog.nomadscafe.jp
次に、Perlにアプリケーションを変更し、起動方法も変更
まず、cpanfileに以下を追加してcarton install
$ cat cpanfile
requires "Kossy", 0.38;
requires "Starlet", 0.24;
requires "URL::Encode::XS";
requires "Plack::Middleware::Session::Simple";
requires "Cache::Memcached::Fast";
requires "Sereal";
$ carton install
アプリケーションはStarletをつかって起動。その際にunix domain socketをlistenする
[program:isucon_perl]
directory=/home/isucon/webapp/perl
command=/home/isucon/env.sh carton exec start_server --path /dev/shm/app.sock --backlog 16384 -- plackup -s Starlet --workers=4 --max-reqs-per-child 500000 --min-reqs-per-child 400000 -E production -a app.psgi
user=isucon
stdout_logfile=/tmp/isucon.perl.log
stderr_logfile=/tmp/isucon.perl.log
autostart=true
Starlet + unix domain socketの話はこちらのエントリ
Starlet + Server::Stater で UNIX domain socketに対応しました - Hateburo: kazeburo hatenablog
セッションまわりだけ、PlackのMiddlewareを入れ替える
use Cache::Memcached::Fast;
use Sereal;
my $decoder = Sereal::Decoder->new();
my $encoder = Sereal::Encoder->new();
my $app = Isu4Qualifier::Web->psgi($root_dir);
builder {
enable 'ReverseProxy';
enable 'Session::Simple',
store => Cache::Memcached::Fast->new({
servers => [ { address => "localhost:11211",noreply=>0} ],
serialize_methods => [ sub { $encoder->encode($_[0])},
sub { $decoder->decode($_[0])} ],
}),
httponly => 1,
cookie_name => "isu4_session",
keep_empty => 0;
$app;
};
ここで使っているPlack::Middleware::Session::Simpleはこのエントリで紹介しています
Plack::Middleware::Session::Simple has been released - Hateburo: kazeburo hatenablog
そして、nginxの設定変更
$ 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;
}
}
}
cssや画像をnginxから配信するのと、アプリケーションサーバがunix domain socketになったのでその切り替え
nginxの設定はこのエントリが参考になるかな
G-WANはなぜ速いのか?をnginxと比べながら検証してみた - blog.nomadscafe.jp
最後にmysqlの設定
$ cat /etc/my.cnf
innodb_buffer_pool_size = 1G
innodb_flush_log_at_trx_commit = 0
innodb_flush_method=O_DIRECT
この3つだけ追加
全ての設定ができたので、mysql、nginxとSupervisordを再起動
$ sudo service mysqld restart
$ sudo /usr/bin/supervisorctl reload
$ sudo service nginx restart
これで準備完了。
いよいよ、benchmarkを動かしてみる
$ ./benchmarker bench --workload 8
07:51:41 type:info message:launch benchmarker
07:51:41 type:warning message:Result not sent to server because API key is not set
07:51:41 type:info message:init environment
07:51:50 type:info message:run benchmark workload: 8
07:52:50 type:info message:finish benchmark workload: 8
07:52:55 type:info message:check banned ips and locked users report
07:52:57 type:report count:banned ips value:605
07:52:57 type:report count:locked users value:4384
07:52:57 type:info message:Result not sent to server because API key is not set
07:52:57 type:score success:188930 fail:0 score:40812
見事予選突破ラインの37,808を、アプリケーションのコードを変更せずに超える事に成功しました。ぱちぱちぱち
// 追記
実際のスコアはtagomorisとsugyanのアプリケーションの変更が入って、ここから+10k以上だし、僕のしたことは足場を組んだだけ
— masahiro nagano (@kazeburo) October 14, 2014