Welcome back! In Part 1 of this tale, we'd successfully configured a WCF client and an IIS-hosted service to communicate via MSMQ on the same machine. But we're only half done. As you may recall, our goal here is to deploy the client, service and queues all on separate machines. We also want to secure the configuration so that only or client is permitted to send messages to the queue.
Before we dive in, a quick disclaimer. As I mentioned in the first article, at the time of writing there is very little information about how to get this scenario working correctly. As such, we had to use a lot of trial and error. While I hope all of the tips in this article are correct and helpful, keep in mind that I don't have the time or resources to test everything in a clean environment. If any of this advice turns out to be incorrect or if I've missed anything important, please let me know and I'll correct the article.
The next phase of this journey is to get all of the components running on their own servers, as shown in the diagram below (yes, it's the same one I included in part 1). Since getting everything working can be a little fiddly, we're going to continue to take baby steps so we won't be switching to authenticated or transactional messages just yet.
To get started, make sure you have your three servers, and configure the necessary Windows components on each as described in part 1. Then deploy the client app on the client app server, create the message queues on the MSMQ server, and deploy the service in IIS on the service app server. Other than the fact that the boxes are different, there really isn't any difference in this step to what you did in the single-server scenario.
The first difference between the single-server and multi-server scenario is that MSMQ will normally reject unauthenticated messages from remote machines. When you use set the security mode to "None" (or "Message") in the NetMsmqBinding, all messages will be deemed to be sent from a pretend user called ANONYMOUS LOGON. As such, you need to set the ACLs on the message queue to grant the ANONYMOUS LOGON account "Send Message" permission. This step had me stumped for ages - I had assigned permissions to the actual account that my client app was running under, yet all messages ended up in the Dead Letter Queue with an "Access Denied" message. Hopefully this tip will save you the same pain!
Remember how we needed to configure IIS using appcmd.exe to listen to the MSMQ protocol? Well one part of the cryptic command syntax was bindingInformation='localhost'. The meaning of the bindingInformation attribute varies for each protocol, but for net.msmq this refers to the server that hosts the queues that IIS should be listening to. In our multi-server scenario we will be putting our queues on a separate server called msmqserver. First, let's switch off the localhost binding we configured last time. Note that the only difference in syntax for adding and removing a binding is the use of -+ versus --.
appcmd set site "Default Web Site" --bindings.[protocol='net.msmq',bindingInformation='localhost']
Now let's switch on the net.msmq protocol for our remote msmqserver:
appcmd set site "Default Web Site" -+bindings.[protocol='net.msmq',bindingInformation='msmqserver']
If you're not joined to a domain, here's a top tip from the MSMQ Activation Sample on MSDN: "To enable activation in a computer joined to a workgroup, both the activation service and the worker process must be run with a specific user account (must be same for both) and the queue must have ACLs for the specific user account."
Hopefully the final step will be to modify the queue address in the config files for your client and service applications. The only change should be to replace localhost with msmqserver, leading to a queue URI like net.msmq://msmqserver/private/MsmqService/MsmqService.svc.
Now that everything is working properly across multiple machines, let's start hardening the solution by turning on Transport Security. The NetMsmqBinding has four security modes: None (which we've been using up until now), Transport (which specifies that we should be using MSMQ's built-in security features), Message (in which WCF provides security at the SOAP level), and Both (which combines Transport and Message modes). In this scenario we will be using Transport security, as it enables to administrators to use the standard MSMQ security features. Most importantly it will allow us to lock down the queue so only the account running our client is authorised to send messages to the queue.
If you haven't done so already, go to Add/Remove Windows Components and enable MSMQ Active Directory integration. Using AD is the easiest way to get Transport Security working. It is possible to use Transport Security without AD if you use custom certificates, but I won't discuss this approach in this article (mainly because I've never tried it :-).
In order to switch on Transport Security, we'll need to configure a new WCF binding. (Alternatively you can just change the configuration of your existing binding, but I like to make sure each binding's name describes what it actually does). Transport is the default security mode for NetMsmqBinding, but in order to avoid confusion I also like to configure this explicitly:
<binding name="MsmqBindingNonTransactionalTransportSecurity" exactlyOnce="false">
This needs to go in both your client and server's configuration files. Of course, you'll also need to update your endpoints to use the new MsmqBindingNonTransactionalTransportSecurity binding configuration.
This step sounds simple, and in your case it may be. However in my environment I found there were a number of tricks required (probably mainly because I was using non-standard service accounts for my client).
The simple bit is to make sure the account running your client has permission to send to the message queue. If you're running the client app under your own account, this is probably already set. Once you've checked or set the ACLs, try the application and see if it works. If so, congratulations - you're done! If not, keep reading.
One error that we saw when attempting to send to the queue was "An error occurred while sending to the queue: Unrecognized error -1072824273 (0xc00e002f).Ensure that MSMQ is installed and running. If you are sending to a local queue, ensure the queue exists with the required access mode and authorization.". If you get this, it probably means that there is no certificate in Active Directory for your specific user account on a specific server. I'm not sure if you need a certificate for all three servers in the scenario, but it's probably better to be safe than sorry. To register the certificate, do the following:
After you've done this, try again - and again, hopefully you're done. One other trick we found may be necessary is to add the machine account of the client app server into the AD domain group called "Windows Authorization Access Group" - this is described in this TechNet article. I'm not positive of the exact situations when this is necessary, but if all else fails I'd suggest giving this a try.
If you're still having troubles getting communication across the boxes, one final thing to check is whether any of the MSMQ traffic is being blocked by a firewall. I'd suggest temporarily turning off all firewalls across the various boxes to see if this is an issue.
Hopefully by now you'll have a secure, multi-server deployment of your WCF client, server and message queues. In the final instalment we will go one step further and switch over to transactional queues to ensure your messages don't ever go walkabout.
PingBack from http://itknowledgeexchange.techtarget.com/serviceendpoint/wmoc-sharp-11-zermatt/
Tonight's slide deck is up here . After the presentation, Steve Andrews was kind enough to come all
nice to read abt MSMQ binding in WCF. it is really helpful
方案的设计目标是在Client/Server端建立可靠的、异步的通信。系统采用MSMQ作为传输机制，因为MSMQ支持可靠的队列通信。MSMQ部署在三方Server上（一般集群部署，避免单点故障）。Client端应用程序使用WCF的NetMsmqBingding 来发送消息到MSMQ Server的私有队列。Service 服务程序将部署在IIS 7.0，并采用Windows Activation Services（WAS）来监听消息队列上的新消息。通过SMSvnHost.exe – Windows
轻松玩转 MSMQ, WCF 和 IIS 7.0 MSMQ, WCF and IIS: Getting them to play nice by Tom Hollander Tom Hollander
Tonight's slide deck is up here . After the presentation, Steve Andrews was kind enough to come all the way out to my house, and help fix some workgroup edition permission issues with TFS on Windows Server 2003, and now all the code is checked in
Tonight's slide deck is up here . After the presentation, Steve Andrews was kind enough to come all the way out to my house, and help fix some workgroup edition permission issues with TFS on Windows Server 2003, and now all the code is checked in as well.