在 WCF 中排队

本部分介绍如何在 Windows Communication Foundation(WCF)中使用排队通信。

作为 WCF 传输绑定进行排队

在 WCF 中,协定指定正在交换的内容。 协定是业务相关或应用程序特定的消息交换。 用于交换消息的机制(或称为“方式”)在绑定中指定。 WCF 中的绑定封装消息交换的详细信息。 它们为用户公开配置旋钮,以控制传输或绑定所表示的协议的各个方面。 WCF 中的队列处理方式与其他任何传输绑定一样,这对许多队列应用程序来说是一大优势。 如今,许多排队应用程序与其他远程过程调用(RPC)样式的分布式应用程序编写方式不同,因此难以遵循和维护。 使用 WCF 时,编写分布式应用程序的样式大致相同,因此更易于遵循和维护。 此外,通过将交换机制与业务逻辑分开考虑,可以更轻松地配置传输或对其进行更改,而不会影响应用程序特定的代码。 下图演示了将 MSMQ 用作传输的 WCF 服务和客户端的结构。

已排队的应用程序关系图

如上图所示,客户端和服务必须仅定义应用程序语义,即协定和实现。 服务用首选设置来配置排队绑定。 客户端使用 ServiceModel 元数据实用工具工具(Svcutil.exe) 向服务生成 WCF 客户端,并生成描述用于向服务发送消息的绑定的配置文件。 因此,若要发送排队的消息,客户端会实例化 WCF 客户端并调用其上的操作。 这会导致消息发送到传输队列并传输到目标队列。 队列通信的所有复杂性都隐藏在发送和接收消息的应用程序中。

关于 WCF 中的排队绑定的注意事项包括:

  • 所有服务操作都必须是单向的,因为 WCF 中的默认排队绑定不支持通过队列进行的双工通信。 双向通信示例(Two-Way 通信)说明了如何使用两个单向合同通过队列实现双向通信。

  • 若要使用元数据交换生成 WCF 客户端,需要在服务上附加 HTTP 终结点,以便直接查询它以生成 WCF 客户端并获取绑定信息以适当配置排队的通信。

  • 根据排队绑定,要求在 WCF 外部进行额外配置。 例如,WCF 附带的 NetMsmqBinding 类要求配置绑定并对消息队列 (MSMQ) 进行最低配置。

后面几节描述 WCF 附带的基于 MSMQ 的特定排队绑定。

MSMQ

WCF 中的排队传输使用 MSMQ 进行排队通信。

MSMQ 作为可选组件随附在 Windows 中,作为 NT 服务运行。 它捕获消息以便在传输队列中进行传输,并在目标队列中进行交付。 MSMQ 队列管理器实现可靠的消息传输协议,以便在传输中不会丢失消息。 协议可以是本机协议,也可以是基于 SOAP 的,例如 SOAP 可靠消息协议(SRMP)。

在 MSMQ 中,队列可以是事务性的或非事务性的。 事务队列允许在事务中捕获和传递消息,然后持久存储在队列中。 发送至事务性队列的消息仅按顺序传输一次。 可以使用非事务性队列发送可变消息和持久消息。 发送到非事务性队列的消息不携带任何可靠的传输保证;因此,消息可能会丢失。

还可以使用向 Active Directory 目录服务注册的 Windows 标识来保护 MSMQ 队列。 安装 MSMQ 时,可以安装 Active Directory 集成,这要求计算机成为 Windows 域网络的一部分。

有关 MSMQ 的详细信息,请参阅安装消息队列(MSMQ)。

NetMsmqBinding

<netMsmqBinding> 是 WCF 为两个 WCF 端点提供的排队绑定,以便使用 MSMQ 进行通信。 因此,此绑定公开了仅限于 MSMQ 的属性。 但是,并非所有 MSMQ 功能和属性都在NetMsmqBinding中公开。 紧凑 NetMsmqBinding 设计为具有一组大多数客户都认为足够的最佳功能。

NetMsmqBinding 以绑定上的属性形式阐明了迄今为止所讨论的核心队列概念。 这些属性反过来又与 MSMQ 通信,了解如何传输和传递消息。 以下各节将讨论属性类别。 有关详细信息,请参阅更完整地描述特定属性的概念主题。

ExactlyOnce 和 Durable 属性

属性ExactlyOnceDurable会影响消息在队列之间传输的方式:

  • ExactlyOnce:设置为 true (默认值)时,排队通道可确保消息(如果已传递)不会重复。 它还可确保消息不会丢失。 如果无法传递消息,或在传递消息前已超过消息的生存时间,则将在死信队列中记录传递失败的消息以及失败原因。 设置为false时,排队通道会努力传输消息。 在这种情况下,可以任意选择一个死信队列。

  • Durable: 设置为 true (默认值)时,排队通道可确保 MSMQ 将消息持久存储在磁盘上。 因此,如果 MSMQ 服务要停止和重启,磁盘上的消息将传输到目标队列或传送到服务。 设置为 false 时,消息存储在易失性存储中,并在停止和重启 MSMQ 服务时丢失。

