So, we have a nice service-oriented broker, but we have no way of knowing whether a particular service is available or not. We know when a request fails, but we donât know why. It would be useful to be able to ask the broker questions like, âIs the echo service running?â The most obvious way to implement this would be to modify our MDP/Client protocol to add commands to ask such questions. But MDP/Client has the great charm of being simple. Adding service discovery to it would make it as complex as the MDP/Worker protocol.
Another option is to do what email servers do, and ask that undeliverable requests be returned. This can work well in an asynchronous world, but it also adds complexity. We need ways to distinguish returned requests from replies and to handle these properly.
Letâs try to use what weâve already built, building on top of MDP instead of modifying it. Service discovery is, itself, a service. It might indeed be one of several management services, such as âdisable service X,â âprovide statistics,â and so on. What we want is a general, extensible solution that doesnât affect the protocol or existing applications.
Thereâs a small RFC that layers this on top of MDP: the Majordomo Management Interface (MMI). We already implemented it in the broker, though unless you read the whole thing you probably missed that. Iâll explain how it works in the broker:
When a client requests a service that starts with
mmi.
, instead of routing this request to a worker, we handle it internally.We handle just one service in our broker, which is
mmi.service
, the service discovery service.The payload for the request is the name of an external service (a real one, provided by a worker).
The broker returns â200â (OK) or â404â (Not found), depending on whether there are workers registered for that service or not.
Example 4-52 shows how we use the service discovery in an application.
Example 4-52. Service discovery over Majordomo (mmiecho.c)
//
// MMI echo query example
//
// Lets us build this source without creating a library
#include "mdcliapi.c"
int
main
(
int
argc
,
char
*
argv
[])
{
int
verbose
=
(
argc
>
1
&&
streq
(
argv
[
1
],
"-v"
));
mdcli_t
*
session
=
mdcli_new
(
"tcp://localhost:5555"
,
verbose
);
// This is the service we want to look up
zmsg_t
*
request
=
zmsg_new
();
zmsg_addstr
(
request
,
"echo"
);
// This is the service to which we send our request
zmsg_t
*
reply
=
mdcli_send
(
session
,
"mmi.service"
,
&
request
);
if
(
reply
)
{
char
*
reply_code
=
zframe_strdup
(
zmsg_first
(
reply
));
printf
(
"Lookup echo service: %s
\n
"
,
reply_code
);
free
(
reply_code
);
zmsg_destroy
(
&
reply
);
}
else
printf
(
"E: no response from broker, make sure it's running
\n
"
);
mdcli_destroy
(
&
session
);
return
0
;
}
Try this with and without a worker running, and you should see the little program report â200â or â404â accordingly.
The implementation of MMI in our example broker is flimsy. For example, if a worker disappears, services remain âpresent.â In practice, a broker should remove services that have no workers after some configurable timeout.
Get ZeroMQ now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.