How (WS-) Reliable Messaging Works
来源:互联网 发布:数据库decode函数 编辑:程序博客网 时间:2024/06/14 17:56
原文地址:http://msdn.microsoft.com/en-us/library/aa480191.aspx
Even though he Windows Communication Foundation does – as you will learn – conveniently hide all the intricate details of the WS-ReliableMessaging specification from the application developer and makes the implementation of reliable messaging a mere matter of picking the right binding configuration for a service and service client, it is certainly useful to have a bit of an idea of what's going on behind the scenes and on the wire.
After all, you can only really trust a mechanism that you fully understand, right?
Reliable messaging works generally like this: A client sends a sequence of messages (the sequence may be as short as one message) across a communication link and asks the receiver to acknowledge that it has received the message(s).
The acknowledgement(s) are sent back to the client either individually and for each message, or in a single acknowledgement for a series of messages. Once the client has received the acknowledgement, it knows that the message(s) has been successfully transferred.
The TCP (Transmission Control Protocol, as in TCP/IP) works with acknowledgement messages to make sure that all data packets of a sequence are reliably transferred between two endpoints. WS-ReliableMessaging works very much in the same way – just a bit higher up on the communication stack and independent of the underlying transport. More concretely: WS-RM is designed to control reliable delivery of single SOAP messages or sequences of SOAP messages between two endpoints, irrespective of how these endpoints are connected; for instance even if messages travel through message routers or other intermediaries using different transport protocols for each of hop.
To establish a reliable messaging link between two endpoints, we first need a notion of a connection or "session". Each message sent in the context of that session is assigned a unique number denoting its order in the sequence. The sender-side (or "initiator") establishes a temporary cache to keep track of the messages sent and matches them up with the incoming acknowledgements. If a message is not acknowledged after a certain time (the "retry-timeout"), the message is resent automatically from the cache. Once an acknowledgement is received, the message can be removed from the cache.
The receiver-side (or "acceptor") establishes a cache for holding messages it accepted in order to store them before delivering them to the application. That's done because the receiving infrastructure and the application may have a "pull-relationship".
Deep down in WCF's channel architecture where the WS-RM channel is stacked on top of the transport channel and possibly some additional channels such as the security channel, arriving messages are queued up in the transport channel as they arrive.
So – and this is indeed a bit of a simplified description of how it all works – whenever a worker thread becomes available to process a message, the service model pulls a message from that transport queue through the channel stack (each channel pulls from its underlying channel) and dispatches the message into the services you write. It may look as if every message is immediately and synchronously pushed to the services you write, but in fact there is always such a pull-push translation taking place.
Because there may be a delay between the arrival of the message and the message dispatch depending on how busy the service is and because the RM channel is concerned about acknowledging arrived messages rather quickly, the RM channel will not wait for messages to flow by as they bubble up from the transport to the service model. Instead, it proactively pulls them out of the underlying transport queue as they arrive, sends out the necessary acknowledgements (if it can; we get to that later) and keeps the messages available in its own queue for pickup by the service model layer.
This cache (or queue) also serves to temporarily hold any messages received out-of-order so that messages can be delivered to the application in the order they were sent. If messages 3 and 4 of a sequence arrive before message 2, these "later" messages are held in the cache until message 2 arrives and therefore only delivered to the application once the sequence is in proper order. This happens if the application requires ordered delivery and message order enforcement is turned on (which is the default behavior).
In addition for supporting ordered delivery, the message number allows the receiver-side to detect duplicate messages and discard them. Messages can be duplicated on the path from the sender to the receiver, or be sent twice by the sender-side if an acknowledgment is lost or delayed.
It's important to note that the terms "initiator" and "acceptor" are used instead of "client" and "server", because each end of the communication path can and often will play both roles. The "client" and "server" terminology becomes easily confusing once you start to think about bi-directional communication.
If we assume having a Request/Response communication pattern, the response needs to be delivered just as reliably as the request and therefore the responding party must implement an initiator mechanism that is very similar to what the requesting party implements for the original requests. The requesting party, in turn, is playing the acceptor role for the responses. If responses get lost, they must be resent by the responding party and therefore they must also be cached (and acknowledged). Both ends of a reliable messaging session therefore maintain separate caches for outbound and inbound messages.
Whenever the communicating parties have a bi-directional (dual) communication link, the responding party can simply retry sending messages just like the requesting party would retry sending if the request cannot be delivered.
However, if the communication link doesn't allow the responding party to deliver messages independent of a client request, things get a bit more complicated. That is specifically the case with HTTP where the responding party only has an opportunity to get anything back to the requesting party when the latter comes around with another request.
To force the requesting party to come around and pick up unacknowledged responses when using HTTP, the responding party uses a simple trick: The acknowledgement for the request message is always piggybacked on the response. With that and in case of the response getting lost, the requesting party will not receive an acknowledgement and will resend the request, even though the original request might indeed have arrived at the responding party and the request was already processed. The responding party will detect such a resend request by inspecting the message's sequence number and will serve the cached response resulting from the original request from its message cache instead of re-processing the message.
Any acknowledgements for received responses are piggybacked on subsequent requests made on the same reliable session, so that the responding party can clean up its response cache. The request that carries the response acknowledgement is thereby completely unrelated – its message simply serves as the next convenient ferryboat to come along and cross the river.
The scope for a WS-ReliableMessaging session is called "Sequence" and is established by a "CreateSequence" Web service request that is sent out-of-band between the communicating endpoints. Out-of-band means that this particular request is sent and handled by the infrastructure and not surfacing as a web service call anywhere on the service model level. Once the party initiating the sequence is done with its work and has collected all outstanding acknowledgements it sends a "TerminateSequence" request – also out-of-band and "behind the scenes" as the channel is closed.
If you really were to poke around down below in the channel architecture, you would see that receiving the "CreateSequence" request causes a new channel to become available, through which all messages for the respective sequence are delivered. The "TerminateSequence" message will cause that channel to indicate the end of the sequence by delivering a null message to the receiver.
原文地址:http://msdn.microsoft.com/en-us/library/aa480191.aspx
- How (WS-) Reliable Messaging Works
- 使用MSMQ进行Reliable Messaging
- Web Services Platform Architecture : SOAP, WSDL, WS-Policy, WS-Addressing, WS-BPEL, WS-Reliable Mess
- How Internet EDI Works
- How E-mail Works
- How E-mail Works
- How Google Works
- How DES works
- How Google Works
- How Google Map Works
- How NAT Works
- How 4GT Works
- How PAE X86 Works
- How Digital Photography Works
- How Tomcat Works 1
- How Tomcat Works 2
- Books - How Tomcat works
- How Tomcat Works 5
- C#线程同步(4)- 通知&EventWaitHandle一家
- Goodbye Steve(1955-2011)
- C#线程同步(5)- 信号量 Semaphore
- Source Insight配置GCC AVR (WinAVR) 步骤
- B 树概念
- How (WS-) Reliable Messaging Works
- web应用UI开发基础笔记-html、css、javascript
- SQL: 判断给定日期值(或时间段)所在星期的星期一和星期天的日期
- 手工破解windows密码
- Android使用自定义AlertDialog(退出提示框)
- iphone开发每日一练【2011-10-06】
- vb/vb.net开发精粹(2)
- [android开发]WebView如何获得正在打开页面的进度?
- 信号量集(主要是AND信号量)