服务总线队列、主题和订阅Service Bus queues, topics, and subscriptions

世纪互联 Azure 服务总线支持一组基于云的、面向消息的中间件技术,包括可靠的消息队列和持久的发布/订阅消息。21Vianet Azure Service Bus supports a set of cloud-based, message-oriented middleware technologies including reliable message queuing and durable publish/subscribe messaging. 这些“中转”消息传送功能可被视为分离式消息传送功能,支持使用服务总线消息传送工作负载的发布-订阅、临时分离和负载均衡方案。These "brokered" messaging capabilities can be thought of as decoupled messaging features that support publish-subscribe, temporal decoupling, and load balancing scenarios using the Service Bus messaging workload. 分离式通信具有很多优点;例如,客户端和服务器可以根据需要进行连接并以异步方式执行其操作。Decoupled communication has many advantages; for example, clients and servers can connect as needed and perform their operations in an asynchronous fashion.

构成服务总线消息传送功能核心的消息传送实体包括队列、主题/订阅、规则/操作。The messaging entities that form the core of the messaging capabilities in Service Bus are queues, topics and subscriptions, and rules/actions.

队列Queues

队列为一个或多个竞争使用方提供先入先出 (FIFO) 消息传递方式。Queues offer First In, First Out (FIFO) message delivery to one or more competing consumers. 也就是说,接收方通常会按照消息添加到队列中的顺序来接收并处理消息,并且每条消息仅由一个消息使用方接收并处理。That is, receivers typically receive and process messages in the order in which they were added to the queue, and only one message consumer receives and processes each message. 使用队列的主要优点是,实现应用程序组件的“临时分离”。A key benefit of using queues is to achieve "temporal decoupling" of application components. 换而言之,创建方(发送方)和使用方(接收方)无需同时发送和接收消息,因为消息持久存储在队列中。In other words, the producers (senders) and consumers (receivers) do not have to be sending and receiving messages at the same time, because messages are stored durably in the queue. 此外,创建方不必等待使用方的答复即可继续处理并发送更多消息。Furthermore, the producer does not have to wait for a reply from the consumer in order to continue to process and send messages.

相关的优点是“负载分级”,它允许创建方和使用方以不同速率发送和接收消息。A related benefit is "load leveling," which enables producers and consumers to send and receive messages at different rates. 在许多应用程序中,系统负载随时间而变化,而每个工作单元所需的处理时间通常为常量。In many applications, the system load varies over time; however, the processing time required for each unit of work is typically constant. 使用队列在消息创建方与使用方之间中继意味着,只需将消费应用程序预配为处理平均负载而非最大负载。Intermediating message producers and consumers with a queue means that the consuming application only has to be provisioned to be able to handle average load instead of peak load. 队列深度将随传入负载的变化而加大和减小。The depth of the queue grows and contracts as the incoming load varies. 此功能会直接根据为应用程序加载提供服务所需的基础结构的数目来节省成本。This capability directly saves money with regard to the amount of infrastructure required to service the application load. 随着负载增加,可添加更多的工作进程以从队列中读取。As the load increases, more worker processes can be added to read from the queue. 每条消息仅由一个辅助进程处理。Each message is processed by only one of the worker processes. 另外,可通过基于拉取的该负载均衡,以最合理的方式使用辅助计算机,即使这些辅助计算机具有不同的处理能力(因为它们以其最大速率拉取消息)也是如此。Furthermore, this pull-based load balancing allows for optimum use of the worker computers even if the worker computers differ with regard to processing power, as they pull messages at their own maximum rate. 此模式通常称为“使用方竞争”模式。This pattern is often termed the "competing consumer" pattern.

使用队列在消息创建方与使用方之间中继可在各组件之间提供固有的松散耦合。Using queues to intermediate between message producers and consumers provides an inherent loose coupling between the components. 由于创建方和使用方互不相识,因此,可升级使用方,不会对创建方产生任何影响。Because producers and consumers are not aware of each other, a consumer can be upgraded without having any effect on the producer.

创建队列Create queues

使用 Azure 门户PowerShellCLI资源管理器模板创建队列。You create queues using the Azure portal, PowerShell, CLI, or Resource Manager templates. 然后使用 QueueClient 对象发送和接收消息。You then send and receive messages using a QueueClient object.

若要快速了解如何创建队列,然后向/从队列发送/接收消息,请参阅每个方法的快速入门To quickly learn how to create a queue, then send and receive messages to and from the queue, see the quickstarts for each method. 有关如何使用队列的更深入教程,请参阅服务总线队列入门For a more in-depth tutorial on how to use queues, see Get started with Service Bus queues.

