SEEDS Creator's Blog

ISUCON 9 予選に京都スイーツ(b・ω・)bで参加して本戦出場できました!(15,490イスコイン / PHP / 総合11位?)

クラウド事業部の原口です。

毎年恒例のISUCONに参加してまいりました。使用言語はPHPです 。

isucon.net

今年は同僚のkawakattunとkuuと僕(cs_sonar)の3人で参加してまいりました!
予選の参加者合計 1561名だそうで、、、すごく大きいイベントになりましたね。
僕は9回目。kawakattunは3回目、kuuは初めてのisuconです。
毎年「今年こそは!」と心に闘志を燃やして参加し、いつも予選敗退するのですが今年はなんと本戦出場できました!

やったーーー嬉しい!

まがいなりにもCTOなので毎年ISUCON出るたびに社内人権が脅かされるのですが、、、今年は人権があってよかったです。
最終的な構成は WEB+Proxy / DB の2台構成でした

前日 && 前々日

業務終わりにISUCON4で練習。ISUCON4を選んだのはAWSにAMIがあってベンチ内包型だったからです。
役割分担などは正式に決めてないのですが、流れで以下のようになっていました

僕 -> インフラ全般
kawakattsun -> アプリ全般
kuu -> 実装と仕様チェック、レギュレーションチェックの情強

当日の流れ

設営をさくっと終わらせて開始!10分遅れたおかげで朝ごはんをたべきれました。
とりあえずアリババクラウドで共有されたイメージで5台ほど立ち上げ。
それぞれのメンバーで触れるようにしました

ベンチを流しても同じ点数しか出ないと思ったら、トランザクション成功数でなるほどな、と思った記憶があります。
ひとまずDB側のitemsにインデックス貼りを実施。

ALTER TABLE items
ADD INDEX seller_id_idx (`seller_id`), 
ADD INDEX status_idx (`status`),
ADD INDEX buyer_id_idx (`buyer_id`);

mysqlの最低のチューニング

innodb_flush_log_at_trx_commit = 0
innodb_buffer_pool_size=1000M
innodb_flush_method = O_DIRECT

上限をあげておく

systemctl

net.ipv4.ip_local_port_range = 10240 65000
net.core.rmem_max=16777216
net.core.wmem_max=16777216
net.ipv4.tcp_rmem=4096 87380 16777216
net.ipv4.tcp_wmem=4096 65536 16777216
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_fin_timeout = 3
net.core.netdev_max_backlog = 30000
net.ipv4.tcp_no_metrics_save=1
net.core.somaxconn = 262144
net.ipv4.tcp_syncookies = 0
net.ipv4.tcp_max_orphans = 262144
net.ipv4.tcp_max_syn_backlog = 262144
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_syn_retries = 2
net.ipv4.tcp_max_tw_buckets = 56384

limits.confは既に65535に設定されていました。

これらを実行してもスコアは全然変わらなく、、、だけど明らかにmysqlの負荷などは減っていいたので
一旦還元率を1にしてみたら6410イスコインになってこの時のTOPに!

引き続いてアプリ側の改修を実施。
ここはkawakattunとkuuがやってくれました
このあたりですでに13:00くらい。

・categoryをすべて配列でプログラム側で持つ
・statusのSQLのINを消す
・セッションにユーザーデータを入れる
・transaction で外部api叩かなくする

などの改修を行ったのですが、特にスコアに変化なく…
同時に行っていたnginxの改修を反映したところスコアが10,000まで上昇。
インフラで止まってた部分を修正する事でアプリの修正も活きた感じがします

nginx

・静的ファイルをnginxで返すように修正
・Cache-Controleでmax-ageとかpublicとかつける
・gzip圧縮するよう設定
・worker_connections 100000
・worker_processes 8
・アクセスログ破棄

しかし、ここからが低迷。
発生する503のエラーのログがどこに吐かれるのかわからずphpのログ出し設定をいろいろいじいじしてたのが結局時間がかかってしまいました。
php実装にはmonologが入ってる事に気づいたのが後半で…
エラー内容がログなくてもかろうじて気づけるSQLのシンタックスエラーじゃなければ死んでたかもしれないです。
またこの時にアクセスログを切ってしまったのは早すぎた。意外とtail -fしてると気づける事ってあるよなーと後から思いました。
/buyが詰まってたのは多分気づけてたと思います。

