Check the status and result of MSMQ message

2019-05-23 00:24发布

问题:

I'm working on a RESTfull web service that does the following:

  1. On POST request, it starts a long running task. It queues up a message for MSMQ, which is processed in windows service hosted applicaiton. It returns HTTP status code 202 Accepted along with id of the job we queued up.
  2. Client application continously polls the service (with GET) with id of the job we just queued up. When the MSMQ client is finished with the task, it should return the result of the operation. If not, it will return 202 Accepted with appropriate expiration date for next recommended poll.

My question is: How should I implement communication from MSMQ to web service? Specifically, how would my web service know if a message was processed by MSMQ client?

My first though was to have a "job" table in SQL database which would contain a JobId, a flag indicating whether a job is finished and a result of computation. MSMQ application would then write to this table when it finishes a job, while web service would query the database for status of a job on each request. I don't like this approach very much, as my web service would not use SQL server otherwise - results of the job are idempotent (but time consuming) and I don't intend to save the data it returns in any way.

I'm wondering if there is more idiomatic approach to this problem, as it's the first time I'm dealing with MSMQ or message queues in general.

回答1:

By introducing an asychronous step into your process you have, willingly or not, entered the realm of eventual consistency.

There are inherent drawbacks with this approach, one of which is that it becomes necessary to continually check for convergence if the caller requires knowledge of system consistency being restored.

That is not to say I disagree with your approach, but if you're using vanilla MSMQ you need to be aware of the ramifications of doing so. MSMQ on it's own gives you none of the message exchange semantics you would expect from a service bus type platform, which would give you more options about how to handle your current perceived problem.

For example, if you could "reply" back to the sender via msmq (by using something like NServiceBus) then you could use some kind of server push technology like WebApi with SignalR to alert the client in realtime without the need to persist to DB.

An alternative would be to lose the asynchronous step, and replace it with a synchronous call, which would be feasible if the offline process completed quickly enough.

However, such approaches are complicated at best and your current solution is much simpler in my opinion.