skydum

個人的な作業記録とか備忘録代わりのメモ

uWSGIで利用できるオプションとその説明

uWSGIで利用できるオプションとその説明

  • uWSGIは設定できるオプションが多いが公式サイトの説明がシンプルすぎてわからなくなるので、個人的に調べて内容を記載する。

ドキュメント

環境

  • CentOS Linux release 7.9.2009 (Core)
  • apach(2.4.6-97)
  • python(3.6.8)
  • uwsgi(2.0.20)
  • Flask(2.0.3)
  • mod_proxy_uwsgi(2.0.18)

uWSGIのインストール

  • すでにuWSGIがインストールされている場合は念のため一度アンインストールする
  • pcreとpcre-develを入れてるのはlog-routeを利用する場合にpcre-develを入れてからuWSGIをインストールしないと
    !!! no internal routing support, rebuild with pcre support !!!
    のエラーが表示されlog-route機能が利用出来ない

  • CentOS 7の場合

yum install pcre pcre-devel
pip install uwsgi -I --no-cache-dir
apt-get install libpcre3 libpcre3-dev
pip install uwsgi -I --no-cache-dir

uwsgitopを利用する

# python3 -m pip install uwsgitop

設定変更の参考

uwsgiに設定するオプション

  • uWSGI --helpで設定できるオプションの一覧が取得できるが量が多すぎる

設定内容の誤りをチェックする

オプション サンプル 内容 ドキュメント
strict strict = true 設定ファイルに記載できるオプションは、uWSGIがオプションとして認識できるもののみとし、strictを有効にした場合は認識できないオプションが記載されている場合はエラーでuWSGIが起動しなくなる
typoを防げる。
独自のプレースホルダーが使えなくなる?(要調査)
strict
need-app need-app = true 実行するアプリケーションに問題があった場合uWSGIを起動しない
デフォルトではアプリは起動するが500エラーを返すので有効にするのを推奨
need-app

パフォーマンスの監視

  • uwsgitopでstatsに指定したファイルを指定して現在のprocessの状態とthreadの状態を確認することができる
オプション サンプル 内容 ドキュメント
stats stats = /var/log/uwsig.socket パフォーマンス監視用の統計データを出力 stats
memory-report memory-report = true モリーの使用量を出力? memory-report

便利そうなオプション

オプション サンプル 内容 ドキュメント
vacuum vacuum = true uWSGIが起動時に作成したファイル(ソケットやPIDのファイルなど)をuWSGIの終了時に自動的に削除する
vacuum
chmod-socket chmod-socket = 666 http-socket, socketオプショと併用する
socketファイルのアクセス権限を変更する
chmod-socket
chown-socket chown-socket = uwsgi_user http-socket, socketオプショと併用する
socketファイルの所有者を変更する
chown-socket

起動時に関係するオプション

オプション サンプル 内容 ドキュメント
chdir chdir = /home/uwsgi_user/api uWSGIが起動し、アプリケーションをロードする前にカレントディレクトリを移動する chdir
chdir2 chdir2 = /home/uwsgi_user/api uWSGIが起動し、アプリケーションをロードしたあとで、カレントディレクトリを移動する chdir2
single-interpreter single-interpreter = true プロセス毎に一つのアプリケーションを利用する single-interpreter
PythonエージェントとuWSGIウェブサーバー
die-on-term die-on-term = true SIGTERMを受けた時にプロセスを終了する
デフォルトではプロセスが再起動してuWSGIは終了しない
die-on-term
What is –die-on-term?
wsgi-file wsgi-file = /home/uwsgi_user/api/app.py 起動するアプリケーションのファイルを指定する wsgi-file
callable callable = app

例としてFlaskの場合
from flask import Flask
app = Flask(__name__)
とした場合は、appを指定する
起動するアプリケーションのオブジェクトを指定する callable
gid gid = uwsgi_group 起動するグループIDを指定する gid
uid uid = uwsgi_user 起動するユーザーIDを指定する uid

待ち受ける方式に関するオプション

