2
votes

I am trying to implement Reliable WCF Service with MSMQ based on this architecture (http://www.devx.com/enterprise/Article/39015)

A message may be lost if queue is not available (even cluster doesn't provide zero downtime)

Take a look at the simple order processing workflow

  1. A user enters credit card details and makes a payment

  2. Application receives a success result from payment gateway

  3. Application send a message as “fire and forget”/”one way” call to a backend service by WCF MSMQ binding

  4. The user will be redirected on the “success” page

  5. Message is stored in a REMOTE transactional queue (windows cluster)

  6. The backend service dequeue and process the message, completes complex order processing workflow and, as a result, sends an as email confirmation to the user

Everything looks fine as excepted.

What I cannot understand how can we guarantee that all “one way” calls will be delivered in the queue? Duplex communication is not a case due to the user should be redirected at the result web page ASAP.

Imagine the case when a user received “success” page with language “… Your payment was made, order has been starting to process, and you will email notifications later…” but the message itself is lost.

How durability can be implemented for step 3?

One of the possible solutions that I can see is

3a. Create a database record with a transaction details marked as uncompleted, just to have any record about the transaction. This record may be used as a start point to process the lost message in case of the message will not be saved in the queue.

I read this post

The main thing to understand about transactional MSMQ is that there are three distinct transactions involved in a transactional send to a remote queue.

  1. The sender writes the message to a local queue.
  2. The queue manager on the senders machine transmits the message across the wire to the queue manager on the recipient machine
  3. The receiver service processes the queue message and then removes the message from the queue.

But it doesn’t solve described issue - as I know WCF netMsmqBinding‎ doesn’t use local queue to send messages to remote one.

1

1 Answers

1
votes

But it doesn’t solve described issue - as I know WCF netMsmqBinding‎ doesn’t use local queue to send messages to remote one.

Actually this is not correct. MSMQ always sends to a remote queue via local queue, regardless of whether you are using WCF or not.

If you send a message to a remote queue then look in Message Queuing in Server Management you will see in Outbound queues that a queue has been created with the address of the remote queue. This is a temporary queue which is automatically created for you. If the remote queue was for some reason unavailable, the message would sit in the local queue until it became available, and then it would be transmitted.

So durability is provided because of the three-phase commit:

  1. transactionally write message locally
  2. transactionally transmit message
  3. transactionally receive and process message

There are instances where you may drop messages, for example, if your message processing happens outside the scope of the dequeue transaction, and also instances where it is not possible to know if the processing was successful (eg back-end web service call times out), and of course you could have a badly formed message which will never succeed processing, but in all cases it should be possible to design for these.

If you're using public queues on a clustered environment then I think there may be more scope for failure as clustering msmq introduces complexity (I have not really used so I don't know) so try to avoid if possible.