Chapter 3 RingyDingy

“A little boat that keeps your DRb service afloat!” That is how developer Eric Hodel describes his RingyDingy gem at http://seattlerb.rubyforge.org/RingyDingy/. In Chapter 2, “Rinda,” we discussed RingServers, including how to build a simple one. RingyDingy aims to make the process of managing a RingServer a little easier and a little less prone to some of the issues that can sometimes occur with RingServers.

Installation

RingyDingy is installed using RubyGems:

$ gem install RingyDingy

It is important that you use correct capitalization. If you do not, RubyGems will not be able to find the gem and install it correctly. Upon installation, you should see the following message:

Successfully installed RingyDingy-1.2.1

Getting Started with RingyDingy

When you install the RingyDingy gem, it installs a binary for you called ring_server. This binary, probably not surprisingly, runs a RingServer for you. Let’s take a quick look at what options are available on this binary:

$ ring_server --help

This should print something similar to the following:

image

The two most important flags for us are --d and --v. The --d flag, as stated in the description, runs the RingServer as a daemon in the background. You should run with this command in production. However, because we are learning about RingyDingy, we can simply run it in the foreground so that we can keep an eye on its output. To help with that, we should use the --v flag when we start the RingServer in our development environment. That will increase the amount of logging to the screen, so we can more easily debug any issues we may come across. Let’s start our RingyDingy RingServer now with the following command:

$ ring_server --v

You should get output similar to the following:

registration and expiration logging enabled

listening on druby://macbates.home:50823

Obviously your computer name and port will be different, but you get the idea. That’s all we need to do to get RingyDingy up and running.

“Hello World” the RingyDingy Way

With our RingyDingy RingServer running and outputting useful logging information, we can now start our “Hello World” application. Fortunately we can make use of the code we wrote in Chapter 2 to power this chapter. Our server code for the Rinda “Hello World” application remains largely unchanged to use with RingyDingy:

image

In fact, there is only one difference between the Rinda version and the RingyDingy version of this code. Did you spot it? Don’t worry if you didn’t; it’s a subtle change in the code. When we create our Tuple with RingyDingy, the library dictates that we use the following format:

[:name, <service_name>, <instance>, <description>]

Notice that the first parameter of the Tuple is hardcoded to the value :name. In our original “Hello World” application, we set that parameter to :hello_world_service. Not a big change but a change nonetheless. The reason for this is simply that the RingyDingy library has :name hardcoded in it. Why is that? No reason that I can ascertain; it just is what it is. It is important, if you want to use RingyDingy without altering its source code, that you use this Tuple pattern; otherwise, it won’t work for you.

When we run our “Hello World” server, we should see output similar to the following for our RingyDingy RingServer:

registered :HelloWorldServer, “I like to say hi!”
      URI: druby://192.168.1.12:52042 ref: 1961110

As with our server, we also have to update our client to use the preferred RingyDingy Tuple pattern:

image

When we run our client, we should see something like the following:

image

Building a Distributed Logger with RingyDingy

RingyDingy allows us to DRY up our server code a bit. We no longer have to remember a whole lot of messy Rinda API calls. Instead, we can wrap it up with a line or two of RingyDingy code. Let’s look at our “Distributed Logger” application to see how we can make it more DRY.

If we were to write our “Distributed Logger” with Rinda, it would look something like the following:

image

With RingyDingy we can rewrite our logging server to look more like this:

image

This is definitely a little cleaner and easier to follow. The first parameter to the new method on the RingyDingy class is the instance of the class we want to serve. The second parameter, which is optional, is the name we want to give the service. This defaults to :RingyDingy if we don’t specify it. I prefer to specify it all the time, because it ensures that we don’t have any naming conflicts. It is also more descriptive of the service if we do. It would be a nice enhancement to RingyDingy if it did some inspection on the instance and used the class name as the default name of the service; at the time of writing, however, this isn’t the case.

Unfortunately, RingyDingy doesn’t give us any nice ways to clean up our client code, so we have to stay with the traditional Rinda code we are now used to:

image

image

When we fire up our server, we should see a rough equivalent of the following:

image

When we run our client, we should see the following on the client side:

[:name, :MyRingyDingyLogger, #<DRb::DRbObject:0x3bb938 @ref=9073620,
@uri=”druby://macbates.home:52186”>, “macbates.home_50587”]

On the server side, we should see the following:

I, [2009-04-29T23:22:58.361040 #50587] INFO -- : Hi There!

Letting RingyDingy Shine

RingyDingy offers a few other nice bits and pieces. One of the better features that the RingyDingy ring_server binary gives you for free is the ability to list available services. Assuming we had both our “Hello World” and “Distributed Logger” services registered with RingyDingy, and we ran the following command:

$ ring_server -l

we could expect to see something similar to the following returned:

image

This is a great debugging tool. It makes troubleshooting much easier when you know what services are and aren’t available, and where those services are actually located.

We can also gain access to this same information programmatically. Let’s take a look at a quick example:

image

In this code example we require the ringy_dingy/ring_server file. Then we call the list_services method on the RingyDingy::RingServer class, which returns to us a Hash of services.

Why do we get back a Hash and not an Array? The answer is because the key in the Hash is the host that is hosting the services, and the value is an Array of the services on that host. This is very helpful for diagnosing issues on a particular host.

After we get the Hash of services, we loop through each of keys, print the host, and then loop through each of the services for that host and print them. The results should look something like this:

image

Although this isn’t the most helpful output, you get the idea that this sort of information can be very helpful, and with RingyDingy it is fairly easy to retrieve. You can, of course, write your own method to retrieve the list of services for a custom RingServer as well, but using RingyDingy means you don’t have to.

Conclusion

Eric Hodel did a great job with this little library. The library doesn’t try to be anything it is not. It just tries to make using Rinda and RingServers a little easier, and it does that nicely. My only complaint is the use of the hardcoded :name parameter in the Tuple template, but that is a small nuisance. It also would’ve been nice to get some help cleaning up the client side of things. I would love to do the following in my client:

RingyDingy.find(:MyRingyDingyLogger)

That would definitely DRY up my client code. Perhaps Eric will find it in his heart to update the library to do that.

In the documentation, RingyDingy mentions the following:

If communication between the RingServer and the RingyDingy is lost, RingyDingy will re-register its service with the RingServer when it reappears.

Similarly, the RingServer will automatically drop registrations by a RingyDingy that it can’t communicate with after a short timeout.

I think I understand what Eric means by all that. However, that is as deep as the documentation goes on the subject. I have not been able to test what I think he means, so I won’t make any grand promises about what the library can and cannot do in regards to expiring/renewing registrations.

Considering its relative ease of use, if you are doing straight-up Rinda applications, dropping RingyDingy into the mix is easy, and it will help you manage your applications a little easier.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.145.178.151