Skip to content

Pixiv 社内 ISUCON 2016の内容に、Python実装を追加し、さらにPython用のDockerfileやログ取得・解析用のスクリプトを追加したものです。

License

Notifications You must be signed in to change notification settings

eycjur/private-isu

 
 

Repository files navigation

private-isu

Pixiv 社内 ISUCON 2016の内容に、Python実装を追加し、さらにPython用のDockerfileやログ取得・解析用のスクリプトを追加したものです。

なお、ログ解析用スクリプトは達人が教えるWebパフォーマンスチューニング〜ISUCONから学ぶ高速化の実践を参考にしています。

ディレクトリ構成

├── benchmarker         # ベンチマーカーのソースコード
├── img                 # README.mdに貼り付ける画像
└── webapp              # 各言語の参考実装
    ├── etc             # nginx, mysqlの設定ファイル
    ├── golang
    ├── logs            # ログ解析用のDockerfile,ログファイル
    │   ├── mysql
    │   ├── netdata
    │   ├── newrelic
    │   ├── nginx
    │   └── python
    ├── node
    ├── php
    ├── public          # 静的ファイル
    ├── python          # Pythonの参考実装
    │   └── templates   # Jinja2のテンプレート
    ├── ruby
    └── sql             # MySQLの初期データ
  • manual.mdは当日マニュアル。一部社内イベントを意識した記述があるので注意すること。
  • public_manual.md は事前公開レギュレーション

Docker Composeで動かす

事前準備

※bunzip2,unzipなど必要なコマンドがない場合は失敗することがあります。その場合は適宜インストールしてください。

git clone https://github.com/eycjur/private-isu.git
cd private-isu

# MySQLの初期データのダウンロード
cd webapp/sql
curl -L -O https://github.com/catatsuy/private-isu/releases/download/img/dump.sql.bz2
bunzip2 dump.sql.bz2
cd ../..

# ベンチマーカー用の画像をダウンロード
cd benchmarker/userdata
curl -L -O https://github.com/catatsuy/private-isu/releases/download/img/img.zip
unzip img.zip
rm -f img.zip
cd ../..

# .envファイルの作成(中身はnew relicでしか使わないので変更不要)
cp webapp/.env.pub webapp/.env

アプリの起動

make up
# http://0.0.0.0:80 からアプリにアクセスできる
# MySQLの初期データのロードにはかなり時間がかかります。

# テーブルがないなどのエラーが出る場合は、一度まっさらな状態に戻してから再度実行する
make down-all
make up

ベンチマーカーの実行

アプリ起動後にベンチマーカーを実行できます。

make bench

# ベンチマーカー実行中にコンテナごとの負荷を確認する
make stats

ログの取得

ベンチマーカーを実行後に解析を行うことができます。

# nginxのアクセスログを解析する
make analyze-nginx-log
# mysqlのスロークエリを解析する
make analyze-mysql-log
# pythonのprofilerを解析する
#   表示されるリンクをブラウザで開いてください(wslの場合はwslのipアドレス`hostname -I`に置き換えてください)
make analyze-python-log
# memcachedの情報を取得する
#   ベンチマーク前にmake restart-memcachedを実行することを推奨
make analyze-memcached-stats

Dev Containerを用いたデバッグ

devcontainerを用いたPythonのデバッグが可能です。

  1. make downでコンテナを停止する
    デバッグするためには、appのportを解放する必要があります
  2. コマンドパレットからDev Containers: Reopen in Containerを選択する
  3. F5キーでデバッグを開始する
  4. 適当なコードにブレークポイントを設定し、ブラウザからアクセスするとブレークポイントで停止する
    MySQLコンテナの初期データのロードには多少時間がかかります

なお、devcontainer用のdocker-compose上でベンチマーカーを実行する場合は以下の手順に従ってください
(Pythonのプログラムとして起動すると、謎のエラーが発生するのでその対処法です)

  1. デバッグ中であれば一旦停止する
  2. devcontainer内で、make run-serverを実行する
  3. ホスト上で、make benchを実行する

