I have a system that will post a message to a queue, but does not need to wait for a response - just needs to make sure the message arrived properly in the queue, not that is was processed at the receiving end. A second service will poll the queue to retrieve outstanding messages and will then move the message to an outside system. The movement of the message to the outside system will be wrapped in a transaction and if the process is successful, then the transaction will be commited otherwise it will be rolled back.
1) is it appropriate for the service that posts the message to send an END CONVERSATION ? This way the sending service will not be waiting for a response.
2) in the data movement phase, is it appropriate to issue and END CONVERSATION when commiting and not issue when ROLLBACK occurs. Or should ROLLBACK occur with a following END CONVERSATION with error message?
Can you define 'need to make sure the message arrived properly'?
In general a Service Broker application is guaranteed that the message send was properly delivered when the SEND statement was commited. That's the whole purpose of the broker, to take this responsibily out of the app programmer hands and offer it as 'plumbing'. A sent message should be considered 'delivered'. However, the application should not make assumptions about the timeframe of the said delivery. If the target service is down (i.e. for maintenance), if there is a bad configuration or simply transient errors, the message might stay 'in traffic' for seconds, minutes, maybe days. If the application needs a certain timeframe for delivery, then it should specify it as a conversation lifetime option in the BEGIN DIALOG statement.
And specific to your questions:
1) No. This is the dradded 'fire-and-forget' pattern. See this post here for details: http://blogs.msdn.com/remusrusanu/archive/2006/04/06/570578.aspx
The appropiate sequence of actions is for initiator to send the message and commit, then go on on its merry ways w/o waiting for a response. The target receives the message, process it and then ends the conversation. The EndDialog message is sent from the target to initiator and the initiator ends its side in reponse. The initiator ending of the conversation can be done by an activated procedure, so there's no need for initiator app to be hanging around waiting for a response.
2) None. You should never intentionally rollback receives from a queue. This is guaranteed to trigger poison message detection mechanism, which will deactivate the queue in response. An applications houls always be able to handle any message received. In case of an error, it should end the conversation with error then commit.
BTW, rather than use pooling on the target service, you should consider activation.
HTH,
~ Remus
Both endpoints of a dialog (the initiator as well as the target) must end the dialog. It does not matter which service ends it first. The general rule is that whichever service has finished processing the dialog and is no longer interested in any messages the other side could send, should end the dialog first. On ending the dialog, the service will automatically send an EndDialog message to the other service so that it knows that the dialog has been closed at the remote end. On RECEIVing this message, the service would normally end the dialog on its end.
1) If your initiating service ends the conversation, it will not be able to receive any responses even asynchronously. Even if you do not have application-level responses, the response could be something as simple as ending the dialog at the target. There is no reason why you couldn't SEND your message from the initiating service and return without waiting for responses. You could setup an activated procedure on the initiator to simply receive EndDialog messages and end those dialogs. This would run asychronous to the thread doing the SEND.
2) All Service Broker statement (SEND, END CONVERATION, BEGIN DIALOG, etc) are transactional. That is, if you issue an END CONVERSATION and then rollback the transaction, the effect is as if the END CONVERSATION was never issued at all. In other words, if you want your END CONVERSATION to actually take effect, you must commit the transaction under which it is issued.
Finally, your app should not be relying on rolling back transactions for expected errors. For example, if you RECEIVE messages and then do some transactional work to an outside system which could fail, then rolling back the RECEIVE could have undesirable consequences. When you rollback a receive, the messages received are immediately put back in the queue and become available. If your app then loops around and re-issues a RECEIVE, it will receive the same set of messages. Trying to process the same message(s) may fail again. If this repeats 5 times, we detect a poisoned message and disable the queue. A better approach to handle expected errors is to remove the messages from the queue, saving them to a table and using some sort of retry mechanism (eg> conversation timers) to try again later.
|||Thanks, I was unaware that the actual SEND message was transactional. That makes sense and helps me put everything into context. I'm still trying to get my mind around the service broker.
One question I do still have, in my case, the receiver will run several processes and then call a mySQL based system. If the mySQL based system is not available, then I would close the conversation with error. I guess I'd then place the message info into a staging table where further processing could be done on it. However, what if the info could not be placed into the staging table? I am confused as to how I could then regain access to this message to insure it gets ultimately fixed and written out to the correct system. Since its already been read successfully and a end conversation has been issued, the message is no longer available, correct?
|||>> On ending the dialog, the service will automatically send an EndDialog message to the other service so that it knows that the dialog has been closed at the remote end. On RECEIVing this message, the service would normally end the dialog on its end.
Is the ending of the dialog automatic when a service receives a message that the other end of the conversation has ended the dialog or is this something that must explicitly be done after receiving the EndDialog message?
|||The END CONVERSATION must be issued explicitly by both services.
No comments:
Post a Comment