Implementing pub-sub using MSMQ in 15 minutes





5.00/5 (4 votes)
Requirements: 1. Install MSMQ. By default the service is not enabled. To do this on Windows 7: a. Launch Control Panel an click on Turn Windows features on or off. b. Select Microsoft Message Queue (MSMQ) Server. c. Under this option, select MSMQ HTTP Support and Multicasting Support.
Requirements:
1. Install MSMQ. By default the service is not enabled. To do this on Windows 7:
a. Launch Control Panel an click on Turn Windows features on or off.
b. Select Microsoft Message Queue (MSMQ) Server.
c. Under this option, select MSMQ HTTP Support and Multicasting Support.
HTTP Support provides the ability to send messages across the internet.
Multicasting provides the ability for publish subscribe.
2. Click OK.
3. Open Computer Manager to confirm that you have a new listing under Services and Applications called Message Queuing with Outgoing, Private and System Queue folders.
Implementing Pub/Sub using MSMQ
1. Create a new C# Console Project.
2. Add reference to System.Messaging dll.
3. Modify Program.cs to look like follows:
class Publisher { static void Main(string[] args) { //1. establish the queue using (var helloQueue = new MessageQueue("FormatName:MULTICAST=234.1.1.1:8001")) { while (true) { var stopWatch = new Stopwatch(); stopWatch.Start(); //2. create a message, that can be anything since it is a byte array for (var i = 0; i < 1000; i++) { SendMessage(helloQueue, string.Format("{0}: msg:{1} hello world ", DateTime.UtcNow.Ticks, i)); Thread.Sleep(10); } stopWatch.Stop(); Console.ReadLine(); Console.WriteLine("===================================================="); Console.WriteLine("[MSMQ] done sending 1000 messages in " + stopWatch.ElapsedMilliseconds); Console.WriteLine("[MSMQ] Sending reset counter to consumers."); SendMessage(helloQueue, "reset"); Console.ReadLine(); } } } private static void SendMessage(MessageQueue queue, string content) { //3. send the message queue.Send(content); Console.WriteLine(" [MSMQ] Sent {0}", content); } }
4. Create a new C# console project and add a reference to the System.Messaging dll.
5. Modify Program.cs to look like this:
class Subscriber { static void Main(string[] args) { int messagesReceived = 0; var messages = new Queue<string>(5000); var filePath = typeof (Subscriber).FullName + ".txt"; var path = @".\private$\hello-queue"; using (var helloQueue = new MessageQueue(path)) { helloQueue.MulticastAddress = "234.1.1.1:8001"; while (true) { var message = helloQueue.Receive(); if (message == null) return; var reader = new StreamReader(message.BodyStream); var body = reader.ReadToEnd(); messagesReceived += 1; messages.Enqueue(body); Console.WriteLine(" [MSMQ] {0} Received {1}", messagesReceived, body); if (string.CompareOrdinal("reset", body) == 0) { messagesReceived = 0; File.WriteAllText(filePath, body); messages.Clear(); } } } } }
Some implementation notes
1. Publish/subscribe requires a different queue path format. For fire and forget, the queue format is .\private$\hello-queue if sending to a privat queue. For pub/sub, we need a multicast address in the form FormatName:MULTICAST=234.1.1.1:8001.
2. Messages received are not exactly same as sent. By default MSMQ uses an XML serializer so our plain string is now wrapped in an XML tag.
3. A multicast subscriber queue is just a regular queue with a multicast address. So you can create many different queues with different names with the same multicast address to receive the same message from the publisher.
4. You can have many publishers and many subscribers. All the subscribers receive all of the messages from each publisher. Contrast this with RabbitMQ where messages are distributed between subscribers, although I would suspect that our quick 15 minute tutorial on RabbitMQ probably is missing a setting to allow equal distribution of messages among the subscribers.