有关工作示例,请参阅 GitHub 上的 BasicSendReceiveUsingQueueClient 示例For a working sample, see the BasicSendReceiveUsingQueueClient sample on GitHub.

接收模式Receive modes

可以指定服务总线接收消息所用的两种不同模式:ReceiveAndDelete 或 PeekLock。You can specify two different modes in which Service Bus receives messages: ReceiveAndDelete or PeekLock. 使用 ReceiveAndDelete 模式时,接收操作是一个单一快照。即,当服务总线收到请求时,会将该消息标记为“已使用”并将其返回给应用程序。In the ReceiveAndDelete mode, the receive operation is single-shot; that is, when Service Bus receives the request, it marks the message as being consumed and returns it to the application. ReceiveAndDelete 模式是最简单的模式,最适合应用程序允许在出现故障时不处理消息的方案。ReceiveAndDelete mode is the simplest model and works best for scenarios in which the application can tolerate not processing a message if a failure occurs. 为了理解此方案,可以考虑这样一种情形:使用方发出接收请求,但在处理该请求前发生了崩溃。To understand this scenario, consider a scenario in which the consumer issues the receive request and then crashes before processing it. 由于服务总线会将消息标记为“已使用”,因此当应用程序重新启动并重新开始使用消息时,它会漏掉在发生崩溃前使用的消息。Because Service Bus marks the message as being consumed, when the application restarts and begins consuming messages again, it will have missed the message that was consumed prior to the crash.

使用 PeekLock 模式时,接收操作分成了两步,从而有可能支持无法容忍遗漏消息的应用程序。In PeekLock mode, the receive operation becomes two-stage, which makes it possible to support applications that cannot tolerate missing messages. 当服务总线收到请求时,它会找到要使用的下一个消息,将其锁定以防其他使用方接收它,并将该消息返回给应用程序。When Service Bus receives the request, it finds the next message to be consumed, locks it to prevent other consumers from receiving it, and then returns it to the application. 应用程序完成消息处理(或可靠地存储消息以供将来处理)后,它将通过对收到的消息调用 CompleteAsync 完成接收过程的第二个阶段。After the application finishes processing the message (or stores it reliably for future processing), it completes the second stage of the receive process by calling CompleteAsync on the received message. 服务总线发现 CompleteAsync 调用时会将消息标记为“正在使用”。When Service Bus sees the CompleteAsync call, it marks the message as being consumed.

如果应用程序出于某种原因无法处理消息,则它可对收到的消息调用 AbandonAsync 方法(而不是 CompleteAsync 方法)。If the application is unable to process the message for some reason, it can call the AbandonAsync method on the received message (instead of CompleteAsync). 此方法可使服务总线解锁消息并使其能够重新被同一个使用方或其他竞争使用方接收。This method enables Service Bus to unlock the message and make it available to be received again, either by the same consumer or by another competing consumer. 此外,还存在与锁定关联的超时,并且如果应用程序无法在锁定超时到期之前处理消息(例如,如果应用程序崩溃),则服务总线将解锁该消息并使其可再次被接收(实质上是默认执行一个 AbandonAsync 操作)。Secondly, there is a timeout associated with the lock and if the application fails to process the message before the lock timeout expires (for example, if the application crashes), then Service Bus unlocks the message and makes it available to be received again (essentially performing an AbandonAsync operation by default).

如果应用程序在处理消息之后,但在发出 CompleteAsync 请求之前发生崩溃,则在应用程序重新启动时会将该消息重新传送给它。In the event that the application crashes after processing the message, but before the CompleteAsync request is issued, the message is redelivered to the application when it restarts. 此过程通常称作“至少处理一次”,即每条消息将至少被处理一次。This process is often called At Least Once processing; that is, each message is processed at least once. 但是,在某些情况下,同一消息可能会被重新传送。However, in certain situations the same message may be redelivered. 如果方案不允许重复处理,则应用程序中需具备其他逻辑用于检测重复,这可通过消息中的 MessageId 属性实现(在整个传输尝试中,该属性保持不变)。If the scenario cannot tolerate duplicate processing, then additional logic is required in the application to detect duplicates, which can be achieved based upon the MessageId property of the message, which remains constant across delivery attempts. 此功能称为“仅一次”处理。This feature is known as Exactly Once processing.

主题和订阅Topics and subscriptions

