2

I am struggling to understand when to use each of these:

1) Message Bus: Used to send integration events between Microservices. For example, Microservice A could publish an integration event, which is handled by Microservice B and Microservice C. The benefit of a Message Bus e.g. RabbitMQ is that it could be durable meaning if one of the Microservices is down then it can handle the event later. It also guarantees delivery.

2) Mediatr (Mediator pattern): Using CQRS the Mediatr pattern can be used to decouple commands and events making the MVC controller/service thinner.

I see how both of these patterns can be used in the same environment. I then see code like this:

3) In Memory Bus: https://github.com/gregoryyoung/m-r/blob/master/SimpleCQRS/FakeBus.cs. It is an In Memory bus.

What is the difference between using Mediatr and an In Memory Bus? The way I am thinking at the moment is that Mediatr is more appropriate when using the Observer pattern and an In Memory Bus is more suitable when using the publisher/subsciber pattern. Have I understood this correctly?

Is it appropriate to use an InMemory Bus for a single Microservice (for domain events) and a durable Message bus for integration events (between Microsservices)?

1
  • Presumably one is synchronous and the other is not. – Telastyn Sep 28 '18 at 10:34
3

A mediator pattern creates a flexible decoupled interface between two microservices. Messages are sent to and from each microservice without one necessarily having to know all the explicit workings of the other.

This pattern is ideal if you think the relationship between the two might change significantly in the future. The mediator could be standalone and it could persist messages in case of failed delivery, so potentially it can be just as stabile as the message bus.

A publish-subscribe pattern which is basically your message bus, isn't just for two interfaces. It is potentially for multiple interfaces, allowing for maximum flexibility. The flexibility also extends to the message itself, meaning the message must be easily sent and received by anyone interested in receiving said message when an event occurs. This also implies you may have problems down the road with versioning if you're not careful, as changes in messages being passed must be consistently interpreted across microservices, unlike the mediator. When the message changes, then only the mediator absolutely must also be updated for everything to work properly.

An in-memory bus isn't really a pattern so much as a message bus with no persistence. It is faster, but also not ideal when there are unexpected failures, as you don't know where the error occurred and would have serious difficulty trying to restore the previous situation. In any production context, I wouldn't recommend this, even if it wrote to a log file.

I hope that answers your question!

10
  • So a in memory bus is a bit like udp, right? You just send out and don't care if it gets lost. So it could have practical applications just as udp has. – findusl Sep 28 '18 at 12:38
  • @findusl Well you've seen how it is written. If the computer shuts off and the message was received by the memory message bus, message is lost. This may be fine if you don't care too much about guaranteeing the delivery of the message. So yes, I suppose you could look at it that way. It is the UDP of message buses, whereas a persistent message bus would be more like TCP. – Neil Sep 28 '18 at 12:46
  • @Neil, thanks. I understand the use of a message bus for communication between Microservices (integration events). However, say you have Domain Events inside a Micro service, then would you have a second message bus inside the Microservice? + 1 for: "It is potentially for multiple interfaces" – w0051977 Sep 28 '18 at 12:55
  • @w0051977 No, not unless by using the main message bus, you'd have major architectural problems. Generally you'd use just the one (if anything, you can better organize the events into namespaces to modularize, i.e. datalayer.connectionEstablished). – Neil Sep 28 '18 at 12:59
  • Thanks, so why does Greg Young use one here: github.com/gregoryyoung/m-r/blob/master/SimpleCQRS/FakeBus.cs – w0051977 Sep 28 '18 at 13:00
1

It's not that simple, and of course "it depends":

I can't remember where, but I think I remember reading Roger Johansson write something along the lines of "Don't queue messages using an enterprise queue if your actors will be the only consumers".

what this is referring to, is the super high cost of serialising a message via an enterprise bus (not in memory), that in order to make "durable" has to first write to persistent storage, typically disk, and get confirmation of successful write before continuing. (plus other costs, serialisation, deserialisation, network latency, packet re-combination, etc etc) This can be up to 100 000 times slower (random really huge number, but you get my point) than class A calling method of class B, or class A using Mediator to class B. In process method calls are guaranteed to be ACID, and while they're not durable, if you 're 100 000 faster, then replaying the entire message chain if failed is a responsiblity of the parent, typically with it's own try catch. so system crashes, so what (I laugh in the face of system failures mwaaa! "mini me" strokes cat) , when it starts it goes, oh, so-and-so saga didn't complete, replay it, and all it's child messages get replayed.

The key lesson here is make the entry point message to the micro service "durable" and for all internal messages make them fast as heck, and idempotent. (really rough paraphrasing here)

TLDR; entry point to micro-service should be your service processing a message picked up from some durable message bus. Internally, consider using patterns like an in memory bus, or an actor framework, eg libraries like Akka.net, TPL DataFlow etc and as far as possible, designs that don't require durability anywhere other than at the incoming and outgoing edges of the main message processing pipeline.

  • In memory message bus typically does not "queue" work, i.e. Gregory Young's FakeBus linked to above just starts the work in a background thread, so you have to worry about concurrency.
  • Concurrency frameworks, like Akka.net and TPL DataFlow give you high and low level tools respectively for managing work (thread) concurrency. Eliminating a large portion of software engineering problems. Akka.net focuses on higher abstractions around the actor pattern, wheras TPL DataFlow provides low level thread "Pipeline" concurrency management. I highly recommend you complete introductory training on both, before you choose either tool.

If you work on your own, are highly detailed, or writing a library, then possibly consider TPD DataFlow. If you're working in a large team, and building mainly business applications, consider Akka.net or similar actor frameworks.

Message Bus

  • use to send the big Domain Commands or events. e.g. InvoiceCreated, PaymentMade
  • use at entry and exit of micro services

Mediator Pattern

  • as described further up, use to simplify code. In my experience it makes code less brittle, and easier to refactor and easier to read (scan) quickly.
  • typically it makes DI a lot cleaner, without having to have such huge complex dependencies injected.
  • does not make messages durable, does not do anything for concurrency

In memory Bus

  • high speed way of decoupling components
  • Use for handling private, internal messages between components of the service.
  • as the service grows, a service might become a collaboration of micro services. only use an in memory bus to communicate between microservices when there is a parent that can supervise any long running sagas. Typically the durability of the entire saga might be managed by the parent as a result of responding to a durable "message bus" message.

Finally, since I haven't yet answered the OP's question -> "Is it appropriate to use an InMemory Bus for a single Microservice (for domain events) and a durable Message bus for integration events (between Microsservices)?"

I'd say... yes, spot on.

Hope this helps?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.