带有 Twisted 的异步 WSGI
我正在为扭曲的应用程序构建一个 Web 界面,并且希望直接使用 WSGI 而不是 twins.web(因为网站的其余部分是 WSGI,并且我已经拥有大量的 WSGI 代码库)。
我发现关于 WSGIResource 的 Twisted 文档页面 (http://twistedmatrix.com/documents/current/web/howto/web-in-60/wsgi.html) 指出: 与任何其他 WSGI 容器一样,您无法在 WSGI 应用程序中执行任何异步操作,即使这是一个 Twisted WSGI 容器。
这一定是真的吗?在 WSGI 中是否有一些不那么 hacky 的方法来进行 twinsed.web 风格的异步 Web 请求处理 - 也许作为另一个自由软件项目的一部分?假设没有,我的计划是让 WSGI 线程在反应器线程中执行异步工作,并通过轮询进行阻塞,直到数据可用。这并不漂亮。
如果有一种相当简单的方式来异步处理 Twisted 中的 WSGI 请求,我很想听听。
I'm building a web interface for a twisted application and would like to use WSGI rather than twisted.web directly (since the rest of the website is WSGI and I already have a substantial WSGI codebase).
The Twisted documentation page I found about WSGIResource (http://twistedmatrix.com/documents/current/web/howto/web-in-60/wsgi.html) states:
Like any other WSGI container, you can't do anything asynchronous in your WSGI applications, even though this is a Twisted WSGI container.
Does this have to be true? Is there some less-than-hacky way of doing twisted.web style asynchronous web request handling in WSGI - perhaps as part of another free software project? Supposing there isn't, my plan is to have WSGI threads do their asynchronous work in the reactor thread and block by polling until the data is available. It's not pretty.
If there's a reasonably uncomplicated way of asynchronously handling WSGI requests in twisted I'd love to hear it.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
为什么要使用 WSGI 并做异步事情? WSGI 的好处是您可以将应用程序部署在任何 WSGI 容器上。如果您开始使用 Twisted API 执行异步操作,那么您只能将应用程序部署在 Twisted 的 WSGI 容器中。
您可能应该只使用 Twisted Web,而不使用 WSGI 作为异步代码。
Why do you want to use WSGI and do asynchronous things? The benefit of WSGI is that you can deploy your application on any WSGI container. If you start using Twisted APIs to do asynchronous things, then you can only deploy your application in Twisted's WSGI container.
You should probably just use Twisted Web without WSGI for your asynchronous code.
原则上,WSGI本质上与异步程序设计并非不兼容;事实上,PEP 333 用了相当长的篇幅来指定服务器、应用程序和中间件必须如何运行才能支持此类事情。
其核心是将一个迭代器返回到容器。每次调用异步 wsgi app_iter 时,它都会检查所有待处理的异步任务(数据库连接等),如果其中任何任务有数据,则 app_iter 会生成一些数据;否则它会产生一个空字符串。为了支持这一点,wsgi 容器除了为其负责的任何其他延迟工作提供服务之外,还需要跟踪所有正在进行的请求,并依次迭代每个请求以获取更多数据。
原则上,很少有 wsgi 应用程序或框架真正做到这一点。 wsgi 框架几乎总是会因为各种原因而阻塞;出于任何原因从磁盘读取文件或从数据库加载数据(大多数 ORM 使这成为一个很难防止的问题。)Twisted 的 wsgi 容器的运行假设是,由于某些 wsgi 应用程序会阻塞,因此也许任何 wsgi 应用程序都可能会阻塞,并且因此总是在线程中运行它们。
您可以做两件事;要么探索twisted自己的网络框架,它相当可靠;或者考虑在twisted自己的容器之外为twisted创建一个wsgi包装器。确保 wsgi 应用程序实际上是异步的当然是后者的前提条件,但 wsgi 本身非常简单,是 http 上的一个薄包装器,因此它应该很容易。
In principle, WSGI is not intrinsically incompatible with asynchronous program design; in fact, PEP 333 goes to some considerable length to specify how servers, applications and middleware must behave to support that kind of thing.
At the heart of this is returning an iterator to the container. Every time an asynchronous wsgi app_iter is invoked, it would check on all of its pending asyncronous tasks (database connections, etcetera) and if any of them have data, the app_iter yields some data; otherwise it yields an empty string. To support this, a wsgi container would need to keep track of all of the in-flight requests, and iterate each of them in turn to get more data, in addition to servicing any other deferred work that it is responsible for.
In principle, very few wsgi apps or frameworks actually do this. almost invariably, wsgi frameworks block for all sorts of reasons; reading files from disk or loading data from a database for any reason at all (Most ORM's make this a tough problem to prevent.) Twisted's wsgi container operates under the assumption that since some wsgi apps block, that perhaps any wsgi app may block, and therefore always runs them in a thread.
There are two things you can do; either explore twisted's own web framework, which is fairly solid; or consider creating a wsgi wrapper for twisted outside of twisted's own container. Making sure the wsgi app is actually asyncronous is certainly a precondition of the latter, but wsgi itself is pretty simple, a thin wrapper over http, and so it should be easy enough.