解析結果の見方

docker stats

docker_stats

列の名前 説明
CONTAINER ID と Name コンテナの ID と名前
CPU % と MEM % ホスト上の CPU とメモリを、コンテナがどれだけ使っているかパーセントで表示(CPUはコア数x100%が上限)
MEM USAGE / LIMIT コンテナが使っている合計メモリ容量と、利用が許可されている合計メモリ容量
NET I/O コンテナが自身のネットワークインターフェースを通して送受信したデータ容量
BLOCK I/O コンテナがホスト上のブロックデバイスから読み書きしたデータ容量
PIDs コンテナが作成したプロセス数またはスレッド

アクセスログ

access_log

項目 意味
COUNT アクセス回数
METHOD 呼び出したメソッドの種類
URI 計測したURI
MIN URIへのアクセスにかかる最小アクセス時間(秒)
AVG URIへアクセスするのにかかった時間の平均(秒)
MAX URIへのアクセスにかかる最大アクセス時間(秒)
SUM URIへアクセスするのにかかった時間の合計(秒)

スロークエリログ

全体のパフォーマンス

slow_query_log_whole

ラベル 意味
total 合計値
min 最小値
max 最大値
avg 平均値
95% 上位95%の合計値
stddev 標準偏差
median 中央値
変数 意味
Exec time 実行時間
Lock time ロック待ち時間
Row sent 送信回数
Rows exeamine フェッチした行数
Query size SQLの値

クエリのランキング

slow_query_log_rank

ラベル 意味
Response time 実行時間の和(秒)とスロークエリログ全体に占める割合
Calls 実行回数
R/Call 平均値
V/M 標準偏差
Item クエリのサマリー

クエリの詳細

slow_query_log_individual

それぞれの要素 意味
Hosts クエリーを実行したホスト
Users クエリーを実行したユーザ
Query_time distribution クエリーの実行時間のグラフ化
Tables 関連するテーブル情報の調査方法

MySQLコマンド集

#テーブル一覧
SHOW TABLES;

#テーブル構造
SHOW CREATE TABLE <テーブル名>;

#クエリの実行計画
EXPLAIN <クエリ>;
# id: SELECT識別子、実行順序を示してる
# select_type: クエリの種類
#   SIMPLE: サブクエリやユニオンが含まれていない単純なselect文
#   SUBQUERY: select文のサブクエリに指定されているselect文
#   PRIMARY: UNIONの1つめのselect文
#   UNION: UNIONの2つめ以降のselect文
#   UNION_RESULT: UNIONの無名一時テーブルから結果を取得するselect文
# table: 出力の行で参照しているテーブルの名前
# partitions: クエリが参照したパーティションテーブル。パーティションされていない場合はNULL
# type: テーブルの結合方法
#   ALL: フルテーブルスキャン。インデックスがはられていないため一番遅い  <改善を検討>
#   index: フルインデックススキャン。インデックスがはられていること以外はALLと同じ、2番目に遅い  <改善を検討>
#   range: indexを使用して、範囲検索
#   const: PKもしくはuniqueキーを参照して検索、一番速い
#   eq_ref: PKもしくはuniqueキーを参照して検索、constより遅い
#   ref: 非ユニークインデックスを使用して検索
# possible_keys: MySQLがクエリを実行する際に使用できるインデックス
# key: MySQLが実際に使用したインデックス
# key_len: MySQLが実際に使用したインデックスの長さ
# ref: インデックスと比較されるカラムや値
# rows: クエリ実行のためにMySQLが調査する行数
# filtered: テーブル条件によってフィルタ処理される行数の割合
# Extra: MySQLがクエリーを解決する方法に関する追加情報
#   Using filesort: ソートを行うためにファイルソートを行っている
#   Using temporary: クエリーを解決するために一時テーブルを作成している
#   Using index: インデックスを使用している
#   Using where: クエリーの結果を取得するためにWHERE句を使用している

