Phillip J. Eby | 16 Sep 01:12 2004

Re: WSGI woes

At 06:48 PM 9/15/04 -0400, Peter Hunt wrote:
>It looks like WSGI is not well received over at twisted.web.
>
>http://twistedmatrix.com/pipermail/twisted-web/2004-September/000644.html

Excerpting from that post:

"""The WSGI spec is unsuitable for use with asynchronous servers and
applications. Basically, once the application callable returns, the
server (or "gateway" as wsgi calls it) must consider the page finished
rendering."""

This is incorrect.  Here is a simple WSGI application that demonstrates 
yielding 50 data blocks for transmission *after* the "application callable 
returns".

     def an_application(environ, start_response):
         start_response("200 OK", [('Content-Type','text/plain')])
         for i in range(1,51):
             yield "Block %d" % i

This has been a valid WSGI application since the August 8th posting of the 
WSGI pre-PEP.

It may be, however, that Mr. Preston means that applications which want to 
use 'write()' or a similar push-oriented approach to produce data cannot do 
so after the application returns.  If so, we should discuss that use case 
further, preferably on the Web-SIG.

>I thought the blocking call was handled by the iterator, but maybe I'm wrong.
(Continue reading)

Donovan Preston | 16 Sep 07:13 2004

Re: [Twisted-web] Re: WSGI woes


On Sep 15, 2004, at 7:12 PM, Phillip J. Eby wrote:

> At 06:48 PM 9/15/04 -0400, Peter Hunt wrote:
>> It looks like WSGI is not well received over at twisted.web.
>>
>> http://twistedmatrix.com/pipermail/twisted-web/2004-September/ 
>> 000644.html
>
> Excerpting from that post:
>
> """The WSGI spec is unsuitable for use with asynchronous servers and
> applications. Basically, once the application callable returns, the
> server (or "gateway" as wsgi calls it) must consider the page finished
> rendering."""
>
> This is incorrect.

As I said in my original post, I hadn't mentioned anything about this  
yet because I didn't have a solution or proposal to fix the problem,  
which I maintain remains. I will attempt to suggest solutions, but I am  
unsure whether they will work or make sense in all environments. Allow  
me to explain:

>   Here is a simple WSGI application that demonstrates yielding 50 data  
> blocks for transmission *after* the "application callable returns".
>
>     def an_application(environ, start_response):
>         start_response("200 OK", [('Content-Type','text/plain')])
>         for i in range(1,51):
(Continue reading)

Phillip J. Eby | 16 Sep 08:37 2004

Re: [Twisted-web] Re: WSGI woes

At 01:13 AM 9/16/04 -0400, Donovan Preston wrote:

>On Sep 15, 2004, at 7:12 PM, Phillip J. Eby wrote:
>
>>At 06:48 PM 9/15/04 -0400, Peter Hunt wrote:
>>>It looks like WSGI is not well received over at twisted.web.
>>>
>>>http://twistedmatrix.com/pipermail/twisted-web/2004-September/ 000644.html
>>
>>Excerpting from that post:
>>
>>"""The WSGI spec is unsuitable for use with asynchronous servers and
>>applications. Basically, once the application callable returns, the
>>server (or "gateway" as wsgi calls it) must consider the page finished
>>rendering."""
>>
>>This is incorrect.
>
>As I said in my original post, I hadn't mentioned anything about this
>yet because I didn't have a solution or proposal to fix the problem,
>which I maintain remains.

Reading the rest of your post, I see that you are actually addressing the 
issue of asynchronous *applications*, and I have only been addressing 
asynchronous *servers* in the spec to date.  (Technically "half-async" 
servers, since to be properly portable, a WSGI server *must* support 
synchronous applications, and therefore an async WSGI server must have a 
thread pool for running applications, even if it contains only one thread.)

However, I'm not certain that it's actually possible to support *portable* 
(Continue reading)

Alan Kennedy | 16 Sep 16:59 2004

Re: [Twisted-web] Re: WSGI woes

