On to Rhino Queues

Having failed miserably to get the first RSB sample to work between two computers, I thought I’d give the second sample a try-out. This is essentially the same program, but using Rhino Queues instead of MSMQ.

Worked on the same machine…

Worked across machines – woo!

So MSQM is relegated to the scrap heap for now. Perhaps it is more tractable when you use public queues between machines.

So let’s see what’s going on with this sample.

   1: using System;
   2: using Rhino.ServiceBus.Hosting;
   3: using Utils;
   4:  
   5: namespace Backend
   6: {
   7:     class Program
   8:     {
   9:         static void Main(string[] args)
  10:         {
  11:             QueueUtil.PrepareQueue("backend");
  12:             Console.WriteLine("Starting to listen for incoming messages ...");
  13:             var host = new DefaultHost();
  14:             host.Start<BackendBootStrapper>();
  15:             Console.ReadLine();
  16:         }
  17:     }
  18: }

The backend main program only does a couple of things:

  1. “Prepares” its queue by deleting what’s already there. Rhino Queues is based on the Microsoft Extensible Storage Engine (another piece of technology to learn!), which is commonly referred to as “Esent” after the name of its DLL (ESE for NT one assumes).
  2. Starts an instance of DefaultHost. The Start method is generic with a type parameter derived from AbstractBootStrapper. The sample implementation is an empty class – a placeholder in which to do some non-default things later I suppose.

The remaining classes in the backend are two message handlers, derived from ConsumerOf<T> with T replaced by HelloWorldMessage in both cases. Both classes override the Consume() method which is called when such a message is received: one echoes to the console, the other sends a response back to the client.

That all looks nice and clean and is simple to understand, but there’s quite a bit of clever stuff going on behind the scenes that I want to know more about. First, let’s look at what Castle Windsor is doing. A bit of light reading is in order. Discoveries in the next post.

Advertisements
Posted in Rhino Service Bus | 1 Comment

Getting Something out of MSMQ

In my last post, I hit a dead-end trying to get the sample client and server to talk to each other on different machines.

Time to cut it back to the basics. I manually created a private queue called “Test” on my server and turned off authentication to make sure that wasn’t getting in the way. I even turned off the firewall, though that didn’t make any difference.

To cut a long story short, here’s my test client that finally managed to get a message across to the Test queue on a different machine:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Messaging;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                using (var queue = new MessageQueue(@"FormatName:Direct=TCP:192.168.1.72\private$\Test"))
                {
                    var msg = new Message("Hello world");
                    msg.UseDeadLetterQueue = true;
                    queue.Send(msg);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
                Console.ReadLine();
            }
        }
    }
}

My initial attempt with the queue path set to “servername\private$\Test”. On my home network (no domain server), messages stayed in the client queue despite what I did on the server. I bit of digging revealed that the machine name was resolving to my public IP address, not the private subnet.

Substituting my 192.168 IP address for the machine name caused it to behave exactly the same as the Rhino sample – the message left the client machine but then disappeared into the ether. If messaging was turned off on the server, the message sat nicely in the outgoing queue on the client, but as soon as messaging was re-enabled, the client queue emptied and the messages were gone.

Enabling the dead-letter queue allowed me to see that the message was reaching the target machine even when it wasn’t getting to the target queue.

Reading around the Internet indicated that the queue name format was important. So instead of plain “192.168.1.72\private$\Test”, I tried prefixing “FormatName:Direct=OS:” which made no difference. However, using “TCP” instead of “OS” made it work.

A message was leaving the client and arriving in the queue at the server. Brillant.

Now I need to figure out the queue name format required in the Rhino-ESB config file.

Posted in Rhino Service Bus | Leave a comment

Getting Started with Rhino Service Bus

I’m going to start with the samples written by Björn Rochel, which are on github, so first I need a git client. Because I’ve used TortoiseSvn, I’ll use TortoiseGit to retain some degree of familiarity.

Having installed TortoiseGit and cloned the samples repository (and having read this mini-tutorial to learn a bit about git), I have a Lib folder, a Source folder and a ReadMe.txt file which says “A set of examples demonstrating important parts of the Rhino.ServiceBus API”, setting the trend for zero documentation because the code is so self-explanatory (we hope).

The Lib folder contains the Rhino Service Bus guts (Rhino.ServiceBus.Host.exe and Rhino.ServiceBus.dll) and other supporting dlls (e.g. for dependency injection and logging).

The Source folder holds ten sub-folders containing the samples. Lets start with number 1, “Hello world using MSMQ”.

The solution contains four assemblies: Client, Backend (interestingly not called Server), Messages and Utils.

02-12-2010 18-25-43

Before digging into the code any further, let’s compile and run, and see what happens.

Running Backend brings up a console showing that it is waiting to receive messages:

Backend consoleWe can also see that a new queue has been created on which messages are received for Backend (right-click on Computer in Windows Explorer and select “Manage”):

A new queue is born

Private queues do not have the Active Directory integration of public queues, which adds a bunch of features such as name lookup. We’ll be skipping all that for now. A private queue can still receive information from remote clients – the clients just need to know where it is.

The queue has two sub-queues: the main one on which the messages are received, and a journal queue, to which processed messages can be copied so that you can see what has been going on. These are created automatically, even though journaling is not enabled in this demo (you can enable it manually after Backend has started and created its queue).

Now for the client. Start it up and it created its own queue and waits for you to press Enter to send a hard-coded message. This is sent to Backend, which replies with an acknowledgement (the original message tells it which queue to reply to).

A conversation via queues.

If you turned on journaling above, you can now look at the message in the Backend journal queue and see its properties and contents.

In theory, you should be able to start Client without Backend running and send the message, then start Backend and see it display the message and send back the response. This requires that the Backend queue exists. In practice it doesn’t work because both Client and Backend purge their queues when starting up. If you remove this code and recompile, it works a treat.


So it all works locally, using MSMQ to talk between processes, but what about between machines? Should just work, right?

I copied the Backend program and supporting dlls to another machine and started it listening. I changed the target queue path in the client config file:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="castle" type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler, Castle.Windsor"/>
  </configSections>
  <castle>
    <facilities>
      <facility id="rhino.esb">
        <bus
          threadCount="1"
          numberOfRetries="5"
          endpoint="msmq://localhost/LearningRhinoESB.E1.Client"/>
        <messages>
          <add
            name="Messages.HelloWorldMessage"
            endpoint="msmq://Server42/LearningRhinoESB.E1.Backend"/>
        </messages>
      </facility>
    </facilities>
  </castle>
</configuration>

Running the client generates no errors but nothing appears at the Backend. Worse, there are no messages hanging around in any of the queues – the message has been lost! I thought this was exactly the kind of thing that queues were supposed to prevent.

So this post ends on a cliffhanger. It seems I need to dig into MSMQ a bit more before proceeding.

Posted in Rhino Service Bus | Leave a comment

Learning to Use Rhino Service Bus

So I’m intending to use this blog to document my discovery of how to use Rhino Service Bus. This is (initially at least) intended to be my own personal set of notes to help me organize my thoughts and understanding as I go along. Maybe it will be useful for others making the same journey.

I am also pretty new to all the other technologies that I will encounter along the way, such as the dependency injection container and ORM, so I will be documenting those too. I know many of the principles of this stuff, just not well enough for application, which is the important thing and what I mean to resolve.

I’m leaving this post small and content free to make sure my blogging software works, and to put my stake in the ground.

Posted in Rhino Service Bus | Leave a comment