You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用不同接收器实例实现Azure Service Bus消息的查看与完成

Solutions for Azure Service Bus Peek/Complete Across Independent APIs

Great question—this is a super common pain point when building reliable message delivery workflows with Azure Service Bus, especially when you need to decouple the "fetch" and "confirm" steps across separate API endpoints. The singleton receiver approach works for small-scale apps but falls apart once you need horizontal scaling. Here are three practical, scalable solutions to solve this:

1. Use Session-Enabled Topics/Subscriptions

Azure Service Bus Sessions let you group related messages and ensure they're processed by the same receiver context, even across scaled-out app instances. Here's how to adapt this to your workflow:

  • Step 1: Enable sessions on your Service Bus subscription (you can do this via the Azure Portal, Azure CLI, or ARM templates).
  • Step 2: When your first API gets a client request, create a session-aware receiver for the subscription. Peek the next message, extract the SessionId from the message properties, and return both the message content and the SessionId to the client.
  • Step 3: When the client calls your second "confirm" API, they include the SessionId in the request. Your API spins up a new session-aware receiver using that same SessionId—this binds to the original session context. You can then locate the message via its sequence number from the initial peek and call Complete() on it.

Pros: No external storage needed, leverages native Service Bus features for consistency.
Cons: Requires messages to be part of a session (you can assign a unique SessionId per message if they don't naturally belong to one). You'll also need to manage session timeouts to avoid orphaned sessions.

2. Leverage Message Lock + Deferral

Instead of relying on Peek, use the native receive-with-lock mechanism combined with message deferral to decouple the fetch and complete steps:

  • Step 1: In your first API, call Receive() on the subscription (this locks the message for a configurable period, e.g., 5 minutes). Instead of returning the message directly, defer it using DeferAsync()—this moves the message to a deferred state while retaining its lock.
  • Step 2: Return the message content, the SequenceNumber of the deferred message, and the LockToken to the client.
  • Step 3: When the client confirms receipt, your second API uses the SequenceNumber to fetch the deferred message via ReceiveDeferredMessageAsync(), then calls CompleteAsync() on it.

Pros: Works without sessions, keeps all state within Service Bus.
Cons: You need to set a sufficiently long lock duration to cover the time between the client's first request and confirmation. If the lock expires before confirmation, you'll need to handle message reprocessing (consider adding a dead-letter queue for failed attempts).

3. Store Message Metadata in an External Datastore

If sessions or deferral don't fit your use case, you can persist key message details to a shared store (like Azure Redis Cache or Azure SQL Database) to bridge the two API calls:

  • Step 1: In your first API, perform a Peek() to get the message. Store critical metadata (message ID, sequence number, subscription name, namespace) in your datastore, along with a unique OperationId that you return to the client.
  • Step 2: When the client calls the confirm API with the OperationId, fetch the metadata from your datastore.
  • Step 3: Create a new receiver instance targeting the subscription, use the sequence number to locate the message, and call Complete().

Pros: Flexible, works with any message type, no Service Bus configuration changes needed.
Cons: Adds complexity with managing external storage, including handling concurrency (e.g., multiple clients trying to confirm the same message) and cleaning up stale metadata records.

Final Recommendation

If your messages can be grouped into sessions (even artificial ones), go with Solution 1—it's the most native and scalable option. If sessions aren't feasible, Solution 2 is the next best choice since it avoids external dependencies. Use Solution 3 only if you need maximum flexibility for complex workflows.

内容的提问来源于stack exchange,提问作者Akash Thambiran

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:35:47