对于 ExactlyOnce 可靠传输,MSMQ 要求队列是事务性队列。 同时,MSMQ 还需要一个从事务性队列中进行读取的事务。 同样,在使用 NetMsmqBinding 时,请记住,如果将 ExactlyOnce 设置为 true,则需要使用事务来发送或接收消息。 与此类似,MSMQ 要求队列为非事务性队列来实现高效保证,例如,当 ExactlyOncefalse 以及进行可变消息传递时。 因此,将 ExactlyOnce 设置为 false,或将 durable 设置为 false 时,将无法使用事务发送或接收消息。

注释

确保基于绑定中的设置创建正确的队列(事务性或非事务性)。 如果ExactlyOncetrue,则使用事务性队列;否则,请使用非事务性队列。

死信队列属性

死信队列用于存储传递失败的消息。 用户可以编写补偿逻辑,以便从死信队列中读取消息。

很多队列系统都提供系统级死信队列。 MSMQ 为无法传递到非事务队列的消息提供系统范围的非事务死信队列,并为未能传递到事务队列的消息提供系统范围的事务死信队列。

如果多个向不同的目标队列发送消息的客户端共享 MSMQ 服务,则客户端发送的所有消息将转到同一死信队列。 这并不总是可取的。 为了更好地隔离,Windows Vista 中的 WCF 和 MSMQ 提供自定义死信队列(或特定于应用程序的死信队列),用户可以指定该队列来存储传递失败的消息。 因此,不同的客户端并不共享同一个死信队列。

绑定具有两个相关属性:

  • DeadLetterQueue:该属性是一个枚举,指示是否请求死信队列。 如果请求某类死信队列,则该枚举还包含这种死信队列。 具体的值为 NoneSystemCustom。 有关这些属性的解释的详细信息,请参阅 使用 Dead-Letter 队列处理消息传输失败

  • CustomDeadLetterQueue:该属性是应用程序专用死信队列的统一资源标识符(URI)地址。 如果选择了 DeadLetterQueue Custom 被选中。

病毒消息处理属性

当服务从事务下的目标队列读取消息时,服务可能会因各种原因无法处理该消息。 然后将消息放回队列中,以便再次读取。 若要处理重复失败的消息,可以在绑定中配置一组病毒消息处理属性。 有四个属性: ReceiveRetryCountMaxRetryCyclesRetryCycleDelayReceiveErrorHandling。 有关这些属性的详细信息,请参阅 病毒消息处理

安全属性

MSMQ 公开自己的安全模型,例如队列上的访问控制列表(ACL),或者发送经过身份验证的消息。 NetMsmqBinding 将这些安全属性作为其传输安全设置的一部分公开。 绑定中有两个用于传输安全性的属性: MsmqAuthenticationModeMsmqProtectionLevel。 这些属性中的设置取决于 MSMQ 的配置方式。 有关详细信息,请参阅使用传输安全性保护消息

除了传输安全性之外,还可以使用消息安全性保护实际的 SOAP 消息本身。 有关详细信息,请参阅使用消息安全性保护消息

MsmqTransportSecurity 还公开两个属性, MsmqEncryptionAlgorithm 以及 MsmqHashAlgorithm。 这些是要为消息的队列到队列传输加密和签名的哈希选择的不同算法的枚举。

其他属性

除了上述属性之外,绑定中公开的其他 MSMQ 特定属性包括:

  • UseSourceJournal:指示打开源日记记录的属性。 源日记是一项 MSMQ 功能,用于跟踪已成功从传输队列传输的消息。

  • UseMsmqTracing:指示打开 MSMQ 跟踪的属性。 MSMQ 跟踪会在每次消息离开或到达托管 MSMQ 队列管理器的计算机时,向报告队列发送报告消息。

  • QueueTransferProtocol:要用于队列到队列的消息传输的协议的枚举。 MSMQ 实现本机队列到队列的传输协议和称为 SOAP 可靠消息传输协议 (SRMP) 的基于 SOAP 的协议。 当使用 HTTP 传输进行队列到队列的传输时将使用 SRMP。 当使用 HTTPS 进行队列到队列的传输时将使用 SRMP 安全。

  • UseActiveDirectory:一个布尔值,指示 Active Directory 是否必须用于队列地址解析。 默认情况下,这是关闭的。 有关详细信息,请参阅 服务终结点和队列寻址

MsmqIntegrationBinding

如果希望 WCF 端点与用 C、C++、COM 或 System.Messaging API 编写的现有 MSMQ 应用程序通信,请使用 MsmqIntegrationBinding

绑定属性与 NetMsmqBinding 的绑定属性相同。 但是,存在以下差异:

  • MsmqIntegrationBinding 的操作协定限制为采用一个类型为 MsmqMessage<T> 的参数,其中类型参数为正文类型。

  • 很多 MSMQ 本机消息属性都在 MsmqMessage<T> 中公开以供使用。

  • 为了帮助序列化和反序列化消息正文,提供了 XML 和 ActiveX 等序列化程序。

示例代码

有关如何编写使用 MSMQ 的 WCF 服务的分步说明,请参阅以下主题:

有关演示如何在 WCF 中使用 MSMQ 的已完成代码示例,请参阅以下主题:

另请参阅