Uma*_*air 1 azureservicebus azure-servicebus-topics asp.net-core
我有一种情况,我有一个 asp.net 核心应用程序,它在启动时将订阅客户端注册到一个主题 ( IHostedService),这个订阅客户端本质上有一个回调字典,每当它检测到一个主题中的新消息时,它就需要触发一个 id(这个 id 存储在消息属性中)。这本字典存在于应用程序的整个生命周期中,并且在内存中。
在 azure 上的 asp.net 核心应用程序服务的单个实例上一切正常,一旦我扩展到 2,我注意到有时订阅中的回调没有触发。这是有道理的,因为我们现在有两个实例,每个实例都有自己的回调字典存储。
所以我更新了代码来检查订阅的id是否存在,如果不存在,则放弃消息,如果存在,则获取回调并调用它。
public async Task HandleMessage(Microsoft.Azure.ServiceBus.Message message, CancellationToken cancellationToken)
{
var queueItem = this.converter.DeserializeItem(message);
var sessionId = // get the session id from the message
if (string.IsNullOrEmpty(sessionId))
{
await this.subscriptionClient.AbandonAsync(message.SystemProperties.LockToken);
return;
}
if (!this.subscriptions.TryGetValue(sessionId, out var subscription))
{
await this.subscriptionClient.AbandonAsync(message.SystemProperties.LockToken);
return;
}
await subscription.Call(queueItem);
// subscription was found and executed. Complete message
await this.subscriptionClient.CompleteAsync(message.SystemProperties.LockToken);
}
Run Code Online (Sandbox Code Playgroud)
但是,问题仍然存在。我唯一的猜测是,在调用时AbandonAsync,同一个实例再次接收消息?
我想我真正想问的是,如果我有多个主题订阅客户端实例都指向该主题的同一个订阅者,是否所有实例都可以获得消息的副本?或者是不能保证的。
如果我有多个主题订阅客户端实例都指向该主题的同一个订阅者,是否所有实例都可以获得消息的副本?或者是不能保证的。
不。如果所有客户端都指向同一个订阅,则只有一个会收到该消息。
您遇到了与竞争消费者进行横向扩展的问题。如果您要向外扩展,您永远不知道哪个实例会选择消息。而且由于您的状态是本地的(在每个实例的内存中),这会不时失败。额外的缺点是成本。通过在“错误”实例上获取消息并放弃,您将在消息传递方面支付更高的成本。
为了解决这个问题,你要么需要一个共享的/集中的,要么围绕这个改变你的架构。
| 归档时间: |
|
| 查看次数: |
2507 次 |
| 最近记录: |