[Phillip J. Eby]
 > However, an asynchronous server isn't going to sit there in a loop
 > calling next()!  Presumably, it's going to wait until the previous
 > string gets sent to the client, before calling next() again.  And,
 > it's presumably going to round-robin the active iterables through the
 > threadpool, so that it doesn't keep blocking on iterables that aren't
 > likely to have any data to produce as yet.
 >
 > Yes, this arrangement can still block threads sometimes, if there are
 > only a few iterables active and they are waiting for some very slow
 > async I/O.  But the frequency of such blockages can be further reduced
 > with a couple of extensions.  Suppose there was an
 > 'environ["async.sleep"]' and 'environ["async.wake"]'.  A call to
 > 'sleep' would mean, "don't bother iterating over me again until you
 > get a 'wake' call".

and

 > Anyway, my point here is that it's possible to get a pretty decent
 > setup for async applications, without any need to actually modify the
 > base WSGI spec.  And, if you add some optional extensions, you can get
 > an even smoother setup for async I/O.
 >
 > Finally, I'm open to trying to define the 'sleep/wake' facilities as
 > "standard options" in WSGI, as well as clarifying the middleware
 > control flow to support this better.

What would be really nice would be if there were some way for the 
application to return, to event-based servers or gateways, an object 
that could be included in the server's event loop, e.g. its select/poll 
(Continue reading)

Phillip J. Eby | 16 Sep 17:22 2004

Re: [Twisted-web] Re: WSGI woes

At 03:59 PM 9/16/04 +0100, Alan Kennedy wrote:
>And, of course, that's what we're really discussing here: server 
>scheduling, and how servers ensure that application output gets 
>transmitted to clients with maximum efficiency and timeliness. IMHO, 
>asynchronous server scheduling algorithms and concerns have no place in 
>core WSGI, although a well-designed optional extension to support effiency 
>might have a nice unification effect on python asynchronous server 
>architectures.

Right.  I'd encourage people to experiment with async extensions like my 
sleep/wake idea, and if there's sufficient consensus we could add a 
"standard extension" to the spec.  But I don't want to disturb the 
write()+iterable model, since that allows middleware to be mostly oblivious 
to the sync/async issue, and only apps or servers that care have to deal 
with it.  While asynchronous servers are fairly common, most existing 
asynchronous applications are going to be tied to a particular async server 
architecture no matter what we do in WSGI.

_______________________________________________
Web-SIG mailing list
Web-SIG@...
Web SIG: http://www.python.org/sigs/web-sig
Unsubscribe: http://mail.python.org/mailman/options/web-sig/gcpw-web-sig%40m.gmane.org

Alan Kennedy | 16 Sep 18:45 2004

Re: [Twisted-web] Re: WSGI woes

[Phillip J. Eby]
 > I'd encourage people to experiment with async extensions like my
 > sleep/wake idea,

Actually, the more I think about it, the more I like your idea.

My solution of using a thread-safe condition variable as an optional 
attribute of application return objects is too heavyweight. Whereas your 
solution can be implement with complexity relative to the server. For 
example, on a single-process server, wsgi.sleep could be defined like this

def sleep():
	# return a closure wrapping a method which sets a simple binary

whereas a threaded server might use

import threading

def sleep():
	# return a closure wrapping a threading.Condition().set()

Also, having the wrapper in the environment means that its meaning can 
be changed by middleware.

The only thing I disagree on are the names "sleep" and "wake", which 
IMHO come with too many semantic hangovers from the threading world. 
When an application calls wsgi.sleep(), it's not really sleeping, it's 
just declaring that it currently has no output: a call to its iterator 
will succeed, but the returned value will be an empty string.

(Continue reading)

Phillip J. Eby | 16 Sep 19:41 2004

Re: [Twisted-web] Re: WSGI woes

At 05:45 PM 9/16/04 +0100, Alan Kennedy wrote:
>The only thing I disagree on are the names "sleep" and "wake", which IMHO 
>come with too many semantic hangovers from the threading world. When an 
>application calls wsgi.sleep(), it's not really sleeping, it's just 
>declaring that it currently has no output: a call to its iterator will 
>succeed, but the returned value will be an empty string.
>
>So basically, WSGI is providing an on/off indicator for every instance of 
>a middleware stack, which indicates to the server if there is currently 
>output available.

Well, I'm proposing it as an optional extension, not a required 
feature.  And, I think I'd like to streamline it to a single 
'wsgi.pause_output' function, e.g.:

     resume = environ['wsgi.pause_output']()

Where 'resume' is then a callback function that can be invoked to resume 
iteration.  This keeps it to a single extension key, helps ensure the 
correct sequence of actions, and makes it easier to implement in some 
cases, while not making other cases any harder.

