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.1k
日経電子版でのDjango活用事例紹介 / djangocongressjp2022-nikkei
bungoume
4
4.5k
CircleCIの活用事例とCI高速化/circleci-community-meetup3-speedup
bungoume
3
1.4k
Password Hashing djangocongress 20180519
bungoume
5
3.8k
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
今こそ変化対応力を向上させるとき 〜ログラスが FAST に挑戦する理由〜 / Why Loglass is Talking on the Challenge of Agile Framework FAST
shioyang
0
110
令和最新版 Perlコーディングガイド
anatofuz
4
3.8k
The People First Approach to Engineering Success - DevNot 2024
zikriyeurkmez
0
150
Unlearn Modularity
lemiorhan
4
110
エムスリー全チーム紹介資料 / Introduction of M3 All Teams
m3_engineering
1
320
Oracle Database 23ai 新機能#4 Application Continuity
oracle4engineer
PRO
0
120
Castor - Le Task Runner PHP qui simplifie votre Workflow
lyrixx
1
290
トークナイザー入門
payanotty
2
990
Kubernetes Meetup Tokyo #67 - KEP-3619: Fine-grained SupplementalGroups Control / k8sjp67-kep-3619
everpeace
0
150
怖くないオフライン機能開発 〜基本的な技術で実現する現場向けオフライン機能 / Developing offline functions without fear ~ Offline functions for the field realized with basic technology
kaminashi
1
110
これはPerl? それともRuby? クイズ〜〜〜〜〜!!!- Perl or Ruby Quiz
moznion
2
1.8k
テストコードの品質を客観的な数値で担保しよう〜Mutation Testのすすめ〜
ysknsid25
12
3.4k
Featured
See All Featured
StorybookのUI Testing Handbookを読んだ
zakiyama
26
5.1k
Navigating Team Friction
lara
183
14k
Product Roadmaps are Hard
iamctodd
PRO
48
10k
Sharpening the Axe: The Primacy of Toolmaking
bcantrill
37
1.7k
Fashionably flexible responsive web design (full day workshop)
malarkey
404
65k
VelocityConf: Rendering Performance Case Studies
addyosmani
325
23k
Infographics Made Easy
chrislema
239
18k
Designing Experiences People Love
moore
138
23k
GraphQLの誤解/rethinking-graphql
sonatard
65
9.9k
Music & Morning Musume
bryan
46
6.1k
The Art of Programming - Codeland 2020
erikaheidi
51
13k
Design and Strategy: How to Deal with People Who Don’t "Get" Design
morganepeng
126
18k
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