root/asynwsgi/trunk/asynwsgi.html

Revision 467, 14.8 kB (checked in by robin, 2 years ago)

* merged the serviceapi branch

These changes firm up the dispatcher api, the service model api and the service request api

* huge set of name changes
* lots of documentation
* a number of micelaneous bug fixes and api enhancements.


  • Property svn:mime-type set to text/html
Line 
1 <?xml version="1.0" encoding="utf-8" ?>
2 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
4 <head>
5 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
6 <meta name="generator" content="Docutils 0.5: http://docutils.sourceforge.net/" />
7 <title>asynwsgi: A light weight, asynchronous, pep-333/WSGI compatible http server</title>
8 <meta name="author" content="Robin Bryce" />
9 <meta name="copyright" content="Copyright (c) 2007 Robin Bryce" />
10 <style type="text/css">
11
12 /*
13 :Author: David Goodger
14 :Contact: goodger@python.org
15 :Date: $Date: 2006-05-21 22:44:42 +0200 (Sun, 21 May 2006) $
16 :Revision: $Revision: 4564 $
17 :Copyright: This stylesheet has been placed in the public domain.
18
19 Default cascading style sheet for the HTML output of Docutils.
20
21 See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to
22 customize this style sheet.
23 */
24
25 /* used to remove borders from tables and images */
26 .borderless, table.borderless td, table.borderless th {
27   border: 0 }
28
29 table.borderless td, table.borderless th {
30   /* Override padding for "table.docutils td" with "! important".
31      The right padding separates the table cells. */
32   padding: 0 0.5em 0 0 ! important }
33
34 .first {
35   /* Override more specific margin styles with "! important". */
36   margin-top: 0 ! important }
37
38 .last, .with-subtitle {
39   margin-bottom: 0 ! important }
40
41 .hidden {
42   display: none }
43
44 a.toc-backref {
45   text-decoration: none ;
46   color: black }
47
48 blockquote.epigraph {
49   margin: 2em 5em ; }
50
51 dl.docutils dd {
52   margin-bottom: 0.5em }
53
54 /* Uncomment (and remove this text!) to get bold-faced definition list terms
55 dl.docutils dt {
56   font-weight: bold }
57 */
58
59 div.abstract {
60   margin: 2em 5em }
61
62 div.abstract p.topic-title {
63   font-weight: bold ;
64   text-align: center }
65
66 div.admonition, div.attention, div.caution, div.danger, div.error,
67 div.hint, div.important, div.note, div.tip, div.warning {
68   margin: 2em ;
69   border: medium outset ;
70   padding: 1em }
71
72 div.admonition p.admonition-title, div.hint p.admonition-title,
73 div.important p.admonition-title, div.note p.admonition-title,
74 div.tip p.admonition-title {
75   font-weight: bold ;
76   font-family: sans-serif }
77
78 div.attention p.admonition-title, div.caution p.admonition-title,
79 div.danger p.admonition-title, div.error p.admonition-title,
80 div.warning p.admonition-title {
81   color: red ;
82   font-weight: bold ;
83   font-family: sans-serif }
84
85 /* Uncomment (and remove this text!) to get reduced vertical space in
86    compound paragraphs.
87 div.compound .compound-first, div.compound .compound-middle {
88   margin-bottom: 0.5em }
89
90 div.compound .compound-last, div.compound .compound-middle {
91   margin-top: 0.5em }
92 */
93
94 div.dedication {
95   margin: 2em 5em ;
96   text-align: center ;
97   font-style: italic }
98
99 div.dedication p.topic-title {
100   font-weight: bold ;
101   font-style: normal }
102
103 div.figure {
104   margin-left: 2em ;
105   margin-right: 2em }
106
107 div.footer, div.header {
108   clear: both;
109   font-size: smaller }
110
111 div.line-block {
112   display: block ;
113   margin-top: 1em ;
114   margin-bottom: 1em }
115
116 div.line-block div.line-block {
117   margin-top: 0 ;
118   margin-bottom: 0 ;
119   margin-left: 1.5em }
120
121 div.sidebar {
122   margin-left: 1em ;
123   border: medium outset ;
124   padding: 1em ;
125   background-color: #ffffee ;
126   width: 40% ;
127   float: right ;
128   clear: right }
129
130 div.sidebar p.rubric {
131   font-family: sans-serif ;
132   font-size: medium }
133
134 div.system-messages {
135   margin: 5em }
136
137 div.system-messages h1 {
138   color: red }
139
140 div.system-message {
141   border: medium outset ;
142   padding: 1em }
143
144 div.system-message p.system-message-title {
145   color: red ;
146   font-weight: bold }
147
148 div.topic {
149   margin: 2em }
150
151 h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
152 h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
153   margin-top: 0.4em }
154
155 h1.title {
156   text-align: center }
157
158 h2.subtitle {
159   text-align: center }
160
161 hr.docutils {
162   width: 75% }
163
164 img.align-left {
165   clear: left }
166
167 img.align-right {
168   clear: right }
169
170 ol.simple, ul.simple {
171   margin-bottom: 1em }
172
173 ol.arabic {
174   list-style: decimal }
175
176 ol.loweralpha {
177   list-style: lower-alpha }
178
179 ol.upperalpha {
180   list-style: upper-alpha }
181
182 ol.lowerroman {
183   list-style: lower-roman }
184
185 ol.upperroman {
186   list-style: upper-roman }
187
188 p.attribution {
189   text-align: right ;
190   margin-left: 50% }
191
192 p.caption {
193   font-style: italic }
194
195 p.credits {
196   font-style: italic ;
197   font-size: smaller }
198
199 p.label {
200   white-space: nowrap }
201
202 p.rubric {
203   font-weight: bold ;
204   font-size: larger ;
205   color: maroon ;
206   text-align: center }
207
208 p.sidebar-title {
209   font-family: sans-serif ;
210   font-weight: bold ;
211   font-size: larger }
212
213 p.sidebar-subtitle {
214   font-family: sans-serif ;
215   font-weight: bold }
216
217 p.topic-title {
218   font-weight: bold }
219
220 pre.address {
221   margin-bottom: 0 ;
222   margin-top: 0 ;
223   font-family: serif ;
224   font-size: 100% }
225
226 pre.literal-block, pre.doctest-block {
227   margin-left: 2em ;
228   margin-right: 2em }
229
230 span.classifier {
231   font-family: sans-serif ;
232   font-style: oblique }
233
234 span.classifier-delimiter {
235   font-family: sans-serif ;
236   font-weight: bold }
237
238 span.interpreted {
239   font-family: sans-serif }
240
241 span.option {
242   white-space: nowrap }
243
244 span.pre {
245   white-space: pre }
246
247 span.problematic {
248   color: red }
249
250 span.section-subtitle {
251   /* font-size relative to parent (h1..h6 element) */
252   font-size: 80% }
253
254 table.citation {
255   border-left: solid 1px gray;
256   margin-left: 1px }
257
258 table.docinfo {
259   margin: 2em 4em }
260
261 table.docutils {
262   margin-top: 0.5em ;
263   margin-bottom: 0.5em }
264
265 table.footnote {
266   border-left: solid 1px black;
267   margin-left: 1px }
268
269 table.docutils td, table.docutils th,
270 table.docinfo td, table.docinfo th {
271   padding-left: 0.5em ;
272   padding-right: 0.5em ;
273   vertical-align: top }
274
275 table.docutils th.field-name, table.docinfo th.docinfo-name {
276   font-weight: bold ;
277   text-align: left ;
278   white-space: nowrap ;
279   padding-left: 0 }
280
281 h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
282 h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
283   font-size: 100% }
284
285 ul.auto-toc {
286   list-style-type: none }
287
288 </style>
289 </head>
290 <body>
291 <div class="document" id="asynwsgi-a-light-weight-asynchronous-pep-333-wsgi-compatible-http-server">
292 <h1 class="title">asynwsgi: A light weight, asynchronous, pep-333/WSGI compatible http server</h1>
293 <table class="docinfo" frame="void" rules="none">
294 <col class="docinfo-name" />
295 <col class="docinfo-content" />
296 <tbody valign="top">
297 <tr class="field"><th class="docinfo-name">License:</th><td class="field-body">MIT</td>
298 </tr>
299 <tr class="field"><th class="docinfo-name">Project-Label:</th><td class="field-body">asynwsgi</td>
300 </tr>
301 <tr><th class="docinfo-name">Version:</th>
302 <td>0.4dev4-r436-service-api</td></tr>
303 <tr><th class="docinfo-name">Author:</th>
304 <td>Robin Bryce</td></tr>
305 <tr class="field"><th class="docinfo-name">Author-email:</th><td class="field-body"><a class="reference" href="mailto:robinbryce&#64;gmail.com">robinbryce&#64;gmail.com</a></td>
306 </tr>
307 <tr class="field"><th class="docinfo-name">Description:</th><td class="field-body">A suspiciously quick, pure python (2.5 only), asynchronous WSGI server, implemented using asynchronous I/O and non blocking sockets.</td>
308 </tr>
309 <tr><th class="docinfo-name">Copyright:</th>
310 <td><a class="first last reference" href="#copyright-c-2007-robin-bryce">Copyright (c) 2007 Robin Bryce</a></td></tr>
311 <tr class="field"><th class="docinfo-name">Classifiers:</th><td class="field-body">Development Status :: 2 - Pre-Alpha</td>
312 </tr>
313 <tr class="field"><th class="docinfo-name">Classifiers:</th><td class="field-body">Programming Language :: Python</td>
314 </tr>
315 </tbody>
316 </table>
317 <div class="abstract topic">
318 <p class="topic-title first">Abstract</p>
319 <p>This work was started as an effort to better understand the impact of
320 different Python <a class="reference" href="http://www.python.org/dev/peps/pep-0333/">pep-333</a> WSGI application profiles on server
321 performance. This is still the focus of development. This server is NOT FOR
322 PRODUCTION USE. This server implementation owes a lot to several prior
323 works:</p>
324 <ul class="simple">
325 <li>Josia Carlsons excelent <a class="reference" href="http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/440665">Asynchronous HTTP Server recipe</a>, and his <a class="reference" href="http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/442412">Simple web request benchmark</a></li>
326 <li><a class="reference" href="http://www.cherrypy.org/browser/tags/cherrypy-3.0.0/cherrypy/wsgiserver.py">CherryPy wsgiserver</a>, The standalone, threaded, wsgi implementation, provided with CherryPy 3.0</li>
327 <li>asyncore, and asyncore/chat from the Python stdlib</li>
328 </ul>
329 <p>Keep-Alive works for both HTTP/1.0 and HTTP/1.1 clients and is essential
330 for best performance.</p>
331 <p>The implementation requires Python 2.5, and (currently) linux and the
332 <cite>poll</cite> system call.</p>
333 <p>For documentation on using the dispatch mainloop and implementing
334 compatible dispatch targets see <a class="reference" href="doc/api/asynwsgi.dispatcher-module.html">asynwsgi.dispatcher</a> and
335 <a class="reference" href="doc/api/asynwsgi.tcpsocket-module.html">asynwsgi.tcpsocket</a></p>
336 <p>For the current server implementation see:</p>
337 <blockquote>
338 <tt class="docutils literal"><span class="pre">python</span> <span class="pre">-m</span> <span class="pre">asynwsgi.wsgiservice.server</span> <span class="pre">--help</span></tt></blockquote>
339 <p>For a minimal async http clients see:</p>
340 <pre class="literal-block">
341 python -m asynwsgi.httpclient oneraw --help
342 python -m asynwsgi.httpclient bulkfetch --help
343 </pre>
344 <p>For profiling, use the --profile option of the server above
345 in conjunction with:</p>
346 <blockquote>
347 <tt class="docutils literal"><span class="pre">python</span> <span class="pre">-m</span> <span class="pre">asynwsgi.bench.http_processing</span> <span class="pre">--help</span></tt></blockquote>
348 <p>For a means to stress test the server on a single host see:</p>
349 <pre class="literal-block">
350 python -m asynwsgi.bench.tool saturate --help
351 python -m asynwsgi.bench.tool bench --help
352 </pre>
353 <p>Both saturate and bench start a single server instance. saturate runs one
354 instance of a http_processing client while bench runs mutliple GET and POST
355 async client processes (http_processing instances with appropriate options)
356 against the same server instance.</p>
357 <p>For a means to generate and sustain a large number of pending connection
358 attempts with the server - Ie, MORE than the rate at wich the
359 server can accept those connections - see:</p>
360 <blockquote>
361 <tt class="docutils literal"><span class="pre">python</span> <span class="pre">-m</span> <span class="pre">asynwsgi.sclients.main</span> <span class="pre">--help</span></tt></blockquote>
362 <p>And take a look at the C10k site for a detailed explanation of what an
363 sclient is and what you can do with one.</p>
364 </div>
365 <blockquote id="copyright-c-2007-robin-bryce">
366 <p>Copyright (c) 2007 Robin Bryce</p>
367 <p>Permission is hereby granted, free of charge, to any person obtaining a
368 copy of this software and associated documentation files (the &quot;Software&quot;),
369 to deal in the Software without restriction, including without limitation
370 the rights to use, copy, modify, merge, publish, distribute, sublicense,
371 and/or sell copies of the Software, and to permit persons to whom the
372 Software is furnished to do so, subject to the following conditions:</p>
373 <p>The above copyright notice and this permission notice shall be included in
374 all copies or substantial portions of the Software.</p>
375 <p>THE SOFTWARE IS PROVIDED &quot;AS IS&quot;, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
376 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
377 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
378 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
379 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
380 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
381 DEALINGS IN THE SOFTWARE.</p>
382 </blockquote>
383 <div class="contents topic">
384 <p class="topic-title first"><a id="contents" name="contents">Contents</a></p>
385 <ul class="simple">
386 <li><a class="reference" href="#wsgi-implementation-status" id="id1" name="id1">wsgi implementation status</a></li>
387 </ul>
388 </div>
389 <div class="section">
390 <h1><a class="toc-backref" href="#id1" id="wsgi-implementation-status" name="wsgi-implementation-status">wsgi implementation status</a></h1>
391 <p>Certain aspects of the wsgi spec implementation may be neither complete or
392 correct. Development is currently focused on identifying how performance of
393 async servers is affected by aspects of the wsgi spec.</p>
394 <dl class="docutils">
395 <dt><tt class="docutils literal"><span class="pre">wsgi.input</span></tt>:</dt>
396 <dd><ul class="first last">
397 <li><p class="first">For Transfer-Encoding:chunks: read, readline etc are NOT SUPPORTED. The
398 only means to process the input is via the __iter__ method. See
399 <tt class="docutils literal"><span class="pre">asynwsgi.wsgiservice.server:wsgi_file_uploader</span></tt> for an example. The
400 yield pattern for __iter__ is also somewhat specialised. It is:</p>
401 <pre class="literal-block">
402 [chunksz, datafirst] [data]* [chunksz, datafirst] [data]* ... [0 '']
403 </pre>
404 <p>This pattern enables the server to deal with chunk boundaries on behalf of
405 your application with out incurring excessive buffering overhead.</p>
406 <p>The iterator will raise StopIteration <em>after</em> it has yielded the
407 terminating chunk. The future plan is to incorporate trailer headers into
408 this yield pattern but presently any trailer headers are silently droped
409 on the floor (this is actualy RFC 2616 compliant although not very
410 friendly).</p>
411 <p>Your application iterable is GUARANTEED only to be resumed if input.next()
412 has some data ready (either [chunksz, datafirst] or some/all of [data]*).
413 If on a subsequent iteration the server detects EAGAIN/EWOULDBLOCK then
414 input.next() will return <tt class="docutils literal"><span class="pre">wsgi.input_sentinel</span></tt>. If your application
415 sees this value it should simply yield it back to the server. So the
416 simplest idiom is:</p>
417 <pre class="literal-block">
418 uploaded = cStringIO.StringIO()
419 content_length = 0
420 for v in iter(environ['wsgi.input']):
421     if d is environ['wsgi.input_sentinel']):
422         yield d
423         continue
424     if not isinstance(d, str):
425         chunksz, d = d
426         content_length += chunksz
427     uploaded.write(d)
428 assert len(uploaded.getvalue()) == content_length
429 </pre>
430 <p>Note: wsgiservice.server has an example application interable that handles
431 POST with transfercoding:chunks and you can test this using:</p>
432 <pre class="literal-block">
433 python -m asynwsg.bench.http_processing --synthesize-post=NCHUNKS\
434 --chunksz=NBYTES http://localhost:8080/uploader/
435 </pre>
436 </li>
437 <li><p class="first">POST suport where Transfer-Encoding header is absent or is set to 'none'
438 At present the server collects all the data into a cStringIO.StringIO
439 instance and does not invoke the application until <em>all</em> input has been
440 collected. (AND this is not particularly well tested at present)</p>
441 </li>
442 </ul>
443 </dd>
444 </dl>
445 </div>
446 </div>
447 </body>
448 </html>
Note: See TracBrowser for help on using the browser.