Category Archives: messaging

The duality of request/reply vs. publish/subscribe #2

In my last post, I described how the mechanics of publish/subscribe actually mirror those of request/reply.

In this post, I’ll look at the two operation from another angle: What do they mean?

What does it mean when you bus.Send?

Sending means either that the sender wants to

  • Command that another service does something.
  • Request that another service does something, and yields one or more replies1.

This means that the sender knows stuff about the other service, but that other service will most likely not know or care about who’s sending. In other words, the sender depends on that other service!

What does it mean when you bus.Publish?

Publishing means that the publisher wants to

  • Broadcast an event that contains information on something that has happened.

This means that the publisher most likely does stuff inside itself, maybe updates some internal state, and then goes on and publishes information on some aspect of what has happened. In doing this, the publisher will most likely not know or care about who’s receiving. In other words, the subscriber depends on the publisher!

Summing it up with a picture

Consider this illustration, where service dependencies are shown with arrows:

Again, see how comparing Send to Publish is actually like comparing two mirror images when the other mirror image is upside-down?

  1. Note that the request/reply pattern may impose unwanted temporal coupling in an architecture and should probably be used only in integration scenarios orchestrated by a saga.

The duality of request/reply vs. publish/subscribe #1

A question I often meet in relation to messaging frameworks like NServiceBus and Rebus, is this: Where do messages go?

The confusion often comes from comparing how bus.Publish works with how bus.Send works.

In this post, I’d like to describe the two operations and show that they are mirror images of each other – except maybe not as much a mirror image as a transposition.

Sending messages

In the case where you’re doing a bus.Send(message), the answer is trivial: The message gets sent to the endpoint specified in the sender’s enpoint mapping for that message type. Let’s say our sender is equipped with this snippet of XML1 in its app.config:

<UnicastBusConfig>
  <MessageEndpointMappings>
    <add Messages="MyService.Messages" Endpoint="my_service"/>
  </MessageEndpointMappings>
</UnicastBusConfig>

If we assume that message is an instance of a class from the MyService.Messages assembly, in this case a bus.Send(message) will be translated into bus.Send("my_service", message).

Publishing messages

But where do messages go when they’re published? Well, they go to whomever subscribed to that particular message type – and with NServiceBus (and, for that matter, with Rebus as well) subscribers get subscribed by sending some kind of subscription message, which is basically saying: “Hey there, mr. Publisher – I’m some_subscriber, and I’d like to subscribe to MyService.Messages.SomeParticularMessage“.

From this point on, the publisher will store the mapping of the message type along with the subscriber’s address, allowing a bus.Publish(message) method to be implemented something along the lines of

public void Publish(object message)
{
    foreach(var subscriberEndpoint in GetSubscribersFor(message.GetType()))
    {
        Send(subscriberEndpoint, message);
    }
}

So – how do we understand this on a higher level, allowing us to never ever confuse these things again? Let’s dive into…

The duality

Consider these two sequence-like diagrams:

See how request/reply and publish/subscribe are actually the same patterns? The reason these two are often confused, is that the Send operation is often countered by Publish, when in fact it would be more fitting to see the subscription message (i.e. subscription request) as the counterpart of Send. Thus, Publishing is more like replying. And thus, Send is actually the transposition of Publish.

Now, when you realize this, you’re never going to confuse these things again :) In the next post, I’ll touch a little bit on another difference between Send and Publish.

  1. The snippet is an endpoint mapping in NServiceBus format, which can also be understood by Rebus when it’s running with the DetermineDestinationFromNServiceBusEndpointMappings implementation of IDetermineDestination