#インデックス作成
ALTER TABLE <テーブル名> ADD INDEX <インデックス名>(<カラム名>);
ALTER TABLE <テーブル名> ADD INDEX <インデックス名>(<カラム名1>, <カラム名2>);

Python profiler

profiler

項目 意味
ncalls 呼び出し回数
tottime 関数の処理時間の合計(呼び出した関数の処理時間は除外)
percall tottimeをncallsで割った値。一回の実行にかかる平均時間
cumtime 関数の処理時間の合計(呼び出した関数の処理時間も含める)
percall cumtimeをncallsで割った値。一回の実行にかかる平均時間
filename:lineno(function) ファイル名、行番号、関数名

Python wlreporter(line profiler)

wlreporter

column mean
file_name ファイル名
line 行数
avg_per_time 平均値(1e-06ms)
hits その行の実行回数
total_time 合計時間(1e-06ms)

memcached stats

memcached_stats

代表的な項目のみ表示

項目名 説明
cmd_get GETコマンドの累積発行数
cmd_set SETコマンドの累積発行数
get_hits GETコマンドがキーにhitした回数
get_misses GETコマンドがキーにhitしなかった回数
get_expired GETコマンドがキーにhitしたが、期限切れだった回数
limit_maxbytes 使用可能な最大メモリ容量(バイト)
bytes 現在使用中のメモリ容量(バイト)
listen_disabled_num コネクション数の不足によりmemcachedから切断されたコネクション数
threads リクエスト当たりに動作するワーカースレッドの数
curr_items 現在格納中のアイテム数
total_items memcachedの起動から現在までに格納した累積アイテム数
evictions メモリ容量の不足によりmemcachedから追い出されたアイテム数

NetData

現状は利用しない設定になっています。利用する場合は以下の変更が必要です。

  1. webapp/docker-compose.ymlのnetdataのコメントアウトを外す
  2. http://localhost:19999 からnetdataのUIにアクセスして、モニタリングを行う

New Relic

現状は利用しない設定になっています。利用する場合は以下の変更が必要です。

  1. webapp/docker-compose.ymlのnewrelic-infraのコメントアウトを外す
  2. New Relicのアカウントを作成し、webapp/.env.pubを参考に、webapp/.envを作成する
  3. webapp/python/Dockerfileを以下のように変更する。また、devcontainer上での実行コマンドもrun-server-newrelicを利用する
    -CMD gunicorn main:app -b "0.0.0.0:8080" --reload --log-file - --access-logfile -
    +# CMD gunicorn main:app -b "0.0.0.0:8080" --reload --log-file - --access-logfile -
    
    -# # if you want to use newrelic
    -# ENV NEW_RELIC_CONFIG_FILE=newrelic.ini
    -# RUN pip install newrelic
    -# CMD newrelic-admin run-program gunicorn main:app -b "0.0.0.0:8080" --reload --log-file - --access-logfile -
    +# if you want to use newrelic
    +ENV NEW_RELIC_CONFIG_FILE=newrelic.ini
    +RUN pip install newrelic
    +CMD newrelic-admin run-program gunicorn main:app -b "0.0.0.0:8080" --reload --log-file - --access-logfile -
  4. new relicのwebサイトにアクセスし、モニタリングを行う

なお、MySQL,nginx,memcachedなどのモニタリングは設定していません。

cf. 環境構築方法

About

Pixiv 社内 ISUCON 2016の内容に、Python実装を追加し、さらにPython用のDockerfileやログ取得・解析用のスクリプトを追加したものです。

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Go 36.2%
  • PHP 14.3%
  • JavaScript 11.0%
  • HTML 10.4%
  • Python 9.9%
  • Ruby 9.6%
  • Other 8.6%