首页 > 解决方案 > Elixir - 通知其他应用程序有关事件

问题描述

假设我有一个从 Internet 下载数据的系统(elixir 应用程序),然后它将解包数据(例如 gzip),解析它(例如获取一些元数据),最后将这些数据放入某个本地数据库中。之后,系统可以被其他应用程序使用(例如,他们可以从系统中查询数据)。正如我们所看到的,从开始到准备好查询数据,需要一些未定义的时间。

问题:在 Elixir(模式/行为/?)中通知其他模块(在单独的应用程序中)数据现在已在所描述的系统中准备就绪的最佳方式是什么?

标签: elixir

解决方案


您的应用程序正在做什么,并且您希望它们传递某些任务已完成的事件消息,您必须问自己您需要哪种类型的消息?

  • 没有任何保证的交付(意味着您的事件消费者应用程序不关心它是否因为任何原因而没有收到消息)
  • 有保证的交货
    • 至少一次交付(意味着事件消费者应用程序肯定会收到消息,但有时可能会收到两次)
    • 最多一次交付(意味着事件消费者应用程序将只获取每条消息一次!)

因此,如果您必须解决第一种情况,请选择:

  • 内置二郎pg2
  • 生成集群全局 OTP 进程,该进程应充当发布/订阅中介(接受订阅者,然后在发出消息时向他们发送消息)

如果您需要满足消息传递保证,那么您需要一些“后端”来保存消息,直到每个已知的消费者承认它读取/处理它。一种方法是为此编写自己的“后端”,例如使用mnesia或一些 SQL/NOSQL 数据库,然后在某个间隔查询该后端以查看是否写入了任何事件。另一种方法是使用已经久经考验的烘焙工具,例如 RabbitMQ、Kafka……如果您需要更强大的解决方案。

请注意,在消息传递方面,分布式事务很难实现。你的任务向数据库写入了一些数据,在写入数据库完成后可能会出现消息发送失败的情况,因此任务处理器可能无法向其他应用程序发送消息(这也适用于 pg2 和全局 erlang 进程,不一个保证它们一直处于运行状态),因此您需要考虑如何从此类故障中恢复。此类基础设施故障可能会丢失一小部分消息。

一个问题。如果您的消费者应用程序不时从数据库中提取新条目,是否可以?比如说,任务具有唯一的增量数字 id,那么您可以将其用作消费类应用程序中的读取“位置”,只需记下最后写入的位置。每个应用程序应在下一次读取间隔期间保持其位置。

- - 编辑 - -

在思考如何解决这个问题时,还有一件事可能会有所帮助。如果您还没有机会阅读有关 CQRS 和“事件溯源”的信息,请简单地用谷歌搜索一下,看看它是什么概念。简要介绍一下,事实的来源是事件流,而任何其他数据存储只是事件流对特定时间时刻的事件投影(某些框架或人们称之为事件日志)这有什么有趣的“ Aritechtual Approach”是您不需要分布式事务。虽然 Event Stream 的目的是在实体生命周期内存储更改(插入和更新),但为此目的构建的一些后端也可以帮助将事件推送给订阅者。我已经提到过 Kafaka,它经常被使用,事件存储

我并不是说您应该构建 CQRS 应用程序,只是尝试了解管道在这种架构中是如何组织的,我相信它会帮助您为您的案例构建可靠的管道。


推荐阅读