[Twisted-web] Re: [Web-SIG] WSGI woes
Phillip J. Eby
pje at telecommunity.com
Thu Sep 16 18:18:26 CEST 2004
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
point was to allow non-Twisted applications and frameworks (e.g. Zope) to
run under Twisted or any other web server, this was the only possible approach.
>So, basically, I concur: WSGI is implementable for async servers, but only
>to implement blocking applications.
If by "blocking" you mean, you can't absolutely guarantee that no operation
will tie up the current thread, then yes. If you mean "tie up the current
thread for the entire request", then no, since it's possible to pause the
output with a few minor changes to the spec.
>>However, I'm not certain that it's actually possible to support
>>*portable* asynchronous applications under WSGI, since such asynchrony
>>requires additional support such as an event loop service.
>>As a practical matter, asynchronous applications today require a toolset
>>such as Twisted or peak.events in addition to the web server, and I don't
>>really know of a way to make such applications portable across web
>>servers, since the web server might use a different toolset that insists
>>on having its own event loop. Or it might be like mod_python or CGI, and
>>not really have any meaningful way to create an event loop: it could be
>>utterly synchronous in nature and impossible to make otherwise.
>>Thus, as a practical matter, applications that make use of asynchronous
>>I/O *may* be effectively outside WSGI's scope, if they have no real
>>chance of portability. As I once said on the Web-SIG, the idea of WSGI
>>is more aimed at allowing non-Twisted apps to run under a Twisted web
>>server, than at allowing Twisted applications to run under other web
>>servers! The latter, obviously, is much more ambitious than the former.
>Yes, there is no way that I can see to make WSGI suitable for writing
>async applications without significant work. There are two obvious
>issues: the input stream only provides blocking read(), not a selectable
>fd, and there is no way to pause output.
The sleep/wake extensions I proposed would allow pausing output. I hadn't
thought about the input stream issue.
>If the write callback was extended into a write/finish callback, it
>wouldn't completely fix the second problem. Twisted would have to call the
>write() callback from its reactor loop (having no access to the original
>request thread). Especially if there is any middleware, the *write* might
>block! There's also the question of whether the write() and finish()
>methods are threadsafe or not -- would it even be safe to call from a
>separate thread from that in which the request was started?
That's one reason why sleep/wake over iterables is a better solution than
write/finish for the "pausing output" issue.
>Writing an async application *is* an interesting question, because then,
>possibly, you could take the framework half of twisted web and run it as a
>WSGI application. However, if this question is punted by WSGI (as I think
>is likely a good idea..), twisted web framework can continue to work with
>other servers by using HTTP proxying -- which is a _perfectly good_
>solution, and something major webservers already support. HTTP is a pretty
>good protocol for talking between webservers and webapps.
>Also, if WSGI becomes really popular on servers that cannot do HTTP
>proxying natively, twisted could provide a WSGI "application" that simply
>proxies the requests over a socket to a separate twisted web server
>process. This would provide essentially no advantage to HTTP proxying
>where that works, however.
No *technical* advantage, true, but if WSGI becomes a popular buzzword, the
mere existence of such a solution allows you to boast that Twisted Web can
be used with any WSGI-compliant server, as well as any server that supports
HTTP proxying, which makes it sound like you have twice as many deployment
options from a "marketecture" perspective. :)
More information about the Web-SIG