>In an asynchronous situation, the application cannot simply do a blocking 
>read on the input: that will tie up the server thread.

What do you mean by "server thread"?  A truly asynchronous server (one 
using "no threads") cannot serve multiple WSGI requests simultaneously.  In 
the general case, a WSGI server can only serve as many requests 
simultaneously as it has available threads for.  However, WSGI applications 
that use iteration in place of 'write()' can sometimes be run with fewer 
(Continue reading)

Alan Kennedy | 16 Sep 21:29 2004

Re: [Twisted-web] Re: WSGI woes

[Alan Kennedy]
 >> In an asynchronous situation, the application cannot simply do a
 >> blocking read on the input: that will tie up the server thread.

[Phillip J. Eby]
 > What do you mean by "server thread"?  A truly asynchronous server (one
 > using "no threads") cannot serve multiple WSGI requests
 > simultaneously.  In the general case, a WSGI server can only serve as
 > many requests simultaneously as it has available threads for.

Sorry, I should have paid more attention to phrasing in this context.

By  "server thread" I mean the thread of execution that is running the 
select/poll operation in the server (which needs at least *one* thread). 
If the application did a blocking read of the input running in a simple, 
single-threaded asyncore-style server, that single thread would block, 
holding up event processing.

[Phillip J. Eby]
 >
 > [About asynchronous input handlers]
 >
 > Such a wrapper would basically be just a function returning an
 > iterator, with a bunch of pausing logic and a queue to communicate
 > with the actual asynchronous app.  And, such wrappers should only
 > need to be written once for each asynchronous API, which as a
 > practical matter probably means only Twisted, anyway, as (IMO) it has
 > no real competitors in the Python async framework space.

I see the need for returning an iterator: the application processing the 
(Continue reading)

Phillip J. Eby | 16 Sep 22:08 2004

Re: [Twisted-web] Re: WSGI woes

At 08:29 PM 9/16/04 +0100, Alan Kennedy wrote:
>[Alan Kennedy]
> >> In an asynchronous situation, the application cannot simply do a
> >> blocking read on the input: that will tie up the server thread.
>
>[Phillip J. Eby]
> > What do you mean by "server thread"?  A truly asynchronous server (one
> > using "no threads") cannot serve multiple WSGI requests
> > simultaneously.  In the general case, a WSGI server can only serve as
> > many requests simultaneously as it has available threads for.
>
>Sorry, I should have paid more attention to phrasing in this context.
>
>By  "server thread" I mean the thread of execution that is running the 
>select/poll operation in the server (which needs at least *one* thread). 
>If the application did a blocking read of the input running in a simple, 
>single-threaded asyncore-style server, that single thread would block, 
>holding up event processing.

Right, which is (one reason) why a WSGI server can in the general case only 
serve as many WSGI requests simultaneously as it has available threads for, 
although it's possible to improve on that worst-case condition by 
appropriate use of iterators.

>But I don't see the need for pausing logic or queues? Why can't the server 
>simply call directly into the application, e.g. using a "process_input" 
>method, in effect saying "you have some input ready".
>
>And I'm not sure I see the need for the application to check that the 
>wsgi.input hasn't been replaced: if there were middleware further down 
(Continue reading)

Alan Kennedy | 16 Sep 23:41 2004

Re: [Twisted-web] Re: WSGI woes

[Alan Kennedy]
 >> I suppose I'm talking about the server "pushing" the input through
 >> the middleware stack, whereas you're talking about the application at
 >> the stop of the stack "pulling" the data up through the stack. Is
 >> that right?

[Phillip J. Eby]
 > That's correct, and that's what I'm trying to avoid if at all
 > possible, because it enormously complicates middleware, to the sole
 > benefit of asynchronous apps -- that mostly aren't going to be
 > portable anyway.

Hmmm. Perhaps I'll resort to explaining my idea through code rather than 
text. Here is my take on a putative blocking *and* asynchronous rot-13 
stream encoder.

But before showing you the blocking and async one, I want to show what I 
think the blocking one would look like

class blocking_rot13_streamer:

   def __init__(self, environ, start_response):
     self.in_stream = environ['wsgi.input']
     start_response("200 OK", [('context-type', 'text/plain-rot13')])

   def __iter__(self):
     return self

   def next(self):
     try:
