[Web-SIG] Could WSGI handle Asynchronous response?

Donovan Preston dsposx at mac.com
Tue Jul 29 04:16:27 CEST 2008


On Jul 28, 2008, at 6:21 PM, Phillip J. Eby wrote:

> At 04:57 PM 7/28/2008 -0700, Donovan Preston wrote:
>
>> On Jul 28, 2008, at 12:52 PM, Etienne Robillard wrote:
>>
>>> On Mon, 18 Feb 2008 04:23:38 -0800 (PST)
>>> est <electronixtar at gmail.com> wrote:
>>>
>>>> I am writing a small 'comet'-like app using flup, something like
>>>> this:
>> <snip>
>>>> So is WSGI really synchronous? How can I handle asynchronous  
>>>> outputs
>>>> with flup/WSGI ?
>>
>> WSGI says that the entire body should be written by the time the wsgi
>> application returns.
>
> No, it doesn't.  It says that all your write() calls must be done by  
> then, which is not at all the same thing.  If the application  
> returns an iterator, that iterator can keep yielding outputs until  
> the (figurative) cows come home.

Hmm, I see what you are saying. I hadn't thought about returning an  
iterable instead of just using a generator. Cool.

>> So yes it is really synchronous; as Manlio
>> Perillo said in another message it is possible to abuse generators to
>> allow a wsgi application to operate in the fashion you desire, but
>> both the server and the application have to know how to do this and
>> there is no standardization yet.
>
> This is confusing asynchronous APIs, non-blocking behavior, and  
> streaming output.  A WSGI application can avoid blocking the server  
> by yielding empty strings until it is ready to produce more output.   
> (This may not provide any performance benefit over sleep() however,  
> and may in some circumstances be worse.)

You're right. But continually yielding empty strings is basically busy- 
waiting, which would result in terrible performance, as you mention.

> There is no async API that's part of WSGI itself, and it's unlikely  
> there will ever be one unless there ends up being an async API for  
> Python as well.

I know this has been discussed before on the list and I wasn't really  
paying attention enough to know what was proposed, but it seems to me  
that just having a well-defined way for the application to tell the  
server when to resume the iterable is possible. Manlio has come up  
with an API for this in his nginx mod_wsgi.

For example, something like the interface to select could be used:

def foo(env, start_response):
	my_sock = socket.socket()
	my_sock.setblocking(0)
	my_sock.connect((...))
	r, w, e = yield [[my_sock.fileno()], [], [my_sock.fileno()]]
	if e:
		...
	bytes = my_sock.recv(4096)

This requires 2.5's extended generators, but the file descriptor  
readiness lists could be put in the environ before resuming the  
iterator for people who don't want to or can't move to 2.5.

This is just an example, I think Manlio's api (which is more like poll  
if I remember correctly) is better.

Really I don't actually care, since eventlet and greenlet let me mash  
together wsgi applications written with blocking i/o style with an  
http server that does non-blocking i/o.

> (By the way, using a generator to produce streaming output is not  
> abuse: it is the *intended* use of iterables in WSGI!)

Nice.

Donovan


More information about the Web-SIG mailing list