[zeromq-dev] RFC: zbeacon for dhcp-style discovery

Chris Laws clawsicus at gmail.com
Thu Nov 28 06:29:26 CET 2013


I have implemented a service discovery mechanism that might work for you.
This approach lets my system applications find and make available any
number of services. It is influenced by zbeacon and czmq in general. While
I serialise the UDP packet content using msgpack it could equally be simple
strings.

Here is a brief overview:

// Create a discovery service on a certain UDP port
sdisco_t * sdisco_new (char *peer_id);

// Resolve the service endpoints for the named service.
void sdisco_lookup (sdisco_t *self, const char* service);

// Remove the named service from the list of currently unresolved services.
void sdisco_remove_lookup (sdisco_t *self, const char* service);

// Make the service with endpoint discoverable
void sdisco_add_service (sdisco_t *self, const char* service, const char
*endpoint);

// Remove the named service and endpoint combination from being
discoverable.
void sdisco_remove_service (sdisco_t *self, const char* service);

// Get discovery socket, for polling or receiving messages
void * sdisco_socket (sdisco_t *self);


The discovery mechanism binds a UDP socket to a port and listens for
discovery packets, similar to zbeacon. The packets that are processed must
match the version_id and a configuration_id. The configuration id allows me
to run multiple system configurations ('dev' 'production', etc) on the same
compute resources without interfering with each other.

Each discovery packets contains
version_id Eg. 'DISCO01'
peer_id Eg. 'app_1'
config_id Eg. user_id
a list of service lookups Eg. ['service_2', 'log_service']
a dict of services Eg. {'service_1': ['ipc://service_1.ipc',
'tcp://192.168.1.1:5555']}

Applications wanting to make use of the discovery mechanism must first
create a discovery object using 'sdisco_new ("app_name")'. After this the
app would typically put the sdisco socket into a poll loop so it's messages
can be processed.

Service providing applications typically bind a socket and add the endpoint
along with a service name to the discovery mechanism using the
'sdisco_add_service' call. The discovery mechanism will emit this
information after a brief interval (to minimise unnecessary emits in case
the app is registering lots of services right now). After the service is
broadcast once it is not broadcasted again until another application
requests it. This minimises unnecessary discovery packets on the network.

Applications looking for a particular service make this known to the sdisco
object using the 'sdisco_lookup'. The discovery mechanism emits lookup
packets at a configurable interval for as long as it has unresolved
lookups.

When emitting lookup requests the discovery packet does not populate the
services dict. When the discovery mechanism resolves a lookup it returns
this on its socket and removes the lookup from its list of unresolved
lookups.

So far the method seems to work well for my system of C and Python
applications. It lets me create applications with numerous discoverable
services (eg. control, diagnostics, logging, etc) and it only emits
discovery messages when necessary.

Hopefully this was of interest and informative. Perhaps you could make your
own based on a similar method?
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.zeromq.org/pipermail/zeromq-dev/attachments/20131128/8f22b47d/attachment.html>


More information about the zeromq-dev mailing list