在 Twisted App 中持久化数据
Posted
技术标签:
【中文标题】在 Twisted App 中持久化数据【英文标题】:Persisting Data in a Twisted App 【发布时间】:2014-04-06 16:49:39 【问题描述】:我正在尝试了解如何在 Twisted 应用程序中保存数据。假设我决定编写一个 Twisted 服务器:
-
接受入站 SMTP 请求
将消息发送到第 3 方系统进行修改
将修改后的消息中继到其目的地
一个典型的 Twisted 教程会让你使用 Deferreds 和回调来构建这个应用程序,大致如下:
工厂处理入站请求 每次收到完整的电子邮件时,都会向远程消息处理器发送一个调用,返回一个延迟 如果在 modify 调用中出现任何问题,请添加替换原始消息的 errback。 添加回调以将消息发送给收件人,收件人再次返回延迟。 真正的服务器会添加/包含额外的调用/errbacks 以重试或通知发件人或诸如此类。再次为简单起见,假设我们认为这是可以接受的工作量并且只记录错误。当然,如果发生崩溃/重启/其他情况,这不会保留任何数据。我知道一个解决方案涉及第 3 方持久数据存储(经常提到 RabbitMQ),并且可能会想出十几种随机方法来实现结果。
但是,我想有几种方法在 Twisted 应用中效果最好。他们看起来怎么样?他们如何存储(并在发生崩溃时恢复)进程中消息?
【问题讨论】:
如果您提供一些您编写的简短示例代码 (sscce.org),并询问它有什么问题,而不仅仅是“您将如何做所有这些事情”,将会很有帮助? 我绝对没有问如何实现所有这些东西。我继续阅读教程,并且(除了术语)伪代码几乎已经死了。例如,this tutorial 遵循几乎完全相同的逻辑流程。如果您将 main 中的调用替换为 SMTP 工厂(类似于 this setup)并添加 replacepoem_done 为 async relay_message,您将拥有一个工作服务器。 问题是在这样的系统中更高级别的“如何持久化数据”(即提供交付可靠性)。我认识到答案可能是使用不同的架构(即用消息代理代替回调链),这就是为什么我以更笼统的“有没有更好的方法”结束。 【参考方案1】:如果您发现了这个问题,您可能已经知道 Twisted 是基于事件的。这听起来很简单,但答案中“最难”的部分是让持久性平台在我们需要的时候生成我们需要的事件。当然,您可以将数据保存在数据库或消息队列中,但某些平台不会自然生成事件。例如:
ZeroMQ 有(或至少有)no callback 用于新数据。它的持久性也相对较差。在其他情况下,事件很容易,但可靠性是一个问题:
pgSQL 可以配置为使用 triggers 生成事件,但它们是一次性的,因此您无法恢复不完整的事件隧道尽头的光似乎有点像 RabbitMQ。
RabbitMQ 可以persist 数据库中的消息在崩溃中幸免于难 我们可以在两条腿(传入 SMTP 到 RabbitMQ 和 RabbitMQ 到传出 SMTP)上使用确认来确保应用程序是可靠的。重要的是,RabbitMQ 支持acknowledgements。 最后,一些 RabbitMQ 客户端提供了完整的异步支持(参见例如 pika、txampq 和 puka)RabbitMQ 客户端为我们提供一个基于事件的接口就足够了。
然而,在更理论的层面上,情况并非如此。事实上,尽管有上面的“通知”问题,ZeroMQ 有一个event-based client。即使我们的软件优雅地基于事件,我们也会遇到不是这样的系统。在这些情况下,我们别无选择,只能求助于polling。原则上,如果不是在实践中,我们只是向消息提供者查询消息。当我们耗尽当前队列时(如果没有消息则立即),我们使用callLater 命令在未来再次检查。它可能会让人觉得反模式,但它(无论如何据我所知)是处理这种特殊情况的正确方法。
【讨论】:
以上是关于在 Twisted App 中持久化数据的主要内容,如果未能解决你的问题,请参考以下文章