(Continue reading)

Alan Kennedy | 17 Sep 00:12 2004

Re: [Twisted-web] Re: WSGI woes

[Alan Kennedy]
> Though I suppose having the top 
> component pulling input from an iterator chain mirrors nicely the 
> situation where the server pulls output from an iterator chain.

Which also means that the top component must be prepared to receive "" 
from the component below it in the input chain.

Say for example that the headers for a new chunk body arrive on the 
client socket, but not a chunk-encoded body, yet.

The top iterator, e.g. the uploaded-file processor, pulls data from the 
component below it, which is say the dechunker. The dechunker will read 
the headers and get the relevant metadata for the chunk. But since there 
is no actual data available now, it must yield "" to the next component up.

I was wondering if we might need to mirror the pause/resume facility on 
the input stream. But it's not a required, because the application is 
getting a callback directly from the server when there is data 
available. It's just that the data on socket that gave rise to the 
notification may not translate to actual data for the called application.

Regards,

Alan.

_______________________________________________
Web-SIG mailing list
Web-SIG@...
Web SIG: http://www.python.org/sigs/web-sig
(Continue reading)

Phillip J. Eby | 17 Sep 00:37 2004

Re: [Twisted-web] Re: WSGI woes

At 10:41 PM 9/16/04 +0100, Alan Kennedy wrote:

>In this way, there could be a middleware component below the 
>rot13_streamer in the stack that, say, does chunked_transfer encoding and 
>decoding. It would be the same in form as the above, except that it would

FYI, middleware and apps are now banned from dealing in any kind of 
transfer-encodings, per James' very valuable input on that subject.  Like 
connection properties, these should be the exclusive province of the actual 
web server.

>1. Change the environ entry for 'wsgi.async_input_handler' to be its own 
>callable that records the callback for the next layer up in the stack, the 
>rot13_streamer.input_handler.

This would lead to the unacceptable situation of every middleware component 
having to know in principle about extensions.  The "Server Extension APIs" 
section of the PEP demands that any "bypass" API verify replacement for 
this very reason.

>I think that this proposed approach is clean, and not overly complex for 
>async or blocking programmers to handle.

Unless of course they're writing middleware that does something with the input.

>But I think we do have to cleanly separate the two. I think there are 
>problems associated with trying to run *all* components seamlessly across 
>async or blocking servers. I think that middleware components that are 
>always going to behave correctly in an async situation will have to be 
>designed like that from the ground up. It's dangerous to take components 
(Continue reading)

Phillip J. Eby | 17 Sep 00:59 2004

Re: [Twisted-web] Re: WSGI woes

At 06:37 PM 9/16/04 -0400, Phillip J. Eby wrote:
>Not entirely, actually.  For my approach to really work, the middleware 
>would have to be guaranteed to return something from read(), as long as 
>the parent's read() returns something.  Otherwise, the resumption would 
>block, unless the middleware were much smarter.  I've got to think about 
>it some more, because right now I'm still not happy with the specifics of 
>any of the proposals for pausing and resuming output.

Aha!  There's the problem.  The 'read()' protocol is what's wrong.  If 
'wsgi.input' were an *iterator* instead of a file-like object, it would be 
fairly straightforward for async servers to implement "would block" reads 
as yielding empty strings.  And, servers could actually support streaming 
input via chunked encoding, because they could just yield blocks once 
they've arrived.

The downside to making 'wsgi.input' an iterator is that you lose control 
over how much data to read at a time: the upstream server or middleware 
determines how much data you get.  But, it's quite possible to make a 
buffering, file-like wrapper over such an iterator, if that's what you 
really need, and your code is synchronous.  (This will slightly increase 
the coding burden for interfacing applications and frameworks that expect 
to have a readable stream for CGI input.)  For asynchronous code, you're 
just going to invoke some sort of callback with each block, and it's the 
callback's job to deal with it.

What does everybody think?  If combined with a "pause iterating me until 
there's input data available" extension API, this would let the input 
stream be non-blocking, and solve the chunked-encoding input issue all in 
one change to the protocol.  Or am I missing something here?

(Continue reading)

Alan Kennedy | 17 Sep 01:04 2004

Re: [Twisted-web] Re: WSGI woes

