20.4. Service Discovery with Distributed Ruby
If you have many services running locally, service discovery might be a useful concept to you; it allows services to be located by name. But if you have few services at well-known locations, this may not be particularly useful.
Because you are apparently still reading, you must be interested in how service discovery works. The Rinda library provides such a service (naturally based on Rinda) called Rinda::Ring. Think of it as providing DNS-like features; it is a central registration service storing information (in a tuplespace) about drb processes. The drb services can use UDP (datagrams) to find a nearby registration server to advertise themselves and/or to find other services in the neighborhood.
The Rinda::RingServer class implements the registration server. It keeps a tuplespace for storing locations of other drb services (though actually any service may be advertised). When it comes up, the RingServer listens for UDP broadcast packets requesting the location of the server. It responds to each of these by connecting back (via drb) to the requesting service. The following is an example of running a RingServer:
require 'rinda/ring' require 'rinda/tuplespace' DRb.start_service Rinda::RingServer.new(Rinda::TupleSpace.new) DRb.thread.join
The Rinda::RingProvider class registers (or advertises) a service with a RingServer. A service is identified by a service type, a front-end object providing the service, and a piece of descriptive text. In the following example, we create a simple Adder service that adds two numbers; then we advertise it to the world:
require 'rinda/ring' class Adder include DRbUndumped def add(val1, val2) return val1 + val2 end end adder = Adder.new DRb.start_service(nil, adder) Rinda::RingProvider.new(:adder, adder, 'Simple Adder') DRb.thread.join
The Rinda::RingFinger class (presumably named for the classic UNIX finger command) can be used to locate a RingServer. It sends a UDP broadcast packet and waits for the RingServer to respond. The RingFinger can then be used to look up advertised services in the tuplespace.
require 'rinda/ring' DRb.start_service rs = Rinda::RingFinger.primary list = [rs] + Rinda::Ringfinger.to_a svc = list.find_all [:name, :adder, nil, nil]