こんにちは宮村(みやむー) @miyamura.koyo です。 2021年9月に福岡のクラウド経費・債務支払開発部にサーバエンジニアとしてジョインして開発を行なっております!
今回は福岡拠点のクラウド経費 ・ 債務支払 開発チームが今年の ISUCON12 に出場した話を書いてみたいと思います。 ※ ISUCON (= Iikanjini Speed Up Contest)とは毎年開催されているWebアプリケーションの高速化チューニングコンテストです。
なお福岡拠点では、様々な取り組みがメンバー起点で行われており、とても働きやすい環境です。 その雰囲気の一端を感じてもらえればと思います。
参加の経緯
私は前職、面白法人カヤックという会社で働いていました。 ISUCON は前回大会の優勝者が出題を行うという文化があるのですが、ISUCON11ではカヤックチームが優勝したので、ISUCON12の出題はカヤックが行いました。 というわけで「前職の出題だし是非参加したい!」と思い、参加を決めました。
ISUCON は最大3人参加できるので、仲間を集めたい!と思い社内で募ってみました。 すると大先輩である野田さんと江口さんが誘いに乗ってくれて、3人でやるぞ!となったのが参加経緯です。 気軽に誘える環境いいなぁと再実感した出来事でした。
1ヶ月前 ~ 当日まで
まず Slack の専用チャンネルを作りました! そしてちょうど発売された 達人が教えるWebパフォーマンスチューニング 〜ISUCONから学ぶ高速化の実践 をみんなで読みました。 個人的には、著者が実際に練習問題をどういう思考過程で解いたかが書かれているところが一番勉強になりました:pray:
また、週末に数回勉強会を実施して過去問を解いて知見を深めました。 ISUCON運営の方からスポンサークーポンいただいて、過去問環境を整えて解いたり、以下のようなカンペ作ったりしていました。
ちなみに参加言語は普段使ってるし Ruby にしよう!と決めました。 なお ISUCON 未経験メンバーもいたので、予選突破目指すよりは、普段の業務でやらないことを体験して学んだり、ISUCON を楽しむことをメインにやっていました。
当日
当日はオフィスに集合して、ワイワイやっていました。
私は Makefile
を準備して以下のような運用をしていました。
(※ alp
と pt-query-digest
を使う ISUCON 定番構成です。)
make init
でディレクトリの準備make install-tools
でツールのインストール- ベンチマーク実行前に
make prepare-bench
ベンチ実行後にmake after-bench
を実行
# isucon ユーザーじゃなければ適宜変更する | |
export ISUCON_USER=isucon | |
export ISUCON_GROUP=isucon | |
export NGINX_USER=root | |
export NGINX_GROUP=root | |
export MYSQL_USER=root | |
export MYSQL_GROUP=root | |
# 初回に実行する | |
# ディレクトリ作成・nginx / mysql の設定ファイルを取得 | |
init: init-dir get-nginxconf get-mysqlconf | |
init-dir: | |
mkdir -p conf/nginx/sites-enabled | |
mkdir -p conf/nginx/sites-available | |
mkdir -p log | |
# 各ツールのインストール | |
install-tools: install-pt-query-digest install-alp install-command | |
install-alp: | |
wget https://github.com/tkuchiki/alp/releases/download/v1.0.9/alp_linux_amd64.zip | |
sudo apt-get install -y unzip | |
unzip alp_linux_amd64.zip | |
sudo install ./alp /usr/local/bin | |
rm alp | |
rm alp_linux_amd64.zip | |
install-pt-query-digest: | |
sudo apt-get update | |
sudo apt-get install -y percona-toolkit | |
install-command: | |
sudo apt-get install -y rsync | |
# 必要なら実行 | |
# デフォルト 11211 ポート | |
# ※ Ruby の場合は Gemfile に gem 'dalli' を追加するなどクライアントのダウンロード別途必要 | |
install-memcached: | |
sudo apt install memcached | |
# 本番のサーバー構成に合わせて適宜書き換える | |
set-nginxconf: | |
sudo rsync -rv conf/nginx/nginx.conf /etc/nginx/nginx.conf | |
sudo rsync -rv conf/nginx/sites-enabled/* /etc/nginx/sites-enabled | |
sudo rsync -rv conf/nginx/sites-available/* /etc/nginx/sites-available | |
sudo chown ${NGINX_USER}:${NGINX_GROUP} /etc/nginx/nginx.conf | |
sudo chown -R ${NGINX_USER}:${NGINX_GROUP} /etc/nginx/sites-enabled | |
sudo chown -R ${NGINX_USER}:${NGINX_GROUP} /etc/nginx/sites-available | |
set-mysqlconf: | |
sudo rsync -rv conf/mysqld.cnf /etc/mysql/mysql.conf.d | |
sudo chown ${MYSQL_USER}:${MYSQL_GROUP} /etc/mysql/mysql.conf.d/mysqld.cnf | |
# 本番のサーバー構成に合わせて適宜書き換える | |
get-nginxconf: | |
sudo rsync -rv /etc/nginx/nginx.conf conf/nginx | |
sudo rsync -rv /etc/nginx/sites-enabled/* conf/nginx/sites-enabled | |
sudo rsync -rv /etc/nginx/sites-available/* conf/nginx/sites-available | |
sudo chown ${ISUCON_USER}:${ISUCON_GROUP} conf/nginx/nginx.conf | |
sudo chown -R ${ISUCON_USER}:${ISUCON_GROUP} conf/nginx/sites-enabled | |
sudo chown -R ${ISUCON_USER}:${ISUCON_GROUP} conf/nginx/sites-available | |
get-mysqlconf: | |
sudo rsync -rv /etc/mysql/mysql.conf.d/mysqld.cnf conf/ | |
sudo chown ${ISUCON_USER}:${ISUCON_GROUP} conf/mysqld.cnf | |
# 現状のログをリポジトリ配下にコピー | |
copylog: | |
sudo cat /var/log/nginx/access.log > /home/${ISUCON_USER}/log/nginx-access.log | |
sudo cat /var/log/mysql/slow.log > /home/${ISUCON_USER}/log/slow.log | |
# pt-query-digest と alp でログを解析 | |
# NOTE: alp の -m オプションの引数は適宜変更する | |
analyze: | |
pt-query-digest cat /home/${ISUCON_USER}/log/slow.log > /home/${ISUCON_USER}/log/ptqd-result | |
cat /home/${ISUCON_USER}/log/nginx-access.log | alp ltsv -m "/api/player/competition/.*/ranking,/api/organizer/competition/.*/score,/api/organizer/competition/.*/finish,/api/player/player/.*,/api/organizer/player/.*/disqualified" --sort=sum -r > /home/${ISUCON_USER}/log/alp-result | |
# 現状のログとその解析結果を git 配下にコピー | |
save-log: | |
if [ -f "/home/${ISUCON_USER}/log/nginx-access.log" ]; then mv /home/${ISUCON_USER}/log/nginx-access.log /home/${ISUCON_USER}/log/nginx-access-`date "+%Y%m%d_%H%M%S"`.log ; fi | |
if [ -f "/home/${ISUCON_USER}/log/slow.log" ]; then mv /home/${ISUCON_USER}/log/slow.log /home/${ISUCON_USER}/log/slow-`date "+%Y%m%d_%H%M%S"`.log ; fi | |
if [ -f "/home/${ISUCON_USER}/log/ptqd-result" ]; then mv /home/${ISUCON_USER}/log/ptqd-result /home/${ISUCON_USER}/log/ptqd-result-`date "+%Y%m%d_%H%M%S"` ; fi | |
if [ -f "/home/${ISUCON_USER}/log/alp-result" ]; then mv /home/${ISUCON_USER}/log/alp-result /home/${ISUCON_USER}/log/alp-result-`date "+%Y%m%d_%H%M%S"` ; fi | |
# ベンチ回す前に、以前の nginx / mysql のログを削除 | |
cleanlog: | |
sudo sh -c "echo > /var/log/mysql/slow.log" | |
sudo sh -c "echo > /var/log/nginx/access.log" | |
# 各デーモンの再起動 | |
# NOTE: isucondition.ruby.service は適宜変更する | |
# memcached.service 入れる場合は以下も追加 | |
# sudo systemctl restart memcached.service | |
restart: | |
sudo systemctl restart nginx | |
sudo systemctl restart mysql | |
sudo systemctl restart isucondition.ruby.service | |
# ベンチ回す前の準備 | |
prepare-bench: set-nginxconf set-mysqlconf restart cleanlog save-log | |
# ベンチ回した後のログ解析 | |
after-bench: copylog analyze | |
# 簡易的に git に push | |
push: | |
git add . | |
git commit -m "push from Makefile" | |
git push origin main |
概ね以下のような流れでやっていました。
- マニュアルを読んでアプリケーションを理解する
- 事前準備した Makefile を適用して、検証サイクルが回せるようにする
- インデックスを貼ったりアプリケーションロジックの変更を行う
- 最後にログ消したりお片付け
なお今回の予選は MySQL と SQLite の混在システムで、MySQL に寄せるか悩みましたが、さすがに時間内に終わらないかということで SQLite のまま頑張りました。
個人的には uuid 発行部分を SecureRandom.uuid
にできたのが Ruby らしい解法ができたなと思っています。
ちなみに反省点としては、自作の make コマンド実行時に slow.log
がなかったので touch コマンドで適当に空ファイル作ったところ、パーミッションがないせいでスロークエリが出ないことにだいぶハマったことですね笑
正常終了するのにログが出なくてだいぶハマりました。
結果
約199位/698チーム (約上位28.5%)でした。予選突破は遠いですが、Ruby で思ったより点数も伸ばせたので個人的には及第点! https://isucon.net/archives/56838276.html
ただ予選の講評を見ると、ここはもっとやれたなー!と思う部分もあって、次こそは!という気持ちになりました。 来年もまた福岡チームで出たいですね!
やってみて
私自身も含めた参加メンバーの感想です。
みやむー(筆者)
- 仕事しながら準備して参加するの大変かなぁと思っていたのですが、先輩が快諾してくれて、色々と知見を教えてもらったり、一緒にワイワイできて楽しかったです。
- ISUCON は2年前も参加していたのですが、その時に比べると格段にできることが増えていたので、自分の成長を感じることができました。
- 一方で、まだまだだなぁと思うことも多かったので、これからも精進していきたいなと思います。
- 特にファイルロックをトランザクションに変えるところは、あまり効果ないかなと思い放置していたところだったのでとりあえず試してみるべきだったなと思いました。すぐできるところでもあったし。
野田さん
- ActiveRecord じゃなくて素の MySQL アダプタで N+1 を解決しようとしたり、SQLite でも使える Windows 関数でクエリを効率化しようとしたりしたが、あまり改善に結びつかなかった。
- よくある改善方法を怪しい箇所にとりあえず適用するのではなく、きちんと計測するということの大切さを実感した。
- SQLite 意外といいじゃんと思うきっかけになった。
- ベンチマークを各メンバーで同一の環境で同期的に実行しないといけないのが大変だった。
- 予期せずファイルのパーミッションや Nginx のよくわからないエラーでハマるのが辛い。アプリが当たり前に動かないもどかしさを感じた。
江口さん
- 「計測しないと、改善したかどうかわからない」という当たり前の事実の重要さを肌で感じた。
- ISUCON の考え方が、その後サービスの実行時間改善に取り組むときに役立ちました。
※また、江口さんはISUCON参加後に以下のような日記を書いているのでこちらもぜひ ISUCON のリアルな感情の動きが書かれています・・・! https://github.com/eggc/memo/blob/main/diary/20220723_isucon.org
まとめ
福岡開発拠点メンバーで ISUCON12 に参加して、いろいろな学びを得ました。 こんな感じで 「こういうことやりたいなー」と思った時に気軽に相談できる仲間がいる職場 です。 FinTech 業界ってお堅いんじゃないの?と思う方もいるかもしれませんが、そんなことはありません。 この記事で紹介したように、マネーフォワードは仕事は真剣にしつつも、柔軟に楽しく働ける会社です! 一緒に働きたい方ぜひお待ちしております!
マネーフォワード福岡拠点では、エンジニアを募集しています! 自分の興味を面白がって、乗っかってくれる職場で働きたい!そんな方はぜひぜひお話聞かせてください。 ご応募お待ちしています。
https://hrmos.co/pages/moneyforward/jobs?category=1666323298559537153
福岡開発拠点のサイトもあるのでぜひみてね!
https://fukuoka.moneyforward.com/
マネーフォワードでは、エンジニアを募集しています。 ご応募お待ちしています。
【会社情報】 ■Wantedly ■株式会社マネーフォワード ■福岡開発拠点 ■関西開発拠点(大阪/京都)
【SNS】 ■マネーフォワード公式note ■Twitter - 【公式】マネーフォワード ■Twitter - Money Forward Developers ■connpass - マネーフォワード ■YouTube - Money Forward Developers