読者です 読者をやめる 読者になる 読者になる

CA MOBILE エンジニアブログ

株式会社シーエー・モバイルのエンジニアブログです

ISUCON4予選に参加しました

こんにちは。

社内ではアプリ、サーバなんでも来い!のエンジニアのおのtです。

9/27日に開催されたISUCON4のオンライン予選に、社内でメンバー募集を行い3チームのC.A.Mobileのエンジニアチームを結成して参加しました!

ISUCONについてはこちら

私のチームは fire_in_the_hole! というチームで、 新卒のエンジニアとの2人チームであれやこれやいいながら進めていきました。

今回はそのときどんな感じで作業を進めていたか解説しようと思います。

10:00 〜

  • AWS での AMI からインスタンス作成して pem ファイルを共有してメンバーが ssh できるように設定、レギュレーションに違反してないかビクビクする
  • 動作しているミドルウェアの確認 -> nginx, MySQL5.5, unicorn, sinatra
  • デフォルトのスコア確認 -> 1300 くらいでした
  • 一旦ボトルネックを探す
  • nginx の ログ探す、 /var/log/ 漁る、 nginx のアクセスログ応答時間を記録するように nginx.conf 設定 ( 以下を参照 )

# nginx.conf

最後の$request_timeは処理時間(ms)

log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for" $request_time';

 

11:00 〜

  • slow-log がでない。。。
  • MySQL my.cnf のチューニング
  • MySQLにインデックス張る

あれ??全然効果上がんなくね?ってなって他にできることがあるから放置したけど、そのせいであとであたふたすることになる。。。

  • 新卒のエンジニアに各種ログの出力を見てもらう
  • 新卒のエンジニアに「unicornをいいかんじにしてくれたまえ」と丸投げする
  • nginx のチューニング

リソース割当がなんとなく少なそうなのでなんか worker とかの数値とかをいじって様子見。worker は CPU の数と合わせました。 # nginx.conf worker_processes 4; worker_cpu_affinity 001 010 011 100;

http { sendfile on; tcp_nopush on; tcp_nodelay on;

keepalive_timeout 10;

connection_pool_size 256; client_header_buffer_size 1k; large_client_header_buffers 4 2k; request_pool_size 4k; if_modified_since before; ignore_invalid_headers on; server_tokens off;

 

12:00 〜

追加した設定はこんな感じ

# nginx.conf

Static files will be served directly.

location ~* ^.+.(?:css|js|jpeg|gif|ico|png)$ { root /home/isucon/webapp/public; access_log off; expires 3d; tcp_nodelay off; open_file_cache max=3000 inactive=120s; open_file_cache_valid 45s; open_file_cache_min_uses 2; open_file_cache_errors off; }

あと nginx 設定初めてで色々よくわからないのでどこの location 設定を読んでるか切り分けたいのでログ出力をわける # nginx.conf location / { access_log /var/log/nginx/access_isu.log main; proxy_pass http://app; }

 

13:00 〜

  • nginx を早くしようとしてキャッシュ設定をいれる

銀行のシステムを模したものなのにログインすると別の人のアカウント情報が表示される斬新なシステムになりました。この設定は誰にも言わずに消しました。

  • MySQL チューニングをさらに行ってみる

さらにいつもやっている感じで以下の設定を入れる

# my.cnf wait_timeout = 15 max_connections=450 thread_cache=20 thread_cache_size = 20 table_cache=20 innodb_buffer_pool_size=2048M innodb_flush_log_at_trx_commit=0

クエリキャッシュも設定してみたのですが、効果なさそうだったので query_cache_type = 0 でオフにしました

  • さらに適当に my.cnf 変えてたら MySQL が立ち上がらなくなる
  • 新人君が運営の方に連絡とってベンチマークできないことを伝えてくれたおかげで解決する → max_allowed_packet = 300M の設定が消えてたのが原因でした。
  • その新人君(めっちゃ良い子)に 「Web アプリは任せた」と無茶ぶりする
  • 別チームのピシさんがハッピーターンを買ってきてくれて絆を感じる

 

14:30 〜

  • スコアがほとんど上がらなくて焦ってくる。このとき 3000 くらい
  • memcached を入れようとするが未遂に終わる → なんか session 自体は使えてるみたいなので最悪ファイルキャッシュでもいいかと思って放置

 

15:00 〜

  • チューニング性に迷いが出てきて Web アプリ側のクエリチューニング、DB設計変更を行う → 確かにスコアが上がったのですが 200 くらいでした。
  • ここで unicorn (foreman) の立ち上げ方でちょいはまる
  • ついでに unicorn の worker_processes をチューニング 100 にしたり、5とかにしたり試してみるがたいした効果はなし。とりあえず 15 にしました。

 

17:00 〜

本当は explain して use index を確認するべきですが時間がないので最大限使われそうな index をスキーマに追加 # schema.sql CREATE TABLE IF NOT EXISTS login_log ( id bigint NOT NULL AUTO_INCREMENT PRIMARY KEY, created_at datetime NOT NULL, user_id int, login varchar(255) NOT NULL, ip varchar(255) NOT NULL, succeeded tinyint NOT NULL, Index ip(ip), Index succeeded(succeeded), Index user_id(user_id), Index user_idsucceeded(user_id, succeeded), Index ipsucceeded(ip, succeeded), Index login(login) ) DEFAULT CHARSET=utf8;

  最終的にスコアは 16000 まで上がりました。

 

感想 あまりスコアはふるわなかったですし、やろうとしたことができなかったり悔しい結果でしたが、 みんなで休日に会社に集まって色々必死に集中して考えての作業はめっちゃ楽しかったです!! また別部署のメンバーとの交流にもなったので社内メンバーで募ってやれてよかったと思っています。   最後に ありがとう ISUCON!次回も参加させていただきます! 次回は予習していこう。。。