forked from mattmakai/fullstackpython.com
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathwsgi-servers.html
More file actions
278 lines (266 loc) · 16.1 KB
/
wsgi-servers.html
File metadata and controls
278 lines (266 loc) · 16.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
<!DOCTYPE html>
<html lang="en"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="Full Stack Python explains each layer of the web application stack, from the server up through the rendering in a user's browser.">
<meta name="author" content="Matt Makai">
<link rel="shortcut icon" href="theme/img/full-stack-python-logo-bw.png">
<title>Full Stack Python: WSGI Servers</title>
<link href="theme/css/fsp.css" rel="stylesheet">
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
<script src="https://oss.maxcdn.com/libs/respond.js/1.3.0/respond.min.js"></script>
<![endif]-->
<style>
html,
body {
font-size: 18px;
color: #222;
background: #fefefe;
}
body {
padding-top: 30px;
}
.footer {
padding: 20px 0 30px 0;
}
a, a:hover {border-bottom: 1px dotted; color: #444;}
a:hover {text-decoration: none; color: #000;}
.logo-title {font-size: 56px; color: #403072; padding-top: 80px;
font-family: "News Cycle", "Arial Narrow Bold", sans-serif;
font-weight: bold; line-height: 30px; margin-left: 5px;}
.logo-title a, .logo-title a:hover {color: #000; text-decoration: none;
border-bottom: none;}
.logo-title a:hover {color: gray;}
.logo-image {vertical-align: top; border: none;}
a.list-group-item.active {background: #444; border: 1px solid #222;}
a.list-group-item.active:hover {background: #444; border: 1px solid #222;}
#sidebar {margin-top: 30px;}
@media (max-width: 600px) {
.logo-header-section {
margin: 20px 32px 0 0;
}
}
</style>
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-19910497-7']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
</head>
<body>
<a href="https://github.com/makaimc/fullstackpython.github.com" class="github">
<img style="position: absolute; top: 0; right: 0; border: 0;" src="http://s3.amazonaws.com/github/ribbons/forkme_right_darkblue_121621.png" alt="Fork me on GitHub" />
</a>
<div class="container">
<div class="row">
<div class="col-md-12">
<div class="logo-header-section">
<a href="/" style="text-decoration: none; border: none;"><img src="theme/img/full-stack-python-logo-bw.png" height="42" width="42" class="logo-image" /></a>
<span class="logo-title"><a href="/">Full Stack Python</a></span>
</div>
</div>
</div>
<div class="row">
<div class="col-md-8">
<h1>WSGI Servers</h1>
<p>A <a href="http://wsgi.readthedocs.org/en/latest/">Web Server Gateway Interface</a>
(WSGI) server implements the web server side of the WSGI interface for
running Python web applications. </p>
<h2>Why are WSGI servers necessary?</h2>
<p>A traditional web server does not understand or have any way to run Python
applications. In the late 1990s, a developer named Grisha Trubetskoy
<a href="http://grisha.org/blog/2013/10/25/mod-python-the-long-story/">came up with an Apache module called mod_python</a>
to execute arbitrary Python code. For several years in the late 1990s
and early 2000s, Apache configured with mod_python ran most Python web
applications.</p>
<p>However, mod_python wasn't a actual standard. It was just an implementation
that allowed Python code to run on a server. As mod_python's
development stalled and security vulnerabilities were discovered there
was recognition by the community that a consistent way to execute Python
code for web applications was needed.</p>
<p>Therefore the Python community came up with WSGI as a standard interface that<br />
modules and containers could implement. WSGI is now the accepted approach
for running Python web applications.</p>
<h2>WSGI's Purpose</h2>
<p>Why use WSGI and not just point a web server directly at an application?</p>
<ul>
<li>
<p><strong>WSGI gives you flexibility</strong>. Application developers can swap out
web stack components for others. For example, a developer can switch from
Green Unicorn to uWSGI without modifying the application or framework
that implements WSGI.
From <a href="http://www.python.org/dev/peps/pep-3333/">PEP 3333</a>:</p>
<p>The availability and widespread use of such an API in web servers for
Python [...] would separate choice of framework from choice of web
server, freeing users to choose a pairing that suits them, while
freeing framework and server developers to focus on their preferred
area of specialization.</p>
</li>
<li>
<p><strong>WSGI servers promote scaling</strong>. Serving thousands of requests for dynamic
content at once is the domain of WSGI servers, not frameworks.
WSGI servers handle processing requests from the web server and deciding
how to communicate those requests to an application framework's process.
The segregation of responsibilities is important for efficiently scaling
web traffic.</p>
</li>
</ul>
<p><img src="theme/img/web-browser-server-wsgi.png" alt="WSGI Server <-> Web server <-> Browser" width="100%" class="technical-diagram" /></p>
<p>WSGI is by design a simple standard interface for running Python code. As
a web developer you won't need to know much more than</p>
<ul>
<li>
<p>what WSGI stands for (Web Server Gateway Inteface)</p>
</li>
<li>
<p>that a WSGI container is a separate running process that runs on a
different port than your web server</p>
</li>
<li>
<p>your web server is configured to pass requests to the WSGI container which
runs your web application, then pass the response (in the form of HTML)
back to the requester</p>
</li>
</ul>
<p>If you're using a standard web framework such as Django, Flask, or
Bottle, or almost any other current Python framework, you don't need to worry
about how frameworks implement the application side of the WSGI standard.
Likewise, if you're using a standard WSGI container such as Green Unicorn,
uWSGI, mod_wsgi, or gevent, you can get them running without worrying about
how they implement the WSGI standard.</p>
<p>However, knowing the WSGI standard and how these frameworks and containers
implement WSGI should be on your learning checklist though as you become
a more experienced Python web developer.</p>
<h2>Official WSGI specifications</h2>
<p>The WSGI standard v1.0 is specified in
<a href="http://www.python.org/dev/peps/pep-0333/">PEP 0333</a>. As of September 2010,
WSGI v1.0 is superseded by
<a href="http://www.python.org/dev/peps/pep-3333/">PEP 3333</a>, which defines the
v1.0.1 WSGI standard.</p>
<h2>Example configuration</h2>
<p>A web server's configuration specifies what requests should be passed to
the WSGI server to process. Once a request is processed and generated by the
WSGI server, the response is passed back through the web server and onto
the browser. </p>
<p>For example, this Nginx web server's configuration specifics
Nginx should handle static assets (such as images, JavaScript, and CSS
files) under the /static directory and pass all other requests to the WSGI
server running on port 8000:</p>
<div class="codehilite"><pre><span class="cp"># this specifies that there is a WSGI server running on port 8000</span>
<span class="n">upstream</span> <span class="n">app_server_djangoapp</span> <span class="p">{</span>
<span class="n">server</span> <span class="n">localhost</span><span class="o">:</span><span class="mi">8000</span> <span class="n">fail_timeout</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
<span class="cp"># Nginx is set up to run on the standard HTTP port and listen for requests</span>
<span class="n">server</span> <span class="p">{</span>
<span class="n">listen</span> <span class="mi">80</span><span class="p">;</span>
<span class="err">#</span> <span class="n">nginx</span> <span class="n">should</span> <span class="n">serve</span> <span class="n">up</span> <span class="k">static</span> <span class="n">files</span> <span class="n">and</span> <span class="n">never</span> <span class="n">send</span> <span class="n">to</span> <span class="n">the</span> <span class="n">WSGI</span> <span class="n">server</span>
<span class="n">location</span> <span class="o">/</span><span class="k">static</span> <span class="p">{</span>
<span class="n">autoindex</span> <span class="n">on</span><span class="p">;</span>
<span class="n">alias</span> <span class="o">/</span><span class="n">srv</span><span class="o">/</span><span class="n">www</span><span class="o">/</span><span class="n">assets</span><span class="p">;</span>
<span class="p">}</span>
<span class="err">#</span> <span class="n">requests</span> <span class="n">that</span> <span class="k">do</span> <span class="n">not</span> <span class="n">fall</span> <span class="n">under</span> <span class="o">/</span><span class="k">static</span> <span class="n">are</span> <span class="n">passed</span> <span class="n">on</span> <span class="n">to</span> <span class="n">the</span> <span class="n">WSGI</span>
<span class="err">#</span> <span class="n">server</span> <span class="n">that</span> <span class="n">was</span> <span class="n">specified</span> <span class="n">above</span> <span class="n">running</span> <span class="n">on</span> <span class="n">port</span> <span class="mi">8000</span>
<span class="n">location</span> <span class="o">/</span> <span class="p">{</span>
<span class="n">proxy_set_header</span> <span class="n">X</span><span class="o">-</span><span class="n">Forwarded</span><span class="o">-</span><span class="n">For</span> <span class="err">$</span><span class="n">proxy_add_x_forwarded_for</span><span class="p">;</span>
<span class="n">proxy_set_header</span> <span class="n">Host</span> <span class="err">$</span><span class="n">http_host</span><span class="p">;</span>
<span class="n">proxy_redirect</span> <span class="n">off</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!-</span><span class="n">f</span> <span class="err">$</span><span class="n">request_filename</span><span class="p">)</span> <span class="p">{</span>
<span class="n">proxy_pass</span> <span class="n">http</span><span class="o">:</span><span class="c1">//app_server_djangoapp;</span>
<span class="k">break</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
</pre></div>
<p>Note that the above code is a simplified version of a production-ready Nginx
configuration. For real SSL and non-SSL templates, take a look at the
<a href="https://github.com/makaimc/underwear/tree/master/underwear/roles/web/templates">Underwear web server templates</a> on GitHub.</p>
<h2>WSGI Resources</h2>
<ul>
<li>
<p><a href="http://www.python.org/dev/peps/pep-0333/">PEP 0333 WSGI v1.0</a>
and
<a href="http://www.python.org/dev/peps/pep-3333/">PEP 3333 WSGI v1.0.1</a>
specifications.</p>
</li>
<li>
<p><a href="http://gunicorn.org/">Green Unicorn</a>,
<a href="http://code.google.com/p/modwsgi/">mod_wsgi</a>,
<a href="https://github.com/unbit/uwsgi-docs">uWSGI</a> and
<a href="http://www.gevent.org/">gevent</a> are common WSGI server implementations.</p>
</li>
<li>
<p>This <a href="http://agiliq.com/blog/2013/07/basics-wsgi/">basics of WSGI</a> post
contains a simple example of how a WSGI-compatible application works.</p>
</li>
<li>
<p>A thorough and informative post for LAMP-stack hosting chocies is
presented in the
"<a href="http://www.apreche.net/complete-single-server-django-stack-tutorial/>">complete single server Django stack tutorial</a>." </p>
</li>
<li>
<p>This detailed post entitled
<a href="http://bartek.im/blog/2012/07/08/simplicity-nginx-uwsgi-deployment.html">The Beautiful Simplicity of an nginx and uWSGI Deployments</a>
is great reading for understanding Nginx and uWSGI configurations.</p>
</li>
<li>
<p>The Python community made a long effort to
<a href="http://blog.dscpl.com.au/2010/05/modpython-project-soon-to-be-officially.html">transition from mod_python</a>
to the WSGI standard. That transition period is now complete and an
implementation of WSGI should always be used instead mod_python.</p>
</li>
<li>
<p>Nicholas Piël wrote an interesting benchmark blog post of
<a href="http://nichol.as/benchmark-of-python-web-servers">Python WSGI servers</a>.
Note that the post is a few years old. Benchmarks should be considered
for their specific tested scenarios and not quickly extrapolated as general
"this server is faster than this other server" results.</p>
</li>
</ul>
<br/>
Next read the
<a href="/web-frameworks.html">web frameworks</a> section.
</div>
<div class="col-md-offset-1 col-md-3" id="sidebar">
<div class="list-group">
<a href="/introduction.html" class="list-group-item ">Introduction</a>
<a href="/servers.html" class="list-group-item ">Servers</a>
<a href="/operating-systems.html" class="list-group-item ">Operating Systems</a>
<a href="/web-servers.html" class="list-group-item ">Web Servers</a>
<a href="/platform-as-a-service.html" class="list-group-item ">Platform-as-a-service</a>
<a href="/databases.html" class="list-group-item ">Databases</a>
<a href="/wsgi-servers.html" class="list-group-item active">WSGI Servers</a>
<a href="/web-frameworks.html" class="list-group-item ">Web Frameworks</a>
<a href="/application-dependencies.html" class="list-group-item ">Application Dependencies</a>
<a href="/cascading-style-sheets.html" class="list-group-item ">Cascading Style Sheets</a>
<a href="/static-content.html" class="list-group-item ">Static Content</a>
<a href="/source-control.html" class="list-group-item ">Source Control</a>
<a href="/caching.html" class="list-group-item ">Caching</a>
<a href="/task-queues.html" class="list-group-item ">Task Queues</a>
<a href="/api-integration.html" class="list-group-item ">API Integration</a>
<a href="/no-sql-datastore.html" class="list-group-item ">NoSQL Data Stores</a>
<a href="/web-application-security.html" class="list-group-item ">Web Security</a>
<a href="/logging.html" class="list-group-item ">Logging</a>
<a href="/monitoring.html" class="list-group-item ">Monitoring</a>
<a href="/configuration-management.html" class="list-group-item ">Configuration Management</a>
<a href="/web-analytics.html" class="list-group-item ">Web Analytics</a>
<a href="/best-python-resources.html" class="list-group-item ">Best Python Resources</a>
<a href="/about-author.html" class="list-group-item ">About the Author</a>
<a href="/change-log.html" class="list-group-item ">Change Log</a>
</div>
</div></div>
<hr/>
<div class="footer pull-right">
<a href="http://www.mattmakai.com/" class="underline">Matt Makai</a> 2014
</div>
</div>
<script src="http://code.jquery.com/jquery-2.1.0.min.js"></script>
<script src="theme/js/bootstrap.min.js"></script>
</body>
</html>