[Alan Kennedy]
>> When I described your approach as "pulling data up the stack", I saw a 
>> bigger difference between the two approaches. I'm thinking now that 
>> there is little difference between our proposals, except that in mine 
>> it's the bottom component that gets notified of the input by the 
>> server, and in yours it's the top component. Though I suppose having 
>> the top component pulling input from an iterator chain mirrors nicely 
>> the situation where the server pulls output from an iterator chain.

[Phillip J. Eby]
> Actually, I'm saying you pull data *down* the stack.  The bottom-most 
> application iterator calls 'read()' on an input stream provided by a 
> parent middleware component, which then calls read on a higher-level 
> component, and so on.

Hmm. That only makes sense to me if your stacks grow downwards :-)

In my mental picture, stacks grow upwards. The server is level ground, 
and each middleware component is placed on top of the other, with the 
"most wrapped" component at the top.

So to me what your description above says is that the component closest 
to the server is the one that gets to see the input last, after all the 
more wrapped components, with the most wrapped component getting first 
dibs on the input. Which doesn't make sense to me.

Perhaps your stacks grow downwards?

Anyway, I *think* we're talking about the same thing.

(Continue reading)

Phillip J. Eby | 17 Sep 01:08 2004

Re: [Twisted-web] Re: WSGI woes

At 12:04 AM 9/17/04 +0100, Alan Kennedy wrote:
>Which leads onto the next question: Why not insist on an iterable for the 
>input stream as well as the output stream. It appears to me that there 
>should be symmetry between the output write()/iterable split and the input 
>read()/iterable split.

Looks like you had the same "aha" as I just did a few minutes ago, so I'll 
take your comment as a +1 on that approach.  :)

_______________________________________________
Web-SIG mailing list
Web-SIG@...
Web SIG: http://www.python.org/sigs/web-sig
Unsubscribe: http://mail.python.org/mailman/options/web-sig/gcpw-web-sig%40m.gmane.org

Donovan Preston | 17 Sep 02:39 2004

Re: [Twisted-web] Re: WSGI woes


On Sep 16, 2004, at 1:41 PM, Phillip J. Eby wrote:

>     resume = environ['wsgi.pause_output']()
>
> Where 'resume' is then a callback function that can be invoked to 
> resume iteration.  This keeps it to a single extension key, helps 
> ensure the correct sequence of actions, and makes it easier to 
> implement in some cases, while not making other cases any harder.

Well, I guess I sparked some discussion here. Great! I am +1 on the 
above construct, calling pause_output and yielding an empty string. I'm 
glad this technique came up because I hadn't paid enough attention to 
the environ dict and how it could be used to do something like this.

I think with servers providing a pause_output callable like this, 
asynchronous applications will be possible and the isolation between 
the layers can be preserved. I am going to try writing some code using 
this construct and provide further feedback after I do.

dp

_______________________________________________
Web-SIG mailing list
Web-SIG@...
Web SIG: http://www.python.org/sigs/web-sig
Unsubscribe: http://mail.python.org/mailman/options/web-sig/gcpw-web-sig%40m.gmane.org

Phillip J. Eby | 17 Sep 03:02 2004

Re: [Twisted-web] Re: WSGI woes

At 08:39 PM 9/16/04 -0400, Donovan Preston wrote:

>On Sep 16, 2004, at 1:41 PM, Phillip J. Eby wrote:
>
>>     resume = environ['wsgi.pause_output']()
>>
>>Where 'resume' is then a callback function that can be invoked to resume 
>>iteration.  This keeps it to a single extension key, helps ensure the 
>>correct sequence of actions, and makes it easier to implement in some 
>>cases, while not making other cases any harder.
>
>Well, I guess I sparked some discussion here. Great! I am +1 on the above 
>construct, calling pause_output and yielding an empty string. I'm glad 
>this technique came up because I hadn't paid enough attention to the 
>environ dict and how it could be used to do something like this.
>
>I think with servers providing a pause_output callable like this, 
>asynchronous applications will be possible and the isolation between the 
>layers can be preserved. I am going to try writing some code using this 
>construct and provide further feedback after I do.

Keep in mind that this is proposed as an optional construct, so if the 
server doesn't provide it, the application iterable will either need to be 
okay being next()-ed repeatedly, or else "go synchronous" and either do the 
work in-thread or block on a queue from the I/O thread.