オプション サンプル 内容 ドキュメント
http http = 127.0.0.1:8080 httpで指定されたアドレスとポート番号で起動する
http-socketを利用する方がパフォーマンスが良い
環境によるので要パフォーマンス調査
http
http-socket http-socket = 127.0.0.1:8080 http-socketで指定されたアドレスとポート番号で起動する
processes = 1でtouch-reloadしてもエラーがクライアントへ返らない
http
socket socket = /home/uwsgi_user/api/app.sock
socket = 127.0.0.0:8080
socketで指定されたファイルまたはipアドレス:ポート番号のいずれかの方法で指定する
ファイル名で指定する場合でapacheと連携する場合、apacheのバージョンが2.4.9以上が必要

socket

各々の待受方式でベンチマークを行った結果

  • apache → uwsgi → app.py実行した結果
  • process=1, threads = 1での結果(環境によってすごく数値が変わるので参考程度)
方式 abテストの結果 uwsgiに直接http接続が可能か
http Requests per second: 1119.57 [#/sec] (mean)
socket(ip:port形式) Requests per second: 1297.07 [#/sec] (mean) 不可
http-socket Requests per second: 1471.42 [#/sec] (mean) 不可
socket(file形式) Requests per second: 1522.14 [#/sec] (mean) 不可

パフォーマンスに直接関係しそうなオプション

オプション サンプル 内容 ドキュメント
master master = true wokerのプロセスが終了した場合に自動的にwokerを再起動してくれる
uWSGI内蔵のPerfork + マルチスレッドで動作する
master
enable-threads enable-threads = ture threadを有効にする
enable-threads = true
とした場合は
threads = 1を設定したのと同じ効果がある
enable-threads
processes processes = 4 利用するプロセス数
processesとworkersはどちらも名称は異なるが同一の設定
processes
workers workers = 4 利用するプロセス数
processesとworkersはどちらも名称は異なるが同一の設定
workers
threads threads = 15 利用するスレッド数
threadsを設定すると
enable-threads = trueも設定される
threads
thunder-lock thunder-lock = true Linuxの場合有効にすることを推奨 thunder-lock
Serializing accept(), AKA Thundering Herd, AKA the Zeeg Problem
ugreen ugreen = true OSのスレッド機構を利用せずに非同期にスレッドを切り替える機構を有効にする
またgreenletよりもパフォーマンスに優れているが、メモリの消費が多い
環境にもよると思うが有効にしても特になにかが変わったように見えなかった
ugreen
uGreen – uWSGI Green Threads
greenlet オプション設定不可 OSのスレッド機構を利用せずに非同期にスレッドを切り替える機構を有効にする
パフォーマンスはugreenより劣るがメモリの消費が少ない
オプションが見つからずエラーとなる
greenlet
uGreen – uWSGI Green Threads

ワーカーの再起動に関するオプション

オプション サンプル 内容 ドキュメント
max-requests max-requests = 100 指定された回数のリクエストを処理したらwokerを再起動する max-requests
max-requests-delta オプション設定不可 max-requestsで指定された回数でwokerが再起動すると同じタイミングでworkerが再起動するので、タイミングをずらすために使用するとあるが、strict modeで起動するとオプションが見つからずエラーとなる

エラーになる原因は以下を参考
あなたの使ってるuWSGI、本当にmax-requests-delta効いてますか?
uWSGIのmax-requets-delta、マジで効いていない
現在のバージョン(uwsgi(2.0.20))では無効なオプションとなる
max-requests-delta
max-worker-lifetime max-woker-lifetime = 60 指定された秒数が経過したらworkerを再起動する max-worker-lifetime
reload-on-rss reload-on-rss = 2048 指定されたバイト数以上のメモリが利用されている場合wokerを再起動する reload-on-rss
worker-reload-mercy worker-reload-mercy = 60 workerがリロードやシャットダウンにかかる時間(秒) worker-reload-mercy

アプリケーションのリロードに関するオプション

オプション サンプル 内容 ドキュメント
touch-reload touch-reload = /home/uwsgi_user/api/uwsig.touch
上記のファイルを更新するとworkerが再起動する
Preforkモード(親プロセスをForkしてWorkerを作成するモード)
リロードされる時にuWSGIの起動オプションも再読込される
touch-reload
lazy-apps lazy-app = true Preforkと違いWorker毎にアプリケーションをロードする lazy-apps
Standard (default/boring) graceful reload (aka SIGHUP)
touch-workers-reload touch-workers-reload = /home/uwsgi_user/api/uwsig.touch lazy-appsと併用する
インスタンス全体のWorkerの同時再起動を避けることができる
touch-reloadと比べて特別メリットがない
touch-workers-reload
Workers reloading in lazy-apps mode
touch-chain-reload touch-chain-reload = /home/uwsgi_user/api/uwsig.touch lazy-appsと併用する
一度に一つのWorkerを再起動するので再起動を行う際の待ち時間を減らすことができる
また、Workerの再起動を順番に行うのでサーバに負荷がかからない
ただし、それなりに多くのWorkerがないとあまり恩恵が受けられない
touch-chain-reload
Chain reloading (lazy apps)
Zerg mode よくわからない よくわからない Zerg mode 1
Zerg mode 2

リロードされる範囲

オプション uWSGIのオプション変更 備考欄
touch-reload 変更可 リロードにかかる時間が長い
touch-workers-reload 不可 processの再起動のみなのでtouch-reloadよりは早い
touch-chain-reload 不可 processの再起動を順番に行う
Zerg mode

ロガー

  • ログ関係は設定の種類が多くてとても分かり辛い
  • ロガーの設定方法は2種類ある(logtoとlogger)
    • logto
      • iniファイルで指定されたファイルへログの内容を出力するlogtoをベースにした機能
    • logger
      • iniファイルで指定された指定の場所(file, socket, syslogなど 詳細はLoggingを参考)へログの内容を出力するloggerをベースにした機能

logto

  • ログの基本設定
    • 記録される内容はオプションは変わっても同じ
    • ログ出力に関するオプションを設定しない場合uWSGIの起動時のログ、アクセスログ、エラー内容が記録される
オプション サンプル 内容 ドキュメント
logto logto = /home/uwsgi_user/api/access_log uWSGIの起動時のログ、アクセスログ、エラーログが記録される
logto2 logto2 = /home/uwsgi_user/api/access_log 特権を剥奪してからログの記録を行う
他の動作はlogtoと同等
daemonize daemonize = /home/uwsgi_user/api/access_log uwsgi uwsgi.iniの様に起動したときに通常はコンソールがコマンド事項状態で止まるが、daemozineを有効にしている場合はuwsgi uwsgi.iniの実行後すぐにコンソールに戻ってきてuwsgiはバッググラウンドで実行するようになる<br<記録されるログはlogtoと同じ
daemonize2 daemonize2 = /home/uwsgi_user/api/access_log アプリケーションの起動後にバックグラウンド動作に移る
uWSGIの起動時のログは記録れずコンソールに表示される、起動時のログが記録されない以外はlogtoと同じ内容が記録される
ファイルをtouchして再起動した時は起動時のログも残る
daemonizeと使い分けるメリットが良くわからない
  • ログ出力に関するオプション設定
オプション サンプル 内容 ドキュメント
disable-logging disable-logging = true 有効にした場合logtoで指定されたファイルへアクセスログを記録しない
apacheとかnginxと連携している場合uWSGI側のアクセスログは不要だと思うのでdisable-logging = trueとしても問題ないと思う
log-4xx log-4xx = true disable-logging = trueの場合に400エラーをlogtoに指定したファイルへ記録する
未設定の場合ログには400エラーは記録されない
log-5xx log-5xx = true log-400 = trueと同じく500エラーをログに記録するようにするのかと思ったらtrueでもfalseでも関係なくlogtoで指定したファイルへエラーが記録されるので、設定する意味がないかもしれない

logger

  • ログに記録する内容をファイルだけでなく別の場所へ記録することができる
  • loggerに記録される内容はlogtoと同じく、uWSGIの起動時のログ、アクセスログ、エラー内容が記録される
  • log-routeがうまく働かない時はログに!!! no internal routing support, rebuild with pcre support !!!が出ていないか確認してください。
    上記の文字が出ている場合はuWSGIのインストールを見てpcre-develを入れてから再度uWSGIを起動する
オプション サンプル 内容 ドキュメント
logger logger = file:/home/uwsgi_user/api/access_log 記録される内容はlogtoと同じ
複数回設定することができ、複数回指定した場合は設定されたすべての設定先にログが記録される
req-logger req-logger = file:/home/uwsgi_user/api/access_log
logger = file:/home/uwsgi_user/api/error_log

約10Mでログローテートする場合
file:logfile=/home/uwsgi_user/api/access_log,maxsize=1000000
loggerと同時に設定する
req-loggerを設定した場合アクセスログはreq-loggerに指定したファイルへ記録され、uWSGIの起動時のログ、エラー内容についてはloggerのファイルへ記録される
少し書き方を変えるとログローテートもできる
log-route logger = internalservererror file:/tmp/errors
log-route = internalservererror (HTTP/1.\d 500)
loggerと同時に設定する
log-routeに設定された正規表現と一致するログをloggerに設定した場所へ振り分ける

公式サイトのサンプルを転機

log-routeに記載する正規表現はログファイルに記載される内容と一致する条件を書くこと

例えばログに
[2022-08-07 21:40:11,780] ERROR in app: Exception on
の様に記載されるのであれば
logger = internalservererror file:/tmp/errors
log-route = internalservererror ERROR in app

の様に記載すると一致する行はloggerに指定されたファイルへ記録され、その他のlogggerには記録されなくなる

uWSGIの起動時のログに記載される内容をlog-routeに設定すれば起動時のログだけを別ファイルに分離することもできる
log-req-route テストしていないので記載方法不明 loggerと同時に設定する
log-req-routeに設定された正規表現と一致するログをloggerに設定した場所へ振り分ける
  • ログ出力に関するオプション設定
オプション サンプル 内容 ドキュメント
disable-logging disable-logging = true logtoのログ出力に関するオプション設定でも書いたのと同様のオプション
loggerと同時に設定した場合はreq-loggerを設定していてもアクセスログを記録することができなくなり、loggerで指定したファイルにもreq-loggerで設定したファイルにもアクセスログが記録されなくなる
disable-logging
log-4xx log-4xx = true logtoのログ出力に関するオプション設定でも書いたのと同様のオプション
disable-logging = trueの場合でも400エラーをloggerに指定したファイルへ記録する
req-loggerを指定している場合はreq-loggerに指定したファイルへ記録する
未設定の場合ログには400エラーは記録されない
log-5xx log-5xx = true logtoのログ出力に関するオプション設定でも書いたのと同様のオプション
trueでも、falseでも関係なくloggerに指定したファイルへエラー内容が記録される

ログローテート

  • logto, logto2, daemonize, daemonize2のファイルが対象
  • uWSGIでログローテートをさせる場合現在のところファイルサイズを基準にログローテートをさせることしか出来ない。
    日毎のログローテートは非対応。
オプション サンプル 内容 ドキュメント
log-reopen log-reopen = true uWSGIが再起動した時にログを再読込する log-reopen
log-maxsize log-maxsize=2000000 ログファイルがここで定義されたサイズ(バイト)以上になった場合ログをログローテートする log-maxsize
logfile-chown logfile-chown
引数なし
uid, gidで指定したユーザーとグループでファイルを作成する
こちらもlogfile-chmodと同じくdaemonize用?
log-maxsize
logfile-chmod logfile-chmod = 777 ログのアクセス権を変更する
設定しても反映されない
daemonizeの時に反映されるような記事がある
Nginx + uWSGI + Djangoのwebアプリケーション環境を作る (その4)
log-maxsize
touch-logreopen touch-logreopen = /home/uwsgi_user/api/uwsgi_log.touch uWSGIがログローテートを管理していない時にuWSGIに新しいログを読み込むように知らせるために利用する touch-logreopen
touch-logrotate touch-logrotate = /home/uwsgi_user/api/uwsgi_log.touch
上記のファイルを更新するとログローテートされる
uWSGIがログローテートを管理している時にuWSGIに強制的にログローテートを実行させる touch-logrotate

ロガーのフォーマット

[uwsgi]
log-format = [pid: %(pid)|app: -|req: -/-] %(addr) (%(user)) {%(vars) vars in %(pktsize) bytes} [%(ctime)] %(method) %(uri) => generated %(rsize) bytes in %(msecs) msecs (%(proto) %(status)) %(headers) headers in %(hsize) bytes (%(switches) switches on core %(core))
log-format = %(addr) - %(user) [%(ltime)] "%(method) %(uri) %(proto)" %(status) %(size) "%(referer)" "%(uagent)"