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
Deploying Flask (WSGI) Applications
Search
Matt Wright
June 26, 2014
Technology
3
1.4k
Deploying Flask (WSGI) Applications
Supporting files:
https://github.com/mattupstate/flask-nyc-deploying
Matt Wright
June 26, 2014
Tweet
Share
More Decks by Matt Wright
See All by Matt Wright
Python Apps and Docker
mattupstate
1
1.1k
Testing Flask Applications
mattupstate
5
1.3k
Other Decks in Technology
See All in Technology
ここがすごいよ! AWS Systems Manager!
saichan11
0
1.8k
What if...? 처음부터 다시 LLM 어플리케이션을 개발한다면
huffon
0
1k
コンテナ・K8s研修 - 前半 コンテナ基礎・ハンズオン【MIXI 24新卒技術研修】
mixi_engineers
PRO
0
170
Flutter研修【MIXI 24新卒技術研修】
mixi_engineers
PRO
0
160
データ分析基盤を作ってみよう~設計編~
nrinetcom
PRO
1
110
成長期に歩みを止めないための創業期の開発文化形成
mayah
6
420
可視化プラットフォームGrafanaの基本と活用方法の全て
hamadakoji
0
230
テストケースの自動生成に生成AIの導入を試みた話と生成AIによる今後の期待
shift_evolve
0
190
CTOから見た事業開発とプロダクト開発 / My Perspective on Business and Product Development as CTO
keisuke69
4
960
エンジニア向け会社紹介資料
caddi_eng
14
230k
AOAI Dev Day - Opening Session
yoshidashingo
2
470
20240725 LLMによるDXのビジョンと、今何からやるべきか @Azure OpenAI Service Dev Day
nrryuya
3
1.2k
Featured
See All Featured
The World Runs on Bad Software
bkeepers
PRO
63
11k
A Modern Web Designer's Workflow
chriscoyier
689
190k
Bootstrapping a Software Product
garrettdimon
PRO
304
110k
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
353
29k
Optimizing for Happiness
mojombo
373
69k
Clear Off the Table
cherdarchuk
89
320k
Gamification - CAS2011
davidbonilla
78
4.9k
実際に使うSQLの書き方 徹底解説 / pgcon21j-tutorial
soudai
149
45k
Fantastic passwords and where to find them - at NoRuKo
philnash
42
2.7k
GraphQLの誤解/rethinking-graphql
sonatard
59
9.6k
10 Git Anti Patterns You Should be Aware of
lemiorhan
652
58k
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
248
20k
Transcript
Deploying Flask (WSGI) Applications
Matt Wright @mattupstate Engineer @ChatID • Python, Ruby, CoffeeScript •
Flask, Chef, AngularJS Open Source • Flask-Security • Flask-Social • Flask-Mail + a few others
WSGI (Web Server Gateway Interface)
PEP 333 http://legacy.python.org/dev/peps/pep-0333/
# ~/hello.py def application(environ, start_response): start_response('200 OK', [('Content-Type','text/html')]) return ["Hello
World"]
# ~/app.py from flask import Flask app = Flask(__name__) @app.route('/')
@app.route('/<path:path>') def catch_all(path=''): return 'Hello World'
Browser WSGI Gateway WSGI App 1 2 4 3 Request
Flow
Browser WSGI Gateway WSGI App 1 1. Browser sends an
HTTP request to the gateway server Request Flow
Browser WSGI Gateway WSGI App 2 2. Gateway server prepares
and sends the request to the WSGI compatible application 1 Request Flow
Browser WSGI Gateway WSGI App 1 2 3 3. Application
processes the request and returns a response Request Flow
Browser WSGI Gateway WSGI App 1 2 4 3 4.
The gateway server returns the response to the browser Request Flow
Browser WSGI Gateway WSGI Middle- ware WSGI App Middleware
Browser WSGI Gateway WSGI Middle- ware WSGI App WSGI Middle-
ware WSGI Middle- ware WSGI Middle- ware WSGI Middle- ware MOAR MIDDLEWARE!
Gateway Servers (sometimes called “containers”)
http://www.tornadoweb.org/ Tornado
1. Written in Python! 2. Web application framework 3. Asynchronous
networking library 4. WSGI support Tornado
# ~/tor.py from tornado.wsgi import WSGIContainer from tornado.httpserver import HTTPServer
from tornado.ioloop import IOLoop from app import app http_server = HTTPServer(WSGIContainer(app)) http_server.listen(8000) IOLoop.instance().start()
matt @ pc in ~/ $ mkvirtualenv wsgi matt @
pc in ~/ workon:wsgi $ pip install flask tornado matt @ pc in ~/ workon:wsgi $ python tor.py
matt @ pc in ~/ $ curl localhost:8000 Hello World
matt @ pc in ~/ workon:wsgi $ pip install tornado matt @ pc in ~/ workon:wsgi $ python tor.py
http://www.gevent.org/ gevent
1. Written in Python! 2. Coroutine networking library 3. 3rd
party module support gevent
# ~/ge.py from gevent.wsgi import WSGIServer from app import app
server = WSGIServer(('', 8000), app) server.serve_forever()
matt @ pc in ~/ workon:wsgi $ pip install gevent
matt @ pc in ~/ workon:wsgi $ python ge.py
matt @ pc in ~/ $ curl localhost:8000 Hello World
matt @ pc in ~/ workon:wsgi $ pip install gevent matt @ pc in ~/ workon:wsgi $ python ge.py 127.0.0.1 - - [2014-06-24...
http://gunicorn.org/ Gunicorn
Gunicorn 1. Written in Python! 2. Easy configuration 3. Broadly
compatible 4. Extensible 5. Fairly speedy
matt @ pc in ~/ workon:wsgi $ pip install gunicorn
matt @ pc in ~/ workon:wsgi $ gunicorn app:app
matt @ pc in ~/ $ curl localhost:8000 Hello World
matt @ pc in ~/ $ mkvirtualenv wsgi matt @ pc in ~/ workon:wsgi $ pip install gunicorn flask matt @ pc in ~/ workon:wsgi $ gunicorn app:app
https://uwsgi-docs.readthedocs.org/ uWSGI
uWSGI 1. Support for many platforms and languages 2. Multiple
configuration formats 3. Flexible logging 4. Extensible 5. Speaks HTTP and uwsgi
matt @ pc in ~/ workon:wsgi $ pip install uwsgi
matt @ pc in ~/ workon:wsgi $ uwsgi --http :8000 -w app:app ... spawned uWSGI worker 1 ...
matt @ pc in ~/ $ curl localhost:8000 Hello World
matt @ pc in ~/ workon:wsgi $ pip install uwsgi matt @ pc in ~/ workon:wsgi $ uwsgi --http :8000 -w app:app ... spawned uWSGI worker 1 ... [pid: 42176|app: 0|req: ...
(how to start your app) Process Management
http://upstart.ubuntu.com/ upstart
# /etc/init/hello-world.conf description "Hello World app" start on runlevel [2345]
stop on runlevel [06] chdir /srv/hello-world exec /usr/local/bin/uwsgi \ --die-on-term \ --http :8000 \ -w app:app
http://www.freedesktop.org/wiki/Software/systemd/ systemd
# /etc/systemd/system/hello-world.service [Unit] Description=Hello World app [Service] ExecStart=/usr/local/bin/uwsgi \ --die-on-term
\ --http :8000 \ -w app:app [Install] WantedBy=multi-user.target
http://supervisord.org/ supervisord
# /etc/supervisor.d/hello-world.conf [program:hello-world] directory=/srv/hello-world command=/usr/local/bin/uwsgi \ --die-on-term \ --http :8000
\ -w app:app
(some things are better than others) Reverse Proxies
Why? • Static files • URL rewrites • Routing •
Header mods • App aggregation • and many more! • Network security • Authentication • Load balancing • SSL termination • Compression • Caching
http://www.nginx.org/ Apache
# /etc/apache2/sites-enabled/hello-world.conf <VirtualHost *:80> ServerName hello-world.com ProxyPreserveHost On ProxyPass /static
! Alias /static "/srv/hello-world/static" ProxyPass / http://127.0.0.1:8000/ ProxyPassReverse / http://127.0.0.1:8000/ </VirtualHost>
http://www.nginx.org/ Nginx
# /etc/nginx/sites-enabled/hello-world.conf server { listen 80; server_name hello-world.com; location /
{ proxy_pass http://127.0.0.1:8000; } location ^~ /static/ { root /srv/hello-world/static; } }
(is hard) Concurrency
Concurrency Models callback/generator (auto) lightweight threads (auto) processor/thread (config) processor/thread
(config) Tornado gevent Gunicorn uWSGI
Increasing Concurrency processes processes workers + processes workers + processes
Tornado gevent Gunicorn uWSGI
Increasing Workers Gunicorn uWSGI --workers <integer> --workers <integer>
DISCLAIMER!
(when one server isn’t enough) Load Balancing
Machine Level App Server 192.168.1.101 App Server 192.168.1.102 App Server
192.168.1.102 Primary Load Balancer 192.168.1.100
# /etc/nginx/sites-enabled/load-balancer.conf upstream app_upstream { least_conn; server 192.168.1.101:8000 server 192.168.1.102:8000
server 192.168.1.103:8000 } server { listen 80; server_name hello-world.com; location / { proxy_pass http://app_upstream; } }
Machine + Process Level App Server 192.168.1.101 App Server 192.168.1.102
App Server 192.168.1.102 Primary Load Balancer 192.168.1.100 t 127.0.0.1:8001 127.0.0.1:8002 127.0.0.1:8000 127.0.0.1:8000 127.0.0.1:8001 127.0.0.1:8002 127.0.0.1:8000 127.0.0.1:8001 127.0.0.1:8002
# /etc/supervisor.d/hello-world.conf [program:hello-world] numprocs=3 process_name=hello-world%(process_num) directory=/srv/hello-world command=/usr/local/bin/uwsgi \ --die-on-term \
--http :80%(process_num)02d \ -w app:app
# /etc/nginx/sites-enabled/hello-world.conf upstream local_upstream { least_conn; server 127.0.0.1:8000 server 127.0.0.1:8001
server 127.0.0.1:8002 } server { listen 80; server_name hello-world.com; location / { proxy_pass http://local_upstream; } }
(I’ve failed at this a lot) Recommendations
1. Use virtualenv and pip 2. Don’t use virtualenvwrapper 3.
Use a `requirements.txt` file Python
1. Provide default settings 2. Enable settings to be overridden
a. Environment Variable(s) b. Default file locations 3. Raise an error at startup when required settings are missing 4. Generate a `SECRET_KEY` with `os. urandom(16)` Configuration
1. Prefer the uwsgi protocol over HTTP 2. Prefer TCP
sockets over Unix sockets 3. Lots of useful options a. virtualenv + pythonpath b. enable-threads + lazy-apps c. need-app d. stats Use uWSGI
1. Pass custom headers 2. Lots of useful modules a.
ngx_http_geoip_module b. ngx_http_gzip_module c. ngx_http_memcached_module d. ngx_http_status_module Use Nginx
(putting it all together) Automation
http://www.ansible.com/ Ansible
(because what could go wrong?) Demo
Thank You! mattupstate.com gittip.com/mattupstate github.com/mattupstate twitter.com/mattupstate