Browser
WSGI
Gateway
WSGI
App
1
1. Browser sends an HTTP request
to the gateway server
Request Flow
Slide 9
Slide 9 text
Browser
WSGI
Gateway
WSGI
App
2
2. Gateway server prepares and sends the
request to the WSGI compatible application
1
Request Flow
Slide 10
Slide 10 text
Browser
WSGI
Gateway
WSGI
App
1 2
3
3. Application processes the request
and returns a response
Request Flow
Slide 11
Slide 11 text
Browser
WSGI
Gateway
WSGI
App
1 2
4 3
4. The gateway server returns the
response to the browser
Request Flow
Slide 12
Slide 12 text
Browser
WSGI
Gateway
WSGI
Middle-
ware
WSGI
App
Middleware
Slide 13
Slide 13 text
Browser
WSGI
Gateway
WSGI
Middle-
ware
WSGI
App
WSGI
Middle-
ware
WSGI
Middle-
ware
WSGI
Middle-
ware
WSGI
Middle-
ware
MOAR MIDDLEWARE!
Slide 14
Slide 14 text
Gateway Servers
(sometimes called “containers”)
Slide 15
Slide 15 text
http://www.tornadoweb.org/
Tornado
Slide 16
Slide 16 text
1. Written in Python!
2. Web application framework
3. Asynchronous networking library
4. WSGI support
Tornado
Slide 17
Slide 17 text
# ~/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()
Slide 18
Slide 18 text
matt @ pc in ~/
$ mkvirtualenv wsgi
matt @ pc in ~/ workon:wsgi
$ pip install flask tornado
matt @ pc in ~/ workon:wsgi
$ python tor.py
Slide 19
Slide 19 text
matt @ pc in ~/
$ curl localhost:8000
Hello World
matt @ pc in ~/ workon:wsgi
$ pip install tornado
matt @ pc in ~/ workon:wsgi
$ python tor.py
Slide 20
Slide 20 text
http://www.gevent.org/
gevent
Slide 21
Slide 21 text
1. Written in Python!
2. Coroutine networking library
3. 3rd party module support
gevent
Slide 22
Slide 22 text
# ~/ge.py
from gevent.wsgi import WSGIServer
from app import app
server = WSGIServer(('', 8000), app)
server.serve_forever()
Slide 23
Slide 23 text
matt @ pc in ~/ workon:wsgi
$ pip install gevent
matt @ pc in ~/ workon:wsgi
$ python ge.py
Slide 24
Slide 24 text
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...
Slide 25
Slide 25 text
http://gunicorn.org/
Gunicorn
Slide 26
Slide 26 text
Gunicorn
1. Written in Python!
2. Easy configuration
3. Broadly compatible
4. Extensible
5. Fairly speedy
Slide 27
Slide 27 text
matt @ pc in ~/ workon:wsgi
$ pip install gunicorn
matt @ pc in ~/ workon:wsgi
$ gunicorn app:app
Slide 28
Slide 28 text
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
Slide 29
Slide 29 text
https://uwsgi-docs.readthedocs.org/
uWSGI
Slide 30
Slide 30 text
uWSGI
1. Support for many platforms and languages
2. Multiple configuration formats
3. Flexible logging
4. Extensible
5. Speaks HTTP and uwsgi
Slide 31
Slide 31 text
matt @ pc in ~/ workon:wsgi
$ pip install uwsgi
matt @ pc in ~/ workon:wsgi
$ uwsgi --http :8000 -w app:app
...
spawned uWSGI worker 1 ...
Slide 32
Slide 32 text
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: ...
Slide 33
Slide 33 text
(how to start your app)
Process Management
Slide 34
Slide 34 text
http://upstart.ubuntu.com/
upstart
Slide 35
Slide 35 text
# /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
# /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;
}
}
Slide 57
Slide 57 text
(I’ve failed at this a lot)
Recommendations
Slide 58
Slide 58 text
1. Use virtualenv and pip
2. Don’t use virtualenvwrapper
3. Use a `requirements.txt` file
Python
Slide 59
Slide 59 text
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
Slide 60
Slide 60 text
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
Slide 61
Slide 61 text
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