锁定服务总线队列并阻止其他人访问它

时间:2016-04-18 22:12:03

标签: c# azureservicebus microservices

我有多个队列,多个客户端将消息插入其中。

在服务器端,我有多个微服务可以访问队列并处理这些消息。我想在服务正在处理时锁定队列,以便其他服务无法在该队列上工作。

这意味着如果服务A正在处理来自队列X的消息,则在服务A处理完该消息之前,其他任何服务都不能处理来自该队列的消息。其他服务可以处理来自X以外的任何队列的消息。

有没有人知道如何锁定队列并阻止其他人访问它?最好是其他服务会收到异常或其他东西,以便他们再次尝试不同的队列。

更新

另一种方法是将队列分配给服务,并且只要服务正在处理队列,就不应该为队列分配其他服务,直到处理完工作项。这也是不容易实现的。

5 个答案:

答案 0 :(得分:2)

您可以使用 Azure Service Bus message sessions

您队列中的所有消息都必须使用相同的 SessionId 标记。在这种情况下,当客户端收到一条消息时,它不仅会锁定这条消息,还会锁定所有具有相同 SessionId(实际上是整个队列)的消息。

答案 1 :(得分:1)

解决方案是使用Azure的redis将锁存储在内存中,并使用redis商店管理这些锁的微服务。

lock()unlock()操作是原子操作,锁具有TTL,因此队列不会无限期锁定。

答案 2 :(得分:1)

有几种内置的方法可以做到这一点。如果您只有一名工作人员,则可以设置MessageOptions.MaxConcurrentCalls = 1

如果您有多个,则可以使用Singleton属性。这使您可以选择在侦听器模式或功能模式下进行设置。前者给出了您要求的行为,即串行处理的FIFO队列。后者允许您更精细地锁定,因此您可以专门锁定关键部分,确保一致性,同时允许更高的吞吐量,但不一定保留订单

我的猜测他们已经实现了类似于Redis方法的单例属性,因此性能应该是等效的。虽然我没有做过测试。

答案 3 :(得分:0)

Azure Service Bus是一个拥有竞争消费者的经纪人。您无法使用服务的所有实例正在使用的常规队列提出要求。

答案 4 :(得分:0)

将工作项放入关系数据库。您仍然可以使用队列将工作推送到工作人员,但队列项现在可以为空。当工人收到他知道要查看数据库的项目时。消息的内容被忽略。

这样消息是独立的和幂等的。为了排队工作,这两个属性通常必须保持。

通过这种方式,您可以更轻松地对实际上是连续的操作进行排序。您也可以使用交易。

也许你根本不需要排队。也许只有固定数量的工作人员轮询数据库才能工作。但是,这会丢失队列的自动缩放功能。