与每条消息都由单个使用方处理的队列相比,主题和订阅通过发布/订阅模式提供“一对多”通信方式。In contrast to queues, in which each message is processed by a single consumer, topics and subscriptions provide a one-to-many form of communication, in a publish/subscribe pattern. 这对于扩展到大量接收方而言十分有用,每个发布的消息对向该主题注册的每个订阅均可用。Useful for scaling to large numbers of recipients, each published message is made available to each subscription registered with the topic. 系统会将消息发送到主题并传递到一个或多个相关联的订阅,具体取决于每个订阅上可以设置的筛选规则。Messages are sent to a topic and delivered to one or more associated subscriptions, depending on filter rules that can be set on a per-subscription basis. 此订阅可以使用其他筛选器来限制其想要接收的消息。The subscriptions can use additional filters to restrict the messages that they want to receive. 消息发送到主题的方式和发送到队列的方式相同,但不会直接从主题被接收。Messages are sent to a topic in the same way they are sent to a queue, but messages are not received from the topic directly. 而是从订阅接收消息。Instead, they are received from subscriptions. 主题订阅类似于接收发送至该主题的消息副本的虚拟队列。A topic subscription resembles a virtual queue that receives copies of the messages that are sent to the topic. 从订阅接收消息的方式与从队列接收相同。Messages are received from a subscription identically to the way they are received from a queue.

通过比较,队列的消息发送功能直接映射到主题,而其消息接收功能映射到订阅。By way of comparison, the message-sending functionality of a queue maps directly to a topic and its message-receiving functionality maps to a subscription. 此外,此功能意味着订阅支持本部分中前面有关队列所述的相同模式:竞争使用者、临时分离、负荷量和负载均衡。Among other things, this feature means that subscriptions support the same patterns described earlier in this section with regard to queues: competing consumer, temporal decoupling, load leveling, and load balancing.

创建主题和订阅Create topics and subscriptions

创建主题与创建队列类似,如前一部分中所述。Creating a topic is similar to creating a queue, as described in the previous section. 然后使用 TopicClient 类发送消息。You then send messages using the TopicClient class. 若要接收消息,可以创建主题的一个或多个订阅。To receive messages, you create one or more subscriptions to the topic. 与队列类似,通过 SubscriptionClient 对象而不是 QueueClient 对象从订阅接收消息。Similar to queues, messages are received from a subscription using a SubscriptionClient object instead of a QueueClient object. 创建订阅客户端,将主题名称、订阅名称和接收模式(可选)作为参数传递。Create the subscription client, passing the name of the topic, the name of the subscription, and (optionally) the receive mode as parameters.

有关完整的工作示例,请参阅 Github 上的 BasicSendReceiveUsingTopicSubscriptionClient 示例For a full working example, see the BasicSendReceiveUsingTopicSubscriptionClient sample on Github.

规则和操作Rules and actions

在许多情况下,必须以不同方式处理具有特定特征的消息。In many scenarios, messages that have specific characteristics must be processed in different ways. 若要启用此处理,可配置订阅以找到具有所需属性的消息,并对这些属性执行某些修改。To enable this processing, you can configure subscriptions to find messages that have desired properties and then perform certain modifications to those properties. 虽然服务总线订阅可以看到发送到主题的所有消息,但你仅可以将这些消息的一个子集复制到虚拟订阅队列。While Service Bus subscriptions see all messages sent to the topic, you can only copy a subset of those messages to the virtual subscription queue. 可使用订阅筛选器完成此筛选。This filtering is accomplished using subscription filters. 此类修改称为筛选器操作。Such modifications are called filter actions. 创建订阅后,可提供一个对消息属性进行操作的筛选器表达式,其中属性包括系统属性(例如 Label)和自定义应用程序属性(例如 StoreName)SQL 筛选器表达式在此示例中为可选;如果没有 SQL 筛选器表达式,会对该订阅的所有消息执行在订阅上定义的任何筛选器操作。When a subscription is created, you can supply a filter expression that operates on the properties of the message, both the system properties (for example, Label) and custom application properties (for example, StoreName.) The SQL filter expression is optional in this case; without a SQL filter expression, any filter action defined on a subscription will be performed on all the messages for that subscription.

有关完整的工作示例,请参阅GitHub上的 TopicSubscriptionWithRuleOperationsSample 示例For a full working example, see the TopicSubscriptionWithRuleOperationsSample sample on GitHub.

有关可能的筛选器值的详细信息,请参阅文档 SqlFilterSqlRuleAction 类。For more information about possible filter values, see the documentation for the SqlFilter and SqlRuleAction classes.

后续步骤Next steps

有关使用服务总线消息传送的详细信息和示例,请参阅以下高级主题:For more information and examples of using Service Bus messaging, see the following advanced topics: