Taku’s Teckブログ

Teckはわざとです。

isucon練習会めも

友人とisuconの練習会を実施しましたが、全然できなかったので次に活かすためのメモ

インフラを担当したけど、ツールのインストトールやMySQLの操作コマンドがすぐに出てこず時間をかけてしまったので、当日の流れを自分がやったこと以外もまとめておく

isuconとは

isucon.net

やったこと

☆が今回自分でやったこと

事前準備

  • 環境構築
    • isucon9用の環境をAWSに準備
    • isucon5予定が、データインポートに時間がかかる?らしく間に合わなかったため変更
      • 一度最大サイズのDBを利用してインポートするようなTipsが必要らしい?
    • セキュリティグループの穴あけ
      • 443, 80, 22, 8000, 5555, 7000, 3306, 19999(Netdata用)
  • チーム分担
  • 役割極め
    • アプリ
    • ☆ インフラ
  • サーバーへのSSHを渡しておく

練習中

  • ☆ レギュレーション確認 isucon.net
  • ☆ マニュアル確認 github.com

  • githubリポジトリ作成

    • Slack連携
    • サーバーにgitの設定
    • メンバーにリポジトリのアクセス・編集権限を渡す
    • ☆ 調べたこと、わかったことは一つのissueにどんどん書いていく
  • Makefile作成

    • ビルドやベンチなど、何度も実行するものをまとめておく
bench:
    ssh -l ubuntu [ベンチサーバーのIP] cd /home/isucon/isucari \&\& /home/isucon/isucari/bin/benchmarker -target-url http://18.183.105.62:80 -shipment-url http://13.231.82.53:7000 -payment-url http://13.231.82.53:5555

/home/isucon/isucari配下に必要なログファイルがあるためそこに移動して実行しないといけないが、sshコマンドでディレクトリ移動した後のコマンド実行は \&\&エスケープする必要があり(ないと移動して実行されない)

  • ミドルウェアのバージョン確認
    • MySQL
      • clientでなくServer側が見たいため、ログインして見る
    • ☆ Nginx
    • Golang
    • ポートを使っているサービスの確認コマンド
      • $ sudo lsof -i:80

MySQL

Server

mysql> select version();
+-------------------------+
| version()               |
+-------------------------+
| 5.7.33-0ubuntu0.18.04.1 |
+-------------------------+
1 row in set (0.00 sec)
Client

ubuntu@ip-172-31-39-97:~$ mysql --version
mysql  Ver 14.14 Distrib 5.7.33, for Linux (x86_64) using  EditLine wrapper
Nginx

$ nginx -V
nginx version: nginx/1.14.0 (Ubuntu)
Go

$ cat go/go.mod
module github.com/isucon/isucon9-qualify/webapp/go

go 1.12

require (
    github.com/go-sql-driver/mysql v1.4.1
    github.com/gorilla/sessions v1.2.0
    github.com/jmoiron/sqlx v1.2.0
    goji.io v2.0.2+incompatible
    golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4
)
  • ☆リソースモニタリングツールを入れる

  • ベンチマーク

    • Nginxでログを取るため、80ポートを利用するように変更
    • kataribeでログ集計 github.com
  • 作戦を立てる

    • kataribeを見て、実行時間が大きいものから着手
    • (1つ大きいのを変えると他の順番が大きく変わることがあるので、2-3つめを並行してやるのは効果が薄かったりするらしい)
  • N+1クエリ改善

    • 最重要
    • 1箇所のみならず、複数箇所あることも
  • ユーザの一括取得とカテゴリのオンメモリ化

  • スロークエリ集計

    • MySQLのスロークエリ出力設定
      • 最初は0以上にして全て出してみる
    • pt-query-digestで集計 www.percona.com
  • インデックス作成

    • スロークエリとなっており改善必要なものから
    • EXPLAINを見て
  • ☆DBを切り出す

    • CPU使用率を見るとMySQLが1番大きいため別サーバーに
    • ☆ 不要なサービス停止(アプリ用サーバーのMySQL、DB用サーバーのService)
$ sudo systemctl status isucari.golang.service | grep Active
$ sudo systemctl stop isucari.golang.service
$ sudo systemctl status isucari.golang.service | grep Active
$ sudo systemctl status payment.service | grep Active
$ sudo systemctl status shipment.service | grep Active
$ sudo systemctl status nginx.service | grep Active
$ sudo systemctl stop nginx.service
  • MySQLへ外部ホストからのアクセス許可設定
  • ☆ 設定確認
    • sudo mysql -e "SHOW VARIABLES LIKE 'bind%';"

  • mysqld.cnfの修正
  • ☆ ユーザー毎の許可アクセス元の確認
    • sudo mysql -e "SELECT user, host FROM mysql.user;"

    • %の場合全てOKなので変更しなくても良いが、ホストを絞っても良い
  • ☆ アプリケーションの向き先変更

    • ☆ アプリケーションでDBの設定をしている箇所を修正
    • 今回env.shMYSQL_HOST=XXX.XXX.XXX.XXXを変える
  • DBコネクションプールの利用

    • connect: connection refusedが出ていたためコネクションを増やそうとする
    • 最大接続数は151だったので一旦そのままで良いという判断
  • ☆ DBチューニング

    • my.cnfの修正
      • innodb buffer pool size = 512M
      • ☆ query cache有効に
        • mysql> SHOW VARIABLES LIKE '%query_cache%';

      • ※直接パラメータをSETする場合は、rootなど権限があるユーザーでないとできない
        • 再起動すると元に戻るのでmy.cnfを修正した方が良い
      • OSのrootユーザーであれば、mysqlのrootにPWなしでログイン可能
        • $ sudo mysql -u root isucari

[mysqld]
innodb_buffer_pool_size=512MB

query_cache_type=1

→この辺りはあまり効果が出ず

練習後

  • 振り返り会
    • チーム毎の3回実行してスコアを見る
    • 各チーム何をやったか共有
      • 今回キャンペーンを有効化してのベンチができなかった
        • N+1の改善が足りてなかった
          • N+1の改善はisuconでよくあるパターンなので、スニペットを用意して簡単に修正できるようにしておくと良いとのこと
        • /loginボトルネックになるので、処理を別サーバーに切り出す
          • Nginxの設定で、GET /loginの時だけ別サーバーへリクエストを投げるようにする
            • TODO) Nginxの設定はわからんので調べる
        • ベンチサーバーのULIMITの変更が必要だった
          • これは元のAMIの不備か?(N+1の改善後、ログをよく読むとわかるらしい)
$ echo "* hard nofile 64000" >> /etc/security/limits.conf
$ echo "* soft nofile 64000" >> /etc/security/limits.conf

次回に向けて

今回のisucon9はこちらの本でも取り上げられていたので再度一人でやっておく(本当は事前に一人でやっておくつもりができなかったので次回までは必ず・・。今回もチラチラ見ながらやってた)

Webサービスチューニングコンテスト ISUCONのススメ (技術の泉シリーズ(NextPublishing))

やることが多いため、繰り返しやりコマンド等に慣れておくのが大切(本業でのトラブル対応の役にも立ちそう)