对于我的应用程序,我需要组织一个循环(环)队列。这意味着任何已处理的消息都会立即进入队列末尾以进行连续处理。
例如:
A
,B
,C
。A
。B
,C
,A
。 2和3应该原子地进行。所以我们永远不会丢失A
或任何其他消息。
另一个要求是忽略重复。所以队列中应该总是有一个A
。即使发件人推送另一个A
项。 A
指的是此处消息的一些唯一(主要)密钥。
我寻找使用Azure Service Bus,但我找不到如何满足这两个要求。是否可以使用Service Bus实现方案?如果没有,最好的选择是什么?
答案 0 :(得分:2)
这种队列可以通过Service Bus 会话实现。会话提供“分组依据”机制,因此我们可以将唯一密钥分配给消息的SessionId
,然后在组中接收消息,忽略除第一个消息之外的组中的所有消息。
<强>实施强>
1)创建一个RequiresSession
设置为true的队列:
var queueDescription = new QueueDescription("CircularQueue")
{
RequiresSession = true,
};
await namespaceManager.CreateQueueAsync(queueDescription);
2)将消息发送到队列时,将SessionId
设置为您的唯一键值:
var message = new BrokeredMessage($"Message body")
{
MessageId = "MESSAGE_UNIQUE_KEY",
SessionId = "MESSAGE_UNIQUE_KEY"
};
await queueClient.SendAsync(message);
3)使用会话接收消息:
while (true)
{
var session = await queueClient.AcceptMessageSessionAsync(TimeSpan.FromSeconds(10));
if (session == null)
continue;
try
{
var messages = (await session.ReceiveBatchAsync(100)).ToList();
if (messages.Count == 0)
continue;
var message = messages[0];
ProcessMessage(message);
await queueClient.SendAsync(message.Clone());
await session.CompleteBatchAsync(messages.Select(msg => msg.LockToken));
}
finally
{
await session.CloseAsync();
}
}
答案 1 :(得分:0)
基于我对Azure Service Bus的了解,我相信这两个要求都可以单独实现,但我不确定它们是如何一起完成的。
消息循环
据我了解,Azure Service Bus支持First-In-First-Out (FIFO)
行为。您可以做的是以Receive and Delete
模式从队列顶部获取消息(例如A),然后将消息重新插入队列中。由于您正在创建新消息,因此它将发布到队列的末尾。
避免重复消息
Service Bus Queues有一个名为RequiresDuplicateDetection
的布尔属性,相应地设置此值将防止插入重复的消息。只需简单搜索Azure Service Bus Duplicate Detection
即可获得许多示例。