And, until I get some feedback on the other part of this (making 
'wsgi.input' an iterator too, and having a way to "pause until input"), I'm 
not ready to add this to the PEP as 'wsgi.pause_output'.  But again, 
nothing stops a server from providing e.g. a 'twisted.pause_output' 
(Continue reading)

Phillip J. Eby | 23 Sep 03:01 2004

Re: [Twisted-web] Re: WSGI woes

At 08:39 PM 9/16/04 -0400, Donovan Preston wrote:

>On Sep 16, 2004, at 1:41 PM, Phillip J. Eby wrote:
>
>>     resume = environ['wsgi.pause_output']()
>>
>>Where 'resume' is then a callback function that can be invoked to resume 
>>iteration.  This keeps it to a single extension key, helps ensure the 
>>correct sequence of actions, and makes it easier to implement in some 
>>cases, while not making other cases any harder.
>
>Well, I guess I sparked some discussion here. Great! I am +1 on the above 
>construct, calling pause_output and yielding an empty string. I'm glad 
>this technique came up because I hadn't paid enough attention to the 
>environ dict and how it could be used to do something like this.
>
>I think with servers providing a pause_output callable like this, 
>asynchronous applications will be possible and the isolation between the 
>layers can be preserved. I am going to try writing some code using this 
>construct and provide further feedback after I do.

So...  how'd it work out?  :)

_______________________________________________
Web-SIG mailing list
Web-SIG@...
Web SIG: http://www.python.org/sigs/web-sig
Unsubscribe: http://mail.python.org/mailman/options/web-sig/gcpw-web-sig%40m.gmane.org

(Continue reading)

James Y Knight | 16 Sep 17:14 2004
Picon

Re: Re: [Web-SIG] WSGI woes

On Sep 16, 2004, at 2:37 AM, Phillip J. Eby wrote:
> Reading the rest of your post, I see that you are actually addressing 
> the issue of asynchronous *applications*, and I have only been 
> addressing asynchronous *servers* in the spec to date.  (Technically 
> "half-async" servers, since to be properly portable, a WSGI server 
> *must* support synchronous applications, and therefore an async WSGI 
> server must have a thread pool for running applications, even if it 
> contains only one thread.)

 From the point of view of Twisted as the server, running a WSGI 
application, the big question is:
Can you (as a host server) assume WSGI applications will run 
non-blocking?

The answer is clearly No and I don't imagine that would change. (well, 
right now it's currently not even possible to write a non-blocking WSGI 
application, but even if it were..). The only sensible thing is to 
assume a WSGI app will block for some arbitrarily long amount of time. 
Therefore, the only solution is to spawn threads for simultaneous WSGI 
applications.

This is not the Twisted Way, BUT, it is very clearly doable in Twisted, 
so it's not like the WSGI spec is unimplementable. For some people it 
might be perfectly acceptable to have an async base Twisted webserver 
running multi-threaded user code. I do not care much about doing that 
myself, but it should be fairly easy to write the WSGI layer to make 
this happen, and I would be happy for someone else to do so and 
contribute it to twisted.

So, basically, I concur: WSGI is implementable for async servers, but 
(Continue reading)

Phillip J. Eby | 16 Sep 18:18 2004

Re: [Twisted-web] Re: WSGI woes

At 11:14 AM 9/16/04 -0400, James Y Knight wrote:
>On Sep 16, 2004, at 2:37 AM, Phillip J. Eby wrote:
>>Reading the rest of your post, I see that you are actually addressing the 
>>issue of asynchronous *applications*, and I have only been addressing 
>>asynchronous *servers* in the spec to date.  (Technically "half-async" 
>>servers, since to be properly portable, a WSGI server *must* support 
>>synchronous applications, and therefore an async WSGI server must have a 
>>thread pool for running applications, even if it contains only one thread.)
>
> From the point of view of Twisted as the server, running a WSGI 
> application, the big question is:
>Can you (as a host server) assume WSGI applications will run non-blocking?
>
>The answer is clearly No and I don't imagine that would change.

Right, because the ability to wrap existing applications is a must, and 
most existing applications are synchronous.

>  (well, right now it's currently not even possible to write a 
> non-blocking WSGI application, but even if it were..)

That depends on what you define as "non-blocking".  :)

>The only sensible thing is to assume a WSGI app will block for some 
>arbitrarily long amount of time. Therefore, the only solution is to spawn 
>threads for simultaneous WSGI applications.

