本主题介绍使用 HTTP 传输进行互作所需的 WS-Reliable 消息传送 2005 年 2 月(版本 1.0)协议的 Windows Communication Foundation (WCF) 实现详细信息。 WCF 遵循 WS-Reliable 消息传送规范以及本主题中所述的约束和说明。 请注意,WS-ReliableMessaging 版本 1.0 协议从 WinFX 开始实现。
WS-Reliable Messaging 2005 年 2 月协议由 ReliableSessionBindingElement 在 WCF 中实现。
为方便起见,本主题使用以下角色:
发起方:启动 WS-Reliable 消息序列创建的客户端
响应方:接收发起方请求的服务
本文档使用下表中的前缀和命名空间。
| 前缀 | Namespace |
|---|---|
| wsrm | http://schemas.xmlsoap.org/ws/2005/02/rm |
| netrm | http://schemas.microsoft.com/ws/2006/05/rm |
| s | http://www.w3.org/2003/05/soap-envelope |
| wsa | http://schemas.xmlsoap.org/ws/2005/08/addressing |
| wsse | http://docs.oasis-open.org/wss/2004/01/oasis-200401-wssecurity-secext-1.0.xsd |
消息传送
序列建立消息
WCF 实现 CreateSequence 和 CreateSequenceResponse 消息以建立可靠的消息序列。 以下约束适用:
B1101:WCF 发起方在
CreateSequence消息中或者在CreateSequence消息包含Offer元素(Expires元素中的可选Offer元素)的情况下,不会生成可选的 Expires 元素。B1102:访问
CreateSequence消息时,WCFResponder会发送和接收这两个Expires元素(如果它们存在),但不使用这些元素的值。
WS-Reliable Messaging 引入了 Offer 机制来建立两个形成会话的反向相关的序列。
R1103:如果
CreateSequence包含一个Offer元素,可靠消息响应者必须接受序列,并以包含CreateSequenceResponse元素的wsrm:Accept进行响应,从而形成两个相关的对话序列,或者拒绝CreateSequence请求。R1104:在反向序列上流动的
SequenceAcknowledgement和应用程序消息必须发送到ReplyTo的CreateSequence终结点引用。R1105:
AcksTo中的ReplyTo和CreateSequence终结点引用必须具有与八进制识别匹配的地址值。WCF 响应程序在创建序列之前会验证
AcksTo和ReplyTo的 EPRs URI 部分是否相同。R1106:
AcksTo和ReplyTo的终结点引用在CreateSequence中应具有相同的引用参数集。WCF 不强制实施,但假定
AcksTo和ReplyTo上的 [引用参数] 与CreateSequence相同,并使用从ReplyTo终结点引用获得的 [引用参数] 进行确认和反向序列消息。R1107:在使用
Offer机制建立两个反向序列时,在反向序列上流动的SequenceAcknowledgement和应用程序消息必须发送到ReplyTo的CreateSequence终结点引用。R1108:使用 Offer 机制建立两个反向序列时,
[address]的wsrm:AcksTo元素的wsrm:Accept终结点引用子元素的CreateSequenceResponse属性必须与CreateSequence的识别字节的目标 URI 相匹配。R1109:使用
Offer机制建立两个相反序列时,发起方发送的消息和响应方对消息的确认必须发送到同一终结点引用。WCF 使用 WS-Reliable 消息传递机制在发起者与响应者之间建立可靠会话。 WCF 的 WS-Reliable Messaging 实现提供单向、请求-答复和完全双工消息传递模式的可靠会话。 WS-Reliable 消息传送
Offer机制CreateSequence/CreateSequenceResponse允许你建立两个相关的相反序列,并提供适用于所有消息终结点的会话协议。 由于 WCF 为此类会话提供安全保证,包括会话完整性的端到端保护,因此确保面向同一方的消息到达同一目标是可行的。 这也允许在应用程序消息上捎带序列确认消息。 因此,R1104、R1105 和 R1108 约束适用于 WCF。
CreateSequence 消息的示例。
<s:Envelope>
<s:Header>
<a:Action s:mustUnderstand="1">
http://schemas.xmlsoap.org/ws/2005/02/rm/CreateSequence
</a:Action>
<a:ReplyTo>
<a:Address>
http://Business456.com/clientA
</a:Address>
</a:ReplyTo>
<a:MessageID>
urn:uuid:addabbbf-60cb-44d3-8c5b-9e0841629a36
</a:MessageID>
<a:To s:mustUnderstand="1">
http://Business456.com/clientA
</a:To>
</s:Header>
<s:Body>
<wsrm:CreateSequence>
<wsrm:AcksTo>
<wsa:Address>
http://Business456.com/clientA
</wsa:Address>
</wsrm:AcksTo>
<wsrm:Offer>
<wsrm:Identifier>
urn:uuid:0afb8d36-bf26-4776-b8cf-8c91fddb5496
</wsrm:Identifier>
</wsrm:Offer>
</wsrm:CreateSequence>
</s:Body>
</s:Envelope>
CreateSequenceResponse 消息的示例。
<s:Envelope>
<s:Header>
<a:Action s:mustUnderstand="1">
http://schemas.xmlsoap.org/ws/2005/02/rm/CreateSequenceResponse
</a:Action>
<a:RelatesTo>
urn:uuid:addabbbf-60cb-44d3-8c5b-9e0841629a36
</a:RelatesTo>
<a:To s:mustUnderstand="1">
http://Business456.com/clientA
</a:To>
</s:Header>
<s:Body>
<wsrm:CreateSequenceResponse>
<Identifier>
urn:uuid:eea0a36c-b38a-43e8-8c76-2fabe2d76386
</Identifier>
<Accept>
<AcksTo>
<a:Address>
http://BusinessABC.com/serviceA
</a:Address>
</AcksTo>
</Accept>
</wsrm:CreateSequenceResponse>
</s:Body>
</s:Envelope>
序列
下面是适用于序列的约束列表:
B1201:WCF 生成并访问不超过
xs:long最大非独占值(9223372036854775807)的序列号。B1202:WCF 始终生成正文为空的最后一条消息,其操作 URI 为
http://schemas.xmlsoap.org/ws/2005/02/rm/LastMessage。B1203:只要操作 URI 不是
LastMessage,WCF 就会接收并传递带有http://schemas.xmlsoap.org/ws/2005/02/rm/LastMessage元素的序列头的消息。
Sequence 标头的一个示例。
<wsrm:Sequence>
<wsrm:Identifier>
urn:uuid:addabbbf-60cb-44d3-8c5b-9e0841629a36
</wsrm:Identifier>
<wsrm:MessageNumber>
10
</wsrm:MessageNumber>
<wsrm:LastMessage/>
</wsrm:Sequence>
AckRequested 标头
WCF 使用 AckRequested 标头作为保持活动机制。 WCF 不生成可选 MessageNumber 元素。 收到带有 AckRequested 元素的 MessageNumber 标头的消息后,WCF 会忽略 MessageNumber 元素的值,如以下示例所示。
<wsrm:AckRequested>
<wsrm:Identifier>
urn:uuid:addabbbf-60cb-44d3-8c5b-9e0841629a36
</wsrm:Identifier>
</wsrm:AckRequested>
SequenceAcknowledgement 标头
WCF 将“非法携带”机制用于在 WS-Reliable Messaging 中提供的序列确认。
R1401:使用
Offer机制建立两个相反序列时,SequenceAcknowledgement标头可以包含在发送到预期收件人的任何应用程序消息中。B1402:当 WCF 必须在接收任何序列消息之前生成确认(例如,若要满足
AckRequested消息),WCF 将生成SequenceAcknowledgement包含范围 0-0 的标头,如以下示例所示。<wsrm:SequenceAcknowledgement> <wsrm:Identifier> urn:uuid:addabbbf-60cb-44d3-8c5b-9e0841629a36 </wsrm:Identifier> <wsrm:AcknowledgementRange Upper="0" Lower="0"/> </wsrm:SequenceAcknowledgement>B1403:WCF 不生成包含
SequenceAcknowledgement元素的标头,但支持Nack元素。
WS-ReliableMessaging 错误
下面列出了适用于 WS-Reliable Messaging 的 WCF 实现错误的约束:
B1501:WCF 不生成
MessageNumberRollover错误。B1502:WCF 终结点可能会生成
CreateSequenceRefused故障,如规范中所述。B1503:当服务终结点达到其连接限制且无法处理新连接时,WCF 将生成额外的
CreateSequenceRefused故障子代码,netrm:ConnectionLimitReached如以下示例所示。<s:Envelope> <s:Header> <wsa:Action> http://schemas.xmlsoap.org/ws/2005/08/addressing/fault </wsa:Action> </s:Header> <s:Body> <s:Fault> <s:Code> <s:Value> s:Receiver </s:Value> <s:Subcode> <s:Value> wsrm:CreateSequenceRefused </s:Value> <s:Subcode> <s:Value> netrm:ConnectionLimitReached </s:Value> </s:Subcode> </s:Subcode> </s:Code> <s:Reason> <s:Text xml:lang="en"> [Reason] </s:Text> </s:Reason> </s:Fault> </s:Body> </s:Envelope>
WS-Addressing 错误
由于 WS-Reliable 消息传送使用 WS 寻址,WCF WS-Reliable 消息传送实现可能会生成 WS-Addressing 错误。 本部分介绍 WCF 在 WS-Reliable Messaging 层显式生成的 WS-Addressing 错误:
B1601:WCF 在满足以下条件之一时生成所需的错误消息寻址标头:
消息缺少
Sequence标头和Action标头。消息
CreateSequence缺少MessageId标头。消息
CreateSequence缺少ReplyTo标头。
B1602:WCF 在响应缺少
Sequence标头并包含 WS-Reliable Messaging 规范不能识别的Action标头的消息时,将生成“操作不受支持”错误。B1603:WCF 生成“终结点不可用”错误以指示终结点将不会根据对
CreateSequence消息的寻址标头的检查来处理序列。
协议构成
与 WS-Addressing 组合
WCF 支持两个版本的 WS 寻址:WS-Addressing 2004/08 [WS-ADDR] 和 W3C WS-Addressing 1.0 建议 [WS-ADDR-CORE] 和 [WS-ADDR-SOAP]。
虽然 WS-Reliable 消息规范中仅提到 WS-Addressing 2004/08,但并未限制可使用的 WS-Addressing 版本。 下面是适用于 WCF 的约束列表:
R2101:WS-Addressing 2004/08 和 WS-Addressing 1.0 可用于 WS-Reliable 消息传送。
R2102:必须在整个给定的 WS-Reliable Messaging 序列或一对通过使用
wsrm:Offer机制相关的反向序列上使用 WS-Addressing 的单一版本。
与 SOAP 组合
WCF 支持将 SOAP 1.1 和 SOAP 1.2 与 WS-Reliable 消息传送配合使用。
与 WS-Security 和 WS-SecureConversation 组合
WCF 通过使用安全传输(HTTPS)、WS-Security 的整合,以及与 WS-Secure 对话的整合,为 WS-Reliable 消息传递序列提供保护。 下面是适用于 WCF 的约束列表:
R2301:除了单个消息的完整性和机密性外,为了保护 WS-Reliable 消息序列的完整性,WCF 要求使用 WS-Secure 对话。
R2302:WS-Secure Conversation 会话必须在建立 WS-Reliable Messaging 序列之前建立。
R2303:如果 WS-Reliable 消息序列的生存期超过了 WS-Secure 对话会话的生存期,那么使用 WS-Secure 对话建立的
SecurityContextToken必须通过相应的 WS-Secure 对话续订绑定来进行续订。B2304:WS-Reliable Messaging 序列或一对相关的反向序列总是绑定到单一的 WS-SecureConversation 会话。
WCF 源在
wsse:SecurityTokenReference消息的元素扩展性部分生成CreateSequence元素。R2305:在与 WS-Secure Conversation 组合时,
CreateSequence消息必须包含wsse:SecurityTokenReference元素。
WS-Reliable Messaging WS-Policy 断言
WCF 使用 WS-Reliable 消息 WS-Policy 断言 wsrm:RMAssertion 来描述端点的功能。 下面是适用于 WCF 的约束列表:
B3001:WCF 将
wsrm:RMAssertionWS-Policy 断言附加到wsdl:binding元素。 WCF 支持附加到wsdl:binding和wsdl:port元素。B3002:WCF 支持 WS-Reliable Messaging 断言的以下可选属性,并在 WCF
ReliableMessagingBindingElement上提供对这些属性的控制:wsrm:InactivityTimeoutwsrm:AcknowledgementInterval
下面是一个示例。
<wsrm:RMAssertion> <wsrm:InactivityTimeout Milliseconds="600000" /> <wsrm:AcknowledgementInterval Milliseconds="200" /> </wsrm:RMAssertion>
流控制 WS-Reliable Messaging 扩展
WCF 使用 WS-Reliable 消息传送扩展性来提供对消息流序列的可选更严格的控制。
通过将属性设置为 ReliableSessionBindingElement.FlowControlEnabledtrue.,启用流控制。 下面是适用于 WCF 的约束列表:
B4001:在启用可靠消息传递流控制时,WCF 在
netrm:BufferRemaining标头的元素扩展性中生成SequenceAcknowledgement元素。B4002:启用可靠消息流控制后,WCF 不要求在
netrm:BufferRemaining头中必须有SequenceAcknowledgement元素,如以下示例所示。<wsrm:SequenceAcknowledgement> <wsrm:Identifier> http://fabrikam123.com/abc </wsrm:Identifier> <wsrm:AcknowledgementRange Upper="1" Lower="1"/> <netrm:BufferRemaining> 8 </netrm:BufferRemaining> </wsrm:SequenceAcknowledgement>B4003:WCF 使用
netrm:BufferRemaining来指示可靠消息目标可以缓存多少条新消息。B4004:当目标应用程序无法快速接收消息时,WCF 可靠消息服务会调节传输的消息数量。 可靠消息传递目标对消息进行缓冲,元素的值降为 0。
B4005:WCF 生成介于 0 和 4096(包括这两个值)之间的
netrm:BufferRemaining整数值,并读取介于 0 和xs:int的maxInclusive值 214748364(包括这两个值)之间的整数值。
消息交换模式
本部分介绍 WS-Reliable 消息传送用于不同消息交换模式时 WCF 的行为。 对于每个消息交换模式,将考虑以下两种部署方案:
不可寻址的发起程序:发起程序位于防火墙后面;响应方只能在 HTTP 响应上将消息传送到发起程序。
可寻址发起方:发起方和响应方都可以发送 HTTP 请求;换句话说,可以建立两个相反的 HTTP 连接。
单向、不可寻址启动器
捆绑
WCF 通过一个 HTTP 通道使用一个序列提供单向消息交换模式。 WCF 使用 HTTP 请求将所有消息从 RMS 传输到 RMD,并使用 HTTP 响应将所有消息从 RMD 传输到 RMS。
CreateSequence Exchange
WCF 发起方生成未包含提议的 CreateSequence 消息。 WCF 响应方确保在创建序列之前 CreateSequence 不包含提议。 WCF 响应程序使用CreateSequence消息回复CreateSequenceResponse请求。
SequenceAcknowledgement
WCF 发起方处理除 CreateSequence 消息和错误消息之外的所有消息答复的确认消息。 WCF 响应方总是在对序列消息和 AckRequested 消息的响应中生成一个独立的确认消息。
TerminateSequence 消息
WCF 将 TerminateSequence 视为单向操作,这意味着 HTTP 响应具有空的正文,并返回 HTTP 202 状态码。
单向、可寻址的发起方
捆绑
WCF 提供了一种单向消息交换模式,这种模式在入站和出站 Http 通道上使用一个序列。 WCF 使用 HTTP 请求传输所有消息。 所有 HTTP 响应都具有空正文和 HTTP 202 状态代码。
CreateSequence Exchange
WCF 发起方生成未包含提议的 CreateSequence 消息。 WCF 响应方确保在创建序列之前 CreateSequence 不包含提议。 WCF 响应程序在以CreateSequenceResponse终结点引用为地址的 HTTP 请求上发送ReplyTo消息。
双工、可寻址的发起方
捆绑
WCF 提供通过一个入站和一个出站 HTTP 通道使用两个序列的完全异步的双向消息交换模式。 WCF 使用 HTTP 请求传输所有消息。 所有 HTTP 响应都具有空正文和 HTTP 202 状态代码。
CreateSequence Exchange
WCF 发起方生成包含提议的 CreateSequence 消息。 WCF 响应方确保在创建序列之前 CreateSequence 包含提议。 WCF 在寻址到 CreateSequenceResponse 的 CreateSequence 终结点引用的 HTTP 请求上发送 ReplyTo。
序列生命周期
WCF 将两个序列视为一个全双工会话。
在某个序列出现故障时,WCF 预期远程终结点会使这两个序列同时出现故障。 当读取导致某个序列故障的错误时,WCF 会使两个序列都故障。
WCF 可以关闭其出站序列并继续处理其入站序列上的消息。 相反,WCF 可以处理入站序列的关闭,并继续在其出站序列上发送消息。
请求-答复、不可寻址的发起方
捆绑
WCF 通过一个 HTTP 通道使用两个序列提供单向和请求-回复消息交换模式。 WCF 使用 HTTP 请求来传输请求序列的消息,并使用 HTTP 响应来传输回复序列的消息。
CreateSequence Exchange
WCF 发起方生成包含提议的 CreateSequence 消息。 WCF 响应方确保在创建序列之前 CreateSequence 包含提议。 WCF 响应程序使用CreateSequence消息回复CreateSequenceResponse请求。
单向消息
若要成功完成单向消息交换协议,WCF 发起程序在 HTTP 请求上传输请求序列消息,并在 HTTP 响应上接收独立 SequenceAcknowledgement 消息。
SequenceAcknowledgement 必须确认已传输的消息。
WCF 响应程序可以使用确认、错误或具有空正文和 HTTP 202 状态代码的响应来回复请求。
双向消息
若要成功完成双向消息交换协议,WCF 发起程序在 HTTP 请求上传输请求序列消息,并在 HTTP 响应上接收回复序列消息。 响应必须包含 SequenceAcknowledgement 对已传输的请求序列消息的确认。
WCF 响应程序可以使用应用程序回复、错误或包含空正文和 HTTP 202 状态代码的响应来回复请求。
由于存在单向消息和应用程序回复的计时,请求序列消息的序列号和响应消息的序列号没有关联。
重试答复
WCF 依赖于 HTTP 请求-回复关联实现双向消息交换协议相关性。 因此,在确认请求序列消息时(而不是在 HTTP 响应携带确认消息、用户消息或错误时),WCF 发起方不会停止重试请求序列消息。 WCF 响应程序在与答复关联的请求的 HTTP 请求回合上重试答复。
LastMessage Exchange
WCF 启动器在 HTTP 请求链路上生成并传输一条消息体为空的最后一条消息。 WCF 需要响应,但忽略实际响应消息。 WCF 响应方使用答复序列的正文为空的最后一条消息答复请求序列的正文为空的最后一条消息。
如果 WCF 响应程序收到的最后一条消息中,其动作 URI 不是 http://schemas.xmlsoap.org/ws/2005/02/rm/LastMessage,则 WCF 会以最后一条消息答复。 对于双向消息交换协议,最后一条消息承载应用程序消息;如果单向消息交换协议,则最后一条消息为空。
WCF 响应程序不需要对答复序列的空体最后一条消息进行确认。
TerminateSequence 交换
当所有请求都收到有效的回复时,WCF 发起程序会在 HTTP 请求回合上生成并传输请求序列 TerminateSequence 的消息。 WCF 需要响应,但忽略实际响应消息。 WCF 响应方使用答复序列的 TerminateSequence 消息答复请求序列的 TerminateSequence 消息。
在正常的关闭序列中,两个 TerminateSequence 消息都携带一个完整范围的 SequenceAcknowledgement。
请求/答复、可寻址的发起方
捆绑
WCF 通过入站和出站 HTTP 通道使用两个序列提供请求-回复消息交换模式。 WCF 使用 HTTP 请求传输所有消息。 所有 HTTP 响应都具有空正文和 HTTP 202 状态代码。
CreateSequence Exchange
WCF 发起方生成包含提议的 CreateSequence 消息。 WCF 响应方确保在创建序列之前 CreateSequence 包含提议。 WCF 在寻址到 CreateSequenceResponse 的 CreateSequence 终结点引用的 HTTP 请求上发送 ReplyTo。
请求/答复关联
WCF 发起程序可确保所有应用程序请求消息都包含一个 MessageId 和一个 ReplyTo 终结点引用。 WCF 发起方在每个应用程序请求消息上应用 CreateSequence 消息的 ReplyTo 终结点引用。 WCF 响应程序要求传入的请求消息包含MessageId和ReplyTo。 WCF 响应程序确保 CreateSequence 的终结点引用的 URI 与所有应用程序请求消息的 URI 相同。