我需要在Azure上创建一些东西,以处理一组实体的传入消息流。我们将在任何时间点拥有20到2,000个实体。这些是动态创建和丢弃的。消息将使用我们的本地系统生成,并使用某种排队机制发送到Azure。每个消息将通过EntityId
属性与特定实体相关联。属于同一实体的消息必须相对于彼此按顺序处理。
同时,该解决方案必须相对于实体具有可伸缩性。如果我有1000个实体的稳定消息流,那么我希望有1000个并发执行我的逻辑。如果一个实体需要很长时间来处理其一条消息,则不得阻止任何其他实体处理其其消息。每条消息可能要花费100毫秒到10秒钟的时间进行处理(大多数情况都低于1秒),每个实体平均每秒会收到一条消息。
令人失望的是,Azure无服务器堆栈似乎没有实现此目的的任何方法。这些是我考虑过的选项及其问题:
Azure函数带有会话队列。 Azure功能可以在使用计划上作为无服务器运行,使其非常适合弹性扩展。服务总线会话提供有序交付,并且是我要求的最接近的实现。但是,Azure Functions:Support Service Bus queues and topics which use sessions中不支持它们。
Logic应用程序:通过“ Correlated in-order delivery using service bus sessions”模板可立即使用。然后,Logic App可以挂接到HTTP触发的Azure函数来处理消息。 Logic App的唯一目的是防止同时处理属于同一实体/会话的多个消息。但是,从对我的former question的评论中,我发现这也无法扩展。 Logic App每5分钟只能执行300,000个操作,触发并发限制为50,而且据说很昂贵。参见Limits and configuration information for Azure Logic Apps。
Azure事件中心。这往往是最受欢迎的选项,也是Microsoft推荐的选项。但是,事件中心最多只允许32个分区,创建时需要指定分区数量:Features and terminology in Azure Event Hubs。固定的静态分区集的这种限制违背了“无服务器”的精神。如果将并行度限制为32,则没有比在32核计算机上运行的并行应用程序更好的可伸缩性。可以通过Microsoft的支持票证将分区限制增加到超过32个,但我不想要求可扩展性超出一般用途的两个数量级。事件中心还缺少其他一些基本属性,例如最多只能交付一次。
我们可以为每个实体动态创建服务总线队列,并为其生成单例Azure函数,该函数单独绑定到该特定队列。但是,这将需要调用Azure资源管理API作为我们的操作代码的一部分,而我的印象是,并非将Azure Functions设计为以这种方式动态产生。
使用服务总线队列消息的SequenceNumber
属性对持久后备存储(例如Redis)进行乐观并发控制,以进行排序。但是,用于此目的的编程模型非常复杂且容易出错-操作需要在重试循环中执行,并且每次都要明确考虑原子性和幂等性。另外,它要求所有消息都包含完整的实体状态;否则,当我们在比赛中丢弃陈旧消息时,信息将丢失。对于我们来说,随着每次增量更改发送完整的实体快照,对于我们而言(在计算和带宽方面)将是昂贵的,因此,我们宁愿找到一种方法来允许我们按顺序处理增量消息。
对于无服务器Azure堆栈上的可伸缩数量的实体,是否有任何干净的方法来实现有序处理?