この間、ボトルネックは完全にphp側に傾いていたので、DBサーバーを分ける事を決意。
分けた時に以下の点にはまり1時間くらいはかかってしまったかもしれないです

・プログラム内のmysqlサーバーのIP指定
・env.shでのmysqlサーバーの指定 ←はまる
・アリババクラウドのセキュリティグループ修正 ←はまる
・my.cnfでbind 127.0.0.1 になっているのを0.0.0.0に修正 ←はまる

普段RDSとかELBで楽してるツケが来ている感じがしました。
これでメモリに余裕ができたのでphp-fpmの設定を変更

php-fpm

以下を60くらいに設定
pm dynamic
pm.max_children
pm.start_servers
pm.min_spare_servers
pm.max_spare_servers

・読まれてるxdebugを切る
・OPCacheを有効化

ここで13,000くらいでした。
また、redisを入れようとしたのですが、うまく立ち上がらず諦め。。。(IPv6系の問題だったそうです)
php-fpm側のネックだったので、残り1台を使って処理を2台に分けようとしましたが、上記のredisが入らないのでセッションどう共有するかという問題と 画像をどう共有するかという問題があって時間的に不可能と思い、断念しました。
/loginのURLに絞る事を考えれたら良かったのになー、と感想部屋見て悔しかったです。

この間にアプリチームが結構長い間、行っていた改修がついに反映されます

・/users/transactions , /new_itemsのn+1をsqlのjoinで回避
・新着一覧から自分のitemとsold outをsqlで除外

自分のitemとsold outをsqlで除外する改修は、最初はカテゴリーのitemsのほうも一緒の対応してたらベンチでitemがありませんってなってしまい。
この改修はすごく時間がかかりました。
Kuuがベンチのエラーをきっちり見てくれて、エラーはカテゴリーの方だけだ、と気付き、新着一覧からのみ除外する事でベンチが通りました。
これが、15790で今回の最高スコア。

最後の17:30からはもう作業は停止。
再起動試験とベンチガチャ回しに勤しみました。
結果は残り5分くらいで 15,490 が出て作業を完全にやめました!

振り返り

f:id:cs_sonar:20190909231445p:plain

考えてみたら、サーバーのチューニング以外はほとんど何もできていません。
感想部屋でのお話を見て「なるほどー」という感じで… /buy の対策などは何もできていなかったりしていました。
本戦までにはプロファイラーをきちんと使い、ボトルネックをきちんと計測できるようにしたいと思いました。
ただ、今回のISUCONがプログラムが膨大だったので、まともに計測してたら何もできずに終わってたかもしれないな、とも思いますので…結果オーライです

弊社のエースエンジニアのkawakattunはもちろんの大活躍でしたが、
今回初参加のkuuがレギュレーションにしっかり目を通し、それを踏まえた案をだしてくれるのはとてもよかったです
僕とkawakattunは多分、ゲームの説明書読まずに始めるタイプなので…w
そういう意味でのチームとして相性がよく、仲間に恵まれた、というのを実感しています。

今まで予選を突破した事がなかったので嬉しいです。
これまでのISCUONを振り返ると惜しい回も結構多かったなーとしみじみ…


ISUCON1 京都スイーツ : fail

ISUCON2 京都スイーツ : (記録がなかったので不明)
#isucon2にていいかんじにスピードアップできなかった話 - SEEDS Creator's Blog

ISUCON3 うさぎ工房 : 5300 予選敗退
isucon3 予選で敗退しました(うさぎ工房) - SEEDS Creator's Blog

ISUCON4 京都スイーツ : 37513 予選敗退&失格
#isucon 4 予選に参加しました(スコア 37513) - SEEDS Creator's Blog

ISUCON5 京都スイーツnext : 13094 予選敗退
ISUCON5に「京都スイーツnext」で参加してきました - SEEDS Creator's Blog

ISUCON6 京都スイーツ : 17000くらい 予選敗退

ISUCON7 ガトリンガー葉の仲間たち : 72,285 55位くらい 予選敗退
ISUCON7に「ガトリンガー葉の仲間たち」で参加して今年も惨敗しました - SEEDS Creator's Blog

ISUCON8 ドラえもんズ : 30,699 27位 予選敗退

ISUCON9 京都スイーツ : 15,490 11位くらい 本戦出場!!


毎度の事ながら、本当に楽しかったです。
運営の皆様、本当にありがとうございました!
そして、今年は本戦でも宜しくお願い致します!