它会在下面产生一个新线程吗?如果经典 Web 服务器生成一个线程来服务 HTTP 请求并且使用 Twisted web 我必须在每次我想查询 mysql 时生成一个 Deferred() - 增益在哪里?如果它产生了一个线程,看起来它没有意义,那么它是如何实现的呢?
2 回答
正如其他人所说,aDeferred
本身只是对价值的承诺,以及价值到达时(或获取价值失败时)要做的事情的列表。
它们的工作原理是这样的:某个函数看到它想要返回的值还没有准备好。因此,它准备了一个 Deferred,然后以某种方式安排该 Deferred 在准备好后以该值被回调(“解雇”)。第二部分可能会引起您的困惑;Deferred 本身无法控制何时或如何被解雇。这是创建 Deferred 的任何人的责任。
在整个 Twisted 应用程序的上下文中,几乎所有内容都是基于事件的,并且事件由反应器管理。说你的代码 used twisted.web.client.getPage()
,所以它现在有一个 Deferred ,它将与 http fetch 的结果一起被触发。这意味着getPage()
启动了与 http 服务器的 tcp 对话,并在反应器中安装了处理程序,说“如果您在此 tcp 连接上看到任何流量,请在此协议对象上调用一个方法”。一旦 Protocol 对象看到它收到了您请求的整个页面,它就会触发您的 Deferred,然后通过该 Deferred 的回调链调用您自己的代码。
所以一切都是回调和钩子,一路下来。这就是为什么你永远不应该在 Twisted 应用程序中使用阻塞代码,除非在单独的线程上——因为它也会阻止其他所有内容被处理。
这有帮助吗?
Python 中的 ADeferred
不做任何事情,它与线程或进程或其他任何东西都没有任何关系。
它是对未来数据交付以及数据如何映射到接收回调函数的承诺的抽象。
如何 Twisted 实现异步行为在 Twisted 文档和新闻组档案中有很好的记录,简单的 Google 搜索将找到您需要的内容。它与 Deferred 的实现无关。如果您仍然不明白,您需要在另一个问题中询问具体信息,而不是在对此答案的评论中。
也就是说,就并发性而言,Twisted 已经死了,它永远不会扩展到多核处理器以及像 Erlang 这样的东西,当 Twisted 为我退出扩展时,我从 Twisted 转移到了这种东西。