背景
- いつも簡単なPoC用web appをflaskとvueで作っている。
- バックエンドはflaskのdev serverを使っているが、本当はよくないらしい。
- gunicornやnginxを通すとよいとよく聞くが、何がなんだかわからないので、調べる+使ってみる。
- かなり色々なサイトを参考にさせていただいた。本当にありがとうございます。→参考にさせていただいたサイト様欄
お勉強
gunicornとは何か?
- PythonのWebアプリケーションサーバー
- WSGI(Web Server Gateway Interface)準拠のWebアプリケーションフレームワークと連携して動作
- WSGIとは?
- WebサーバとWebアプリケーション間の汎用的なインターフェースを定義する
- WSGIを利用することで、WebサーバとWebアプリケーションの実装を切り離すことができ、WebサーバとWebアプリケーションフレームワークの組み合わせを柔軟に選択可能
- flaskはWebアプリケーションフレームワーク
- nginxはwebサーバ
- WSGIはnginxとflaskをつないでくれる
- 複数のプロセスを同時に実行し、複数のリクエストを同時に処理可能
- Webアプリケーションのパフォーマンスが向上し、ユーザーに迅速かつ効率的なレスポンスを提供することが可能
nginxとは何か?
- Webサーバーソフトの1つ
- webサーバとは?
- Webサーバーとは、ユーザーからのリクエストを受けて処理を実行し、ユーザーにレスポンスを返すためのコンピューター
- 特徴は「オープンソース」「高性能な処理」「幅広い機能」
- リバースプロキシやロードバランサとしても使える
- リバースプロキシとは?
- (リバースプロキシの前に)プロキシ(フォワードプロキシ)とは?
- ネットワーク内のpcの代理でwebサーバにリクエストを送ってくれる
- メリット
- キャッシュ:再度アクセス時に高速にアクセス可能
- ユーザ認証:ネットワーク内の特定のpcのみwebにアクセスできる制限をかけられる
- フィルタリング:見てはいけないサイトを禁止できる
- ウィルス対策:受信コンテンツのウィルスチェックができる
- 匿名性の確保:ネットワーク外のwebサーバにはプロキシサーバがアクセスするので、ネットワーク内のIPアドレスなどを隠せる
- リバースプロキシとは?
- ネットワーク外からネットワーク内へのアクセスを中継する
- メリット
- リクエストに応じたサーバ選択:外から見たら一つだけど、中で処理するサーバを分けられる
- 負荷分散:同じ処理を行う複数のサーバを置いておけば、大量アクセスを分散できる
- キャッシュ:同じ情報を保存しておいて、高速に返せる
- SSL高速化:内部のwebサーバで複合化しなくてよくなり、リバースプロキシで高速に行える
- セキュリティ向上:ネットワーク外から内部のサーバのIPなどを隠せる
- (リバースプロキシの前に)プロキシ(フォワードプロキシ)とは?
- ロードバランサとは?
- いったんサーバーへのアクセスを集約し、リソースに余裕があるサーバーを接続先として選択する
- 事前に決めた順序でリクエストを各サーバーに振り分ける「静的分散」、サーバーの状態をリアルタイムに測定して、リクエストをサーバーに振り分ける「動的分散」の2つがある
- リバースプロキシとは?
実験
概要
- ①flaskのdevelopment serverをそのまま使った場合、②gunicornを通した場合、③nginxからgunicornを通した場合のそれぞれの動作を確認した
- 結果は以下のようになった
- gunicornを使うと処理が早くなる
- →プロセス数が増えるため
- gunicorn+nginxにするとgunicornより遅くなる
- →gunicornとnginxとの通信が発生するため?
- gunicornを使うと処理が早くなる
構成 | Average Response Time(ミリ秒) |
---|---|
①flask dev server | 80.44 |
②flask dev server + gunicorn | 47.30 |
③flask dev server + gunicorn + nginx | 75.52 |
再現方法
- こちらからコードを取得
- docker composeを使える環境にする
- 各フォルダ{①:./flask, ②:./flask_gunicorn, ③:./flask_gunicorn_nginx}に入り、docker composeを起動する.以下①flaskの例
cd flask docker compose up
- flask/user/src/output_stats.csvに結果が保存される
メモ
各構成
- ①flask
- webコンテナでflaskを起動
- userコンテナからflaskにアクセスして、apiの性能テストを行う
- ②flask+gunicorn
- webコンテナでgunicornを起動+flaskと通信
- userコンテナからgunicornにアクセスして、apiの性能テストを行う
- ③flask+gunicorn+nginx
- webコンテナでgunicornを起動+flaskと通信
- nginxコンテナでgunicronと通信
- userコンテナからnginxにアクセスして、apiの性能テストを行う
オプション
- gunicornの起動
- gunicorn -w 4
- apiの性能テスト(locust)
- -u 1000 -r 100 --run-time 10s
ファイルの権限
- docker内で作成したファイルをhostで編集しようとすると権限エラーが出る→hostのユーザとUID、GIDを合わせると問題が起きなくなる
- まずdocker-compose.yamlで下記を設定(hostのUID: 1000, GID: 1000とする)
... services: service_name: args: - UID=1000 - GID=1000 - USERNAME=user - GROUPNAME=user ....
- Dockerfileでユーザを作成+選択
... ARG UID ARG GID ARG USERNAME ARG GROUPNAME RUN groupadd -g ${GID} ${GROUPNAME} -f && \ useradd -m -s /bin/bash -u ${UID} -g ${GID} ${USERNAME} ...(aptのupdate, installなど)... USER ${USERNAME}
nginxの設定
- 下記をnginx.confに記載→コンテナにコピーする
...(ここから上の部分もないと動かない)...
http {
server {
# ここは待ち受けるポートを指定
listen 80;
# ここは例にならった
server_name localhost;
# ここで飛ばしたい場所を指定
location / {
# docker composeではサービス名でコンテナ間の通信が可能(gunicornは5901ポートを開いてある)
proxy_pass http://web:5901;
}
}
}
locustの実行
- docker-compose.yamlのcommandで下記のようにすると、うまくいかない
... command: locust -f locustfile.py --headless -u 1000 -r 100 --run-time 10s --csv=output ...
- 下記のようにフルパスを入れるとうまくいった
... command: /home/user/.local/bin/locust -f locustfile.py --headless -u 1000 -r 100 --run-time 10s --csv=output ...
その他メモ
- docker-compose.yamlではコンテナ間のみの通信なら、exposeでok。portsとするとコンテナの外にポートが開いてしまう。