Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
uwsgi-docker-pycon2015
Search
bungoume
October 11, 2015
Technology
10
59k
uwsgi-docker-pycon2015
bungoume
October 11, 2015
Tweet
Share
More Decks by bungoume
See All by bungoume
djangocongressjp2023_password_hash
bungoume
2
1.2k
日経電子版でのDjango活用事例紹介 / djangocongressjp2022-nikkei
bungoume
4
4.8k
CircleCIの活用事例とCI高速化/circleci-community-meetup3-speedup
bungoume
3
1.5k
Password Hashing djangocongress 20180519
bungoume
5
3.9k
OSSで始めるセキュリティログ収集/oss-securitylog-builderscon2017
bungoume
29
11k
日経電子版のアプリ開発を支えるログ活用術/nikkei-log-201609
bungoume
1
1.3k
Kibanaで秒間1万件のアクセスを可視化した話/nikkei-kibana-loganalyst2015
bungoume
20
17k
Ansibleを結構使ってみた/ansible-nikkei-2015
bungoume
32
15k
Dynamic Inventoryと参照変数
bungoume
2
4.8k
Other Decks in Technology
See All in Technology
生成AIをより賢く エンジニアのための RAG入門 - Oracle AI Jam Session #20
kutsushitaneko
4
230
Oracle Cloud Infrastructure:2024年12月度サービス・アップデート
oracle4engineer
PRO
0
180
KubeCon NA 2024 Recap / Running WebAssembly (Wasm) Workloads Side-by-Side with Container Workloads
z63d
1
250
権威ドキュメントで振り返る2024 #年忘れセキュリティ2024
hirotomotaguchi
2
740
サービスでLLMを採用したばっかりに振り回され続けたこの一年のあれやこれや
segavvy
2
420
Wantedly での Datadog 活用事例
bgpat
1
440
LINE Developersプロダクト(LIFF/LINE Login)におけるフロントエンド開発
lycorptech_jp
PRO
0
120
ハイテク休憩
sat
PRO
2
150
ブラックフライデーで購入したPixel9で、Gemini Nanoを動かしてみた
marchin1989
1
530
kargoの魅力について伝える
magisystem0408
0
210
Oracle Cloudの生成AIサービスって実際どこまで使えるの? エンジニア目線で試してみた
minorun365
PRO
4
280
【re:Invent 2024 アプデ】 Prompt Routing の紹介
champ
0
140
Featured
See All Featured
Agile that works and the tools we love
rasmusluckow
328
21k
Build The Right Thing And Hit Your Dates
maggiecrowley
33
2.4k
Rails Girls Zürich Keynote
gr2m
94
13k
How GitHub (no longer) Works
holman
311
140k
Fantastic passwords and where to find them - at NoRuKo
philnash
50
2.9k
The Myth of the Modular Monolith - Day 2 Keynote - Rails World 2024
eileencodes
17
2.3k
The Psychology of Web Performance [Beyond Tellerrand 2023]
tammyeverts
45
2.2k
Save Time (by Creating Custom Rails Generators)
garrettdimon
PRO
28
900
Writing Fast Ruby
sferik
628
61k
Evolution of real-time – Irina Nazarova, EuRuKo, 2024
irinanazarova
5
450
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
44
6.9k
Docker and Python
trallard
42
3.1k
Transcript
uWSGI/Dockerを利用したWebサービス運用事例 PyConJP 2015, 10/11 Yuri Umezaki
#PyConJP_M 2
自己紹介 梅崎 裕利 • 会社 ◦ 日本経済新聞社デジタル編成局 • 主な業務 ◦
Ansibleでサーバ管理 ◦ Django+Elasticsearch(ES)で検索API作成 ◦ Fluentd+ES+Kibanaでログ分析 3
社内でのPython活用シーン • Google App Engine (2010〜) • New API (Search,
Authorization, Logging, etc…) ◦ Django, django-rest-frameworkなど ◦ 全部Python3系で動いています(すでにほぼv3.5) • ちょっとしたスクリプト ◦ Ansible module ◦ Slack通知 ◦ データ集計・分析 ◦ テストツール 4
目次 • uWSGI・Gunicornとは ◦ 特徴紹介 ◦ Gunicornとの比較 • サービスを停止させないGracefulな更新 ◦
更新の課題 ◦ uWSGIで用意されている機能 • Dockerとの併用事例 ◦ 複数PaaS対応(Docker, Heroku)方法 ◦ uWSGI設定例 • まとめ 5
対象 • 話すこと ◦ Djangoなど従来型のPython WebAppの話 • 話さないこと ◦ aiohttpなど非同期なWeb
6
uWSGI・Gunicorn 7
Python Webアプリケーションを動かす方法 WSGI対応サーバを利用する • gunicorn • uwsgi • Apache+mod_wsgi gunicornは利用事例が多くシンプル、
uwsgiは最近のトレンドで多機能 8
質問 • Gunicorn使っている人? ◦ 会場で20% ぐらい • uWSGI使っている人? ◦ 会場で40%
ぐらい 9
uWSGIは多機能 • http以外にもuwsgiプロトコルが話せる • 実はhttpsやspdy、WebSocketも話せる • 複数のアプリも動かせる(Emperorモード) • virtualenvなどが使える •
PythonだけでなくRuby, Perl, Lua, PHPなどにも使える • スプーラ機能 • プロファイラ • キャッシュや静的ファイル配信 • 設定パラメータを数えたら1200以上あった(!!) 10
Gunicornはシンプル • 簡単に起動できる ◦ gunicorn --workers=4 app.wsgi ◦ uwsgi --http
127.0.0.1:8000 --wsgi-file app/wsgi.py --master --processes 4 • 利用事例が多い • uWSGIほど設定項目は多くないが、必要十分 11
uWSGIとGunicornのベンチマーク 12
ベンチマーク環境 • Webサーバ ◦ AWS EC2 m4.large ◦ Amazon Linux
AMI 2015.9 • app ◦ Nginx: 1.8.0 (amazon-repo) ◦ debug-server (python3.5) • 負荷かけツール ◦ wrk ◦ 別サーバより実行 13
ベンチマークに利用したアプリケーション • debug-server ◦ https://www.github.com/bungoume/debug-server ◦ リクエスト内容をJSONで返すサーバ ◦ Django1.8.5 ◦
Python 3.5 (branch) 14
ベンチマーク内容 以下の秒間レスポンス数を比較 • nginx + uwsgi(uwsgi-protocol) • nginx + uwsgi(http)
• uwsgi直接(http) • nginx + gunicorn(http) • gunicorn直接(http) (ワーカー数・スレッド数)は(3, 3)と(4, 1)でテスト 15
nginxの設定 (共通) • ほぼamazon linuxデフォルトのまま 16
ベンチマーク: uWSGI + nginx (uwsgi) nginxの設定 uwsgiの設定(改行しています) 17
ベンチマーク: uWSGI + nginx (uwsgi) レスポンス内容(tcpdump) 18
ベンチマーク: uWSGI + nginx (uwsgi) ベンチマーク結果 19
ベンチマーク: uWSGI (http)+ nginx nginxの設定 uwsgiの設定 20
ベンチマーク: uWSGI (http)+ nginx レスポンス内容(tcpdump) 21
httpプロキシの注意 Python側(uwsgi)でRemote_IPやHost, protocolの値が変わってしまう X-Forwarded-ForやX-Forwarded-Host または、RFC7239のForwarded Headerに入れて利用する 22
ベンチマーク: uWSGI (http)+ nginx ベンチマーク結果 23
ベンチマーク: Gunicorn + nginx nginxの設定 gunicornの設定 24
ベンチマーク: Gunicorn + nginx レスポンス内容 25
ベンチマーク: Gunicorn + nginx ベンチマーク結果 26
ベンチマーク結果まとめ • 今回試した限りはuWSGIのほうが早かった • gunicornはthreadを2以上にしたりeventletを有効にしたりすると遅くなった • (もちろんアプリや設定、環境などによって異なる可能性はあるので注意) nginx+ uwsgi nginx+
uwsgi(http) uwsgi (http) nginx+ gunicorn gunicorn nginx (参考) worker:3 thread:3 1723.10 1747.53 1656.80 1139.12 1260.17 47868.37 worker:4 thread:1 1500.75 1525.72 1608.57 1357.21 1439.42 (req/s) 27
uwsgiやgunicornのhttpを直接使うときの注意点 • gunicorn直接だとheaderとコンテンツが分かれて送信される • uwsgi直接だとheaderにchunkedが入らない。keep-aliveにならない • uwsgi直接はkeep-aliveを使うのは少々無理やりな感じになる ◦ add-header=Connection: Keep-Alive
• uwsgiはhttp-soketでなくhttpを使ったほうがよい ◦ ただし、httpをつかってもkeep-aliveになるわけではない • nginxを挟むとheaderが追加され、パケットも一つになる 28
レスポンス内容: Gunicorn 直接 ヘッダ, body, 終端が別パケットで送られている 29
レスポンス内容: uWSGI 直接 コネクションが毎回切れている。chunkedになってない 30
uWSGI・Gunicorn まとめ • gunicornは事例多い・シンプル • uwsgiはトレンド・多機能 • 今回のベンチマークでは uwsgi >
gunicorn • uwsgiのhttpやgunicornを直接外部に公開するのは注意 ◦ nginxなどのリバースプロキシを通すのが良い 31
uWSGIでGracefulな更新 32
Gracefulな更新とは • サービスを止めずにアプリケーションを更新する方法 • ゼロダウンタイム・ゼロウェイトを実現したい • いろいろな方法がある ◦ DNSで切り替える ◦
LBでWebサーバを切り替える ▪ 複数のサーバを利用する ▪ サーバが切り替わるBrue-Greenデプロイ ◦ nginxで振り先を切り替える ◦ WSGIサーバでリロードする 33
イメージ図 切り替え箇所 新アプリ (サーバIP、 Port、 worker) 旧アプリ (サーバIP、 Port、 worker)
クライアント 34 • 切り替える場所の違い ◦ DNS, LBはサーバの切り替え ◦ nginxはサーバやSocket、Portの切り替え ◦ uWSGIは主にWorkerの切り替え
更新の注意点 • サービスを止めない ◦ 新しいアプリケーションが起動する間スローダウン ◦ 古いアプリケーションを止めるときにエラーが発生 • なるべく即座に反映できる ◦
DNSで切り替えるとクライアントが旧IPにアクセスし続ける恐れ • 簡単に更新できるようしておく ◦ 上段も設定変更が必要になることがある ◦ nginxで切り替える場合はデプロイのたびにnginxの設定変更が必要 ◦ 結合度が高まってしまう • ロールバックもできるように 35
uWSGI上で利用できる仕組み • Standard graceful reload • Worker reload • Chain
reload • Zerg mode • Reuse port • Master forking • Subscription system http://uwsgi-docs.readthedocs.org/en/latest/articles/TheArtOfGracefulReloading.html 36
Standard Graceful Reload (Prefork, Lazy-app) 動いているWorkerが止まるのを待って再起動する • 使い方 ◦ FIFOにrを書き込む(--maste-fifo
オプションでsocketを要しておきechoなどで書き込む) ◦ touch-reloadオプションを使う ◦ SIGHUPを送る ◦ uwsgi.reload() APIを呼ぶ • メリット ◦ 管理が簡単 ◦ 軽量なPreforkでも使える ◦ 不整合が起きない • デメリット ◦ 長い待ち時間が発生する 37
Worker Reload(秒間レスポンス数) • 約1分間の停止期間が発生(preforkでテスト) 38
Worker Reload(平均レスポンス時間) • 60秒でタイムアウト(504)が発生している • アプリケーション起動前の502も発生 39
Worker Reload(Lazy-app) Workerだけをリロードする • 使い方 ◦ FIFOにwを書き込む ◦ touch-worker-reloadオプションを使う •
メリット ◦ 全体の再起動が不要になる • デメリット ◦ コードの更新にしか有効でない 40
Worker Reload(レスポンス数) • 2秒ほど止まるが500エラーなどは出ていない 41
Worker Reload(レスポンス時間) • 一瞬詰まるが問題なさそう 42
Chain Reload (Lazy-app) Workerを一つひとつ順番にリロードしていく • 使い方 ◦ FIFOにcを書き込む ◦ touch-chain-reloadオプションを使う
• メリット ◦ ある程度ワーカー数があれば、クライアントの待ち時間を大幅に削減できる ◦ リロード時の負荷が少ない • デメリット ◦ コードの更新にしか有効でない 43
Chain Reload (レスポンス数) • 4workers, 2threadsにて。段階的に切り替わっており総数への影響は少ない 44
Chain Reload (平均レスポンス時間) • 待ちは発生していない 45
Worker reload, Chain reloadの問題点 uwsgiの設定更新には使えない • 依存ライブラリ更新ができない • Pythonのバージョンをあげられない 46
Unix socketをプールとして活用する(Zerg mode) マスターのuwsgiを用意してportをUnix socketに変換し、 socketに複数のインスタンスを紐付けて振り分ける • 使い方 ◦ masterデーモンを用意しておき、し、アプリはzergでsocketに割り当てる
◦ 更新時は同じsocketで起動し、古いものを落とす • メリット ◦ uWSGIの設定変更も可能になる ◦ 待ち時間が少ない ◦ ロールバックしやすい • デメリット ◦ 追加で常駐のmasterデーモンが必要で、リロード時は更にプロセスが必要になる ◦ 通常と異なる設定が必要。ちょっとわかりにくい 47
Zerg mode (レスポンス数) • 起動時に減るが、大きな影響はなさそう。終了は問題ない(graceful shutdown) 48
Zerg mode (平均レスポンス時間) • 起動時に若干増える。 49
同一ポートを利用 (Reuse-Port) Linux≧3.9かBSD系で使えるSO_REUSEPORTを活用する • 使い方 ◦ --reuse-portオプションを使って起動する ◦ 新しいアプリを同じポートで起動し、古いものを落とす •
メリット ◦ Zerg modeと同じように、uWSGI自体の設定変更も可能 ◦ masterデーモンが不要なので管理が楽 • デメリット ◦ カーネルサポートが必要 複数のプロセスで同じTCPポートをバインドできる夢の機能 LinuxだとKernelがバランシングしてくれる 50
Reuse Port (レスポンス数) • 古いものをSIGINT(強制終了)で止める 51
Reuse Port (レスポンス数) • しかし若干エラー(502)が出ている 52
Reuse Port (平均レスポンス時間) • 起動時と終了時に僅かな待ちが発生している。(緑は502) 53
Reuse Port (レスポンス数) • 古いバージョンをgraceful shutdownすると1分間止まってしまう 54
Reuse Portについて • 試したOSはLinux(4.1.7) • 複数バインド時にどちらに飛ばすかはKernel次第なので細かい制御は難しい • 夢の機能は万能ではなかった。 55
Master forking (黒魔術!) masterを再フォークする • 使い方 ◦ FIFOにfを書き込む • メリット
◦ カーネルサポートも追加プロセスも不要 ◦ かなり速い • デメリット ◦ ログやpidなどの一貫性が壊れる 56
結果 • 試した限りではうまく切り替わりませんでした... 57
Subscription System サブスクリプションサーバとよばれるロードバランサを用意して紐付ける • 使い方 ◦ uwsgi --fastrouter :1717 --fastrouter-subscription-server
192.168.0.100:2626 • メリット ◦ 簡単かつゼロダウンタイム ◦ 構成がシンプル • デメリット ◦ fastserverのようなサブスクリプションサーバが必要 58
Gracefulまとめ • 各機能に特徴があるので要件次第 • アプリケーションのみを安全に切り替えるならChain Reload • ライブラリ更新やロールバックを考慮するならZerg Dance •
ごく僅かなエラーより管理のしやすさを優先させるならReuse Port 利点・欠点を見ながら、良いものを選択 59
uWSGI+Docker利用事例 60
事例 61 • 新規モバイルアプリ向けAPI • 規模はまだ小さいサービス • Djangoを利用して作成
優先したこと 62 • 管理のしやすさ ◦ ライブラリを含め、アプリの更新がしやすい ◦ 別の環境に移行しやすい ≒ 昨今のコンテナ技術周りに追従しやすい
• 運用のしやすさ ◦ サーバにログインしなくても状況がわかるように ◦ 壊れたら消せる = ログは別の場所に送っておく
最初は優先しない • 性能 • 完全にGracefulな更新 63
というわけで、 reuse-port を使います 64
アプリとインフラの分割単位 • Herokuを参考 ◦ アプリ自体はHerokuでも動かせる形にしておく • http(またはuwsgiプロトコル)を話すところまでアプリ ◦ Pythonバージョンや異存ライブラリはアプリで指定 •
LBやリバースプロキシ、デプロイ自体はインフラ ◦ Ansibleやクラウドの機能を利用 65
アプリ側のディレクトリ構成 66 • debug-serverの例 • heroku,dockerどちらでも動く ◦ heroku deploy ◦
docker run
Dockerfileの中身 • Dockerfile • python:3-onbuild 67
uWSGIの設定例 68
構成図 69
現在のデプロイ方法 現在は1ホスト1コンテナの構成 • 新バージョンのコンテナをビルドする • 古いバージョンのコンテナIDを控えておく • reuse-portを使って新バージョンのコンテナを起動する • 数秒待つ
• 古いコンテナを止める 70
運用事例まとめ • Dockerを1ホスト1コンテナとして利用 ◦ 汎用的なVirtualenvとして • Dockerを利用することでHerokuでもdocker runでも動かせる • ECSなどのコンテナホスティングにそのまま載せられる
• ログなどの状態は内部に持たないようにしておく 71
今後の方針 72 • nginxやfluentd側もコンテナにする • デプロイしやすいサービスが出たら乗り換える ◦ AWSのECSに移行中
まとめ 73
74 • uWSGIは多機能、Gunicornはシンプル • 今回のベンチではuWSGIのほうがGunicornより速い • uWSGIはいろいろなGraceful Reload方法がある • 事例としてはReuse-Portを利用している
75 性能・運用のしやすさ・コストなどを 考慮してうまく使うようにしましょう
ご清聴ありがとうございました。 76
予備スライド 77
アクセスログの取り方 78