Right; this has been in the discussions of WSGI since day one, last 
December.  The assumption is that async servers would have to use a thread 
pool (e.g. via reactor.deferToThread) to run WSGI applications.  Since the 
(Continue reading)

William Dode | 16 Sep 10:58 2004
Picon

Re: [Twisted-web] Re: WSGI woes

"Phillip J. Eby" <pje@...> writes:

> At 01:13 AM 9/16/04 -0400, Donovan Preston wrote:
>
>>On Sep 15, 2004, at 7:12 PM, Phillip J. Eby wrote:
>>
>>>At 06:48 PM 9/15/04 -0400, Peter Hunt wrote:
>>>>It looks like WSGI is not well received over at twisted.web.
>>>>
>>>>http://twistedmatrix.com/pipermail/twisted-web/2004-September/ 000644.html
>>>
>>>Excerpting from that post:
>>>
>>>"""The WSGI spec is unsuitable for use with asynchronous servers and
>>>applications. Basically, once the application callable returns, the
>>>server (or "gateway" as wsgi calls it) must consider the page finished
>>>rendering."""
>>>
>>>This is incorrect.
>>
>>As I said in my original post, I hadn't mentioned anything about this
>>yet because I didn't have a solution or proposal to fix the problem,
>>which I maintain remains.
>
> Reading the rest of your post, I see that you are actually addressing
> the issue of asynchronous *applications*, and I have only been
> addressing asynchronous *servers* in the spec to date.  (Technically
> "half-async" servers, since to be properly portable, a WSGI server
> *must* support synchronous applications, and therefore an async WSGI
> server must have a thread pool for running applications, even if it
(Continue reading)

Phillip J. Eby | 16 Sep 17:27 2004

Re: [Twisted-web] Re: WSGI woes

At 10:58 AM 9/16/04 +0200, William Dode wrote:
>But it doesn't mean that i whant to run my application on any
>server. Generaly i use twisted server when i have specials need, like
>telnet, irc... So this application will not run under cgi. But i like
>to can reuse quickly somes litle cgi application under twisted.
>I need the same framework for all the servers to can share 90% of my
>api, to map the url to a resource, for session, cookies...
>
>So, i hope we can find a solution to run simple application anywhere,
>and to be open for very specific uses.

As I said, WSGI should let any WSGI application run under more 
sophisticated architectures like Twisted; it's just that an application 
that uses Twisted-specific features isn't going to be able to move to a 
server that's not Twisted-compatible.

And, if you're using Twisted-specific features in a WSGI app (as opposed to 
just writing a pure Twisted app), you'll have some additional work needed 
to deal with the asynchrony.  However, the only reason I can think of why 
you'd want to make such an application use the WSGI interface is if you 
wanted to be able to use WSGI-based middleware features.  At some point, 
that may be attractive, but I really doubt that in the short term anybody 
using Twisted-specific features in an application would want to bother with 
making it WSGI-compatible.

_______________________________________________
Web-SIG mailing list
Web-SIG@...
Web SIG: http://www.python.org/sigs/web-sig
Unsubscribe: http://mail.python.org/mailman/options/web-sig/gcpw-web-sig%40m.gmane.org
(Continue reading)

Peter Hunt | 17 Sep 01:16 2004
Picon

Re: [Twisted-web] Re: WSGI woes

Alan, that design looks okay. A bit complex, but it works well once
you sit down to look at it.

It would be nice if applications that didn't need a separate thread
didn't use one up, so performance-oriented programmers (like the
Twisted/Nevow guys) won't be able to have that excuse. Perhaps
start_response() could have a "threaded" boolean optional argument
that defaults to true which decides whether or not the iterable will
be called in a separate thread. This, of course, requires that the
application callable itself doesn't have any blocking code.

Does this requirement overcomplicate things?
_______________________________________________
Web-SIG mailing list
Web-SIG@...
Web SIG: http://www.python.org/sigs/web-sig
Unsubscribe: http://mail.python.org/mailman/options/web-sig/gcpw-web-sig%40m.gmane.org

Phillip J. Eby | 17 Sep 01:57 2004

Re: [Twisted-web] Re: WSGI woes

At 07:16 PM 9/16/04 -0400, Peter Hunt wrote:
>Alan, that design looks okay. A bit complex, but it works well once
>you sit down to look at it.
>
>It would be nice if applications that didn't need a separate thread
>didn't use one up, so performance-oriented programmers (like the
>Twisted/Nevow guys) won't be able to have that excuse. Perhaps
>start_response() could have a "threaded" boolean optional argument
>that defaults to true which decides whether or not the iterable will
>be called in a separate thread. This, of course, requires that the
>application callable itself doesn't have any blocking code.
>
>Does this requirement overcomplicate things?

Yes.  The vast majority of existing web applications are synchronous, and 
so are a significant number of Python web server environments that would 
run WSGI applications.  Therefore the WSGI "common case" is to have 
synchronous behavior, and WSGI is most efficient with either a synchronous 
server/gateway, or a "half-async" server/gateway (i.e., one that runs 
application code in a thread pool, separate from the main I/O thread.)

The few applications that can behave in a non-blocking fashion, can and 
should use the iterable interface to provide their output, producing empty 
strings when they are not yet ready to produce output.  (Plus, when such 
applications are run in a synchronous server or gateway, they might as well 
behave synchronously, since they will actually incur more overhead by 
trying to be asynchronous!)

The only scenario that isn't served by this approach is a single-threaded, 
asynchronous server with no threading capability.  However, such a server 
(Continue reading)

Peter Hunt | 17 Sep 02:37 2004
Picon

Re: [Twisted-web] Re: WSGI woes

Yes, but an async app running in an async server in a thread is
overkill, don't you think? We don't need to spawn an extra thread to
run it. I'm not talking about "possible", I'm talking about "optimal".

On Thu, 16 Sep 2004 19:57:59 -0400, Phillip J. Eby
<pje@...> wrote:
> 
> 
> At 07:16 PM 9/16/04 -0400, Peter Hunt wrote:
> >Alan, that design looks okay. A bit complex, but it works well once
> >you sit down to look at it.
> >
> >It would be nice if applications that didn't need a separate thread
> >didn't use one up, so performance-oriented programmers (like the
> >Twisted/Nevow guys) won't be able to have that excuse. Perhaps
> >start_response() could have a "threaded" boolean optional argument
> >that defaults to true which decides whether or not the iterable will
> >be called in a separate thread. This, of course, requires that the
> >application callable itself doesn't have any blocking code.
> >
> >Does this requirement overcomplicate things?
> 
> Yes.  The vast majority of existing web applications are synchronous, and
> so are a significant number of Python web server environments that would
> run WSGI applications.  Therefore the WSGI "common case" is to have
> synchronous behavior, and WSGI is most efficient with either a synchronous
> server/gateway, or a "half-async" server/gateway (i.e., one that runs
> application code in a thread pool, separate from the main I/O thread.)
> 
> The few applications that can behave in a non-blocking fashion, can and
(Continue reading)

Phillip J. Eby | 17 Sep 02:58 2004

Re: [Twisted-web] Re: WSGI woes

At 08:37 PM 9/16/04 -0400, Peter Hunt wrote:
>Yes, but an async app running in an async server in a thread is
>overkill, don't you think? We don't need to spawn an extra thread to
>run it. I'm not talking about "possible", I'm talking about "optimal".

Nothing in the spec stops an async server from providing a configuration 
option to say, "this app+middleware combination is completely non-blocking, 
so don't bother running it in a separate thread".  I've just been speaking 
about the general case, and what the server is required to do to support 
the general case of "an arbitrary WSGI application", with no additional 
information.

In the same way, nothing in the spec stops servers from providing 
per-application configuration options for any number of extended behaviors; 
WSGI is a starting point for server capabilities, not an ending point.

Still, I will admit that I tend to speak of things almost as if WSGI were 
an ending point, because I just assume we're talking about what the spec 
should or should not *require* or *forbid*.  When a use case doesn't need 
any "musts" or "must nots" added (like your use case above), I tend not to 
focus on it directly, because it seems obvious to me that anybody can add 
it on if they like, as a server-specific extension.

So, this may lead sometimes to people getting the impression WSGI doesn't 
allow a use case that in fact it does; it's just that the use case should 
be implemented using an optional extension, rather than being considered a 
common case and made into a requirement.  If I tried to enumerate every 
possible optional extension to WSGI, I'd go mad sooner than you can say 
"Content-Transfer-Encoding".  :)

(Continue reading)


Gmane