こんにちは。
VOYAGE GROUPのシステム本部でインフラエンジニアとして働いている @s_tajima です。
先週末、
LINE株式会社さん主催のチューニングイベントであるISUCON4の予選に参加しました。
(失格にならなければ)4位で予選通過できるようです。

今回は、事前準備〜スコア提出までにやった事とその所感をお話しようと思います。

■ 前日まで

  • 同期の@misty320(業務ではアドテク事業のアプリ担当)と
    @at_grandpa(業務ではアドテクの事業の数値解析周り担当)を誘って参加することに。
    3人とも初参加。
  • 平日の業務終了後、3,4度集まって過去問をやってみて予習。
    3人で並行作業するための戦略もここで打ち合わせ。
  • 当日はおおまかにnginx + ruby構成にしようということを取り決め。
  • 細かい設定変更やアプリの改修はGithubのprivateリポジトリを使って共有することを取り決め。
  • 大きめの修正をした際にはAMIを作成。
  • メンバーのAWSアカウントに対してLaunchPermissionを設定してそこを基準にしてチューニングを再開。
  • 当日役に立ちそうなツール類の準備。★0
  • 前日に会社の会議室にモニター(各自の作業用)やプロジェクター(idobataやTwitter表示用)を用意。

■ 当日
9時
  • おにぎりを食べて会社に集合。開始前にお昼の寿司を頼もうと思ったが出前が営業時間外で断念。
  • 予選当日マニュアルが発表。テーマは銀行?らしい。
  • マニュアルの読み合わせ。(スコアリングの大まかな仕様、ルール等確認)
10時
  • 予選開始。それぞれ1台ずつ起動し状況を確認。
  • 当初の予定だとhttpd + perlの構成を、nginx + rubyにして計測、
    としようと思ったところだがすでにそうなっていた。
  • とりあえず初期状態のまま計測。スコアは1000程度。
  • 周りのベンチ結果を見ると軒並み1500程度はでているようなので、
    今回rubyはハズレなのでは..という空気に。
  • ここでPHPがhttpd + mod_phpではなく最初からnginx + php-fpmになっていることに気がつく。
  • ためしにphpで計測してみると、1500程度。
    (この時点ではスコアの規模感がわからなかったので大きな差に感じた。)
  • 今は3人ともあまり使っていないものの、
    比較的馴染みはあるのでphpに乗り換えることに。
11時
  • 計測スクリプト実行時のアクセスログや, slow query logを確認。
  • @misty320と@at_grandpaにアプリ周りの確認をしてもらう。
  • その間に、最初のAMIを作成。
    (事前に用意したツール類の展開。アプリケーションをphpに。MySQLの大まかな設定変更。)
  • AMIを共有(1回目)。
  • 引き続き@misty320と@at_grandpaにアプリやクエリの確認をお願い。
  • その裏でMySQLをOracle提供の5.6.20に入れ替えてみたが、
    スコアが下がった(1000程度)のでやめた。
12時
  • ブラウザでの表示が崩れていることに気がつく。
    画像の表示やコンテンツの取得に問題はないようだがなぜかcssだけがあたらない。
  • cssのContent-Typeがtext/plainになっていることに気がつく。
    nginxにinclude mime.types;を設定して対応。運営に報告。
  • @misty320が作ったindexを貼るとスコアが3000程に。★1
  • 計測のworkloadを増やしていくと順調にスコアが伸びていくので
    頭打ちになるところまで増やしてみることに。
  • 同時にphp-fpmをHHVMで置き換えるために準備開始。
    RPM落ちてるだろうと思ってたがなかった。仕方なく自分でビルド開始。
  • お昼ごはんにお寿司を注文。
13時
  • nginx, php-fpm, MySQL, OS周りの細かいチューニングをしつつ
    workloadをスコアが頭打ちになるまで上げていく。★2
  • @misty320が作った2つ目のindexも設定。★3
  • この時点でworkloadは30, スコアは35000程度。
     (多分計測の1分タイムアウトは正常に動いてた)
14時
  • ここから1時間程度は思うようにスコアが伸びず焦る。
15時
  • HHVMのビルドが完了。
    自動起動周りなどは気にせずとりあえず起動してベンチ。
  • この時点でのAMIを作成して3人で共有。
  • スループットはかなり上がっていそうだが、特定のPATHでエラーが多発。
    @misty320と@at_grantpaに調査を依頼。★4
  • 解消できることを信じて調査してもらっている間にHHVMのfast-cgiの設定や
    supervisordでの起動を設定していく。
16時
  • ★4の問題は解消。
    workloadを上げるとまたスコアが伸びるようになったので、頭打ちになるところを探していく。
  • スコアはかなり高くなるものの、計測のたびにエラーがでている状態。
    原因を調査し解消していく。★5
  • 事前にチームで計画していた予定に従い、
    16時30分時点で一旦手を止めて現状共有と終盤の方針について相談
    (終盤の混乱での崩壊を避けたかった)。
  • 結論は既にそれなりのスコアが出ているので、スコア向上は小さな調整のみに抑えて安定化、
    ルールの範疇に収まっているかのチェックを重視することに決定。
17時
  • この時点でworkloadは300, スコアは65000 ~ 75000くらいが安定して出せるように。
  • 計測が3分程度になっている気がしたが余り気にしていなかった。
    まさかバグだとは誰も認識していなかった...
  • 残り時間も少なくなってきたので、
    一旦スコアの提出は終了してAMIの調整に入ることに。
  • AMI起動時、自動起動でエラーになったり、運営が計測した時に不具合が。
    にみたいなことがないように調整。
  • AMIを作って3人で共有 -> 細かい不具合を発見 -> 修正したAMIを作成
    というのを何度も繰り返した。
18時
  • 予選終了。スコアの結果4位に入っていた。

■ 具体的な対応
★0
  • 以下のようなスクリプトを用意していた。 
  • 必要な設定ファイルを指定のディレクトリに集めてきて、元あった場所にシンボリックリンクを貼るスクリプト(git管理化をしやすくするため)
  • 計測の前後で必要そうな作業をするためのスクリプト
     計測前: OSのキャッシュクリア, 各種ログのトランケート(地味に重要), 各ミドルウェアの再起動 
     計測後: 各種ログの収集(git管理下のディレクトリに),設定ファイルのコミット(スコアをコミットメッセージにして)
  • AMIを作成するためのコマンド(awsコマンドを打つだけだけど、instance_idとかを調べてオプション渡すのが面倒だったので。) 

★1 
  • 以下のindexを設定。
CREATE INDEX `login_user_idx` ON `login_log` (`user_id`);

★2
  • nginxはworker数や, workerのコネクション数の調整。
  • php-fpmとの接続をunixドメインソケットに。
  • php-fpmはpm*serversあたりのパラメータを調整。
  • MySQLはinnodb_*みたいな定番のパラメータを調整。
  • 具体的な設定ファイルは余力があれば後で公開します。

★3
  • 以下のindexを設定。
 CREATE INDEX `login_ip_idx` ON `login_log` (`ip`);
 
★4
  •  HHVMだとindex.html.phpのflash_now()の処理がうまく動かなかった模様。
  •  値をcookieに持たせるように修正して対処。

★5
  • file descriptor周りの調整がメイン。
  • nginxのfile descriptorを設定したあと、
    親workerのlimitsを見て設定反映されないなあとかちょっとだけハマった。あほ。
  • 計測スクリプトのfile descriptorにも気を配らないといけないのも
    ちょっと気がつくのに時間がかかった。

■ 感想
  • 事前に3人で打ち合わせを数回してから望めたのはよかった。
    同期なのでコミュニケーションもとりやすかった。
  • 当日役に立ちそうなスクリプトを作っておいたのもよかった。
  • HHVM、はじめてビルドしたし触ったのもはじめてだったけど動いてくれてよかった。
    (正直fast-cgiもそれほど詳しくはない)
  • 節目節目でAMIを作って共有して作業できたのはとてもよかった。
    不具合があった時には @at_grandpa が最新のAMIを立ちあげて検証のサポートを
    その間に @misty320 が1つ前のAMIでチューニングをという役割分担ができた。  
  • @misty320のブログ
    (
    http://misty320.hatenadiary.jp/entry/2014/09/29/010956)
    にもある通りとても楽しいイベントでした。
  • (もし失格にならなければ)本戦頑張ります!
■ 余談
  • たしかに少なからずうちのチームは計測スクリプトのbugを踏んでいた模様。
  • 提出時そのままの状態でv2を使うとスコア35000くらいだった。
  • その後小細工をして計測したら30分くらいの作業で57000くらいには伸びたので歯ブラシでも十分に戦えそうだということじゃないかなあと。