3

I am about to make a Domain Driven Design arround RabbitMQ queue, and I am totally new to this. I would like to know if there are some guidelines for identifying the different queues considering the bounded contexts.

Stuffs like one queue per bounded context, or one queue per resource type within bounded contexts.

And since queues will normally cross different bounded contexts, it makes thing more complicated.

Any advice ?

acmoune
  • 2,981
  • 3
  • 24
  • 41

3 Answers3

2

There are 2 major "concerns" (layers) that I tend to use.

For any reasonably sized software system I would use a queue per bounded context that is only concerned commands from the BC in question. The endpoint handling the messages would be named along the lines of System.BoundedContextA.Server and this endpoint would handle only commands from BoundedContextA.

For any orchestration "owned" by BoundedContextA I would have another endpoint/queue handling events that pertain to the orchestration. This endpoint does not handle only messages related to BoundedContextA but also messages from other BCs that may be involved with the orchestration. This endpoint would be named along the lines of System.BoundedContextA.Orchestration.

The endpoints could be scaled horizontally and it is especially easy when using RabbitMQ.

Eben Roux
  • 12,983
  • 2
  • 27
  • 48
  • Thank you very much, but I don't understand what you mean by Orchestration, please can you explain that ? – acmoune May 19 '19 at 12:52
  • It is ok, I got it from here https://www.youtube.com/watch?v=9gW9WTu1pS4. Thanks again. – acmoune May 19 '19 at 13:07
  • Just to confirm, when considering a business process, an Orchestration is when a microservice acts like the master microservice, giving tasks to others workers microservices, in other to complete the business process. The others don't stand on their own, they are there to support the master. – acmoune May 19 '19 at 14:08
  • So to comeback to our concern, a Microservice can be involve in many orchestrations, some where it is a worker, and others where it is the master, and each of those orchestrations will deserve a queue, Right ? – acmoune May 19 '19 at 14:12
  • It is just like having one queue per business process, and a single microservice might be involved in many business processes. – acmoune May 19 '19 at 14:31
  • I wouldn't go as far as having a queue per process or message type although you could configure your endpoints as such. The "base" microservice/BC endpoint is only concerned with functionality in the BC and for all intents and purposes other BCs do not exist for it. The orchestration endpoint acts as an integration layer of sorts and typically interacts with various BCs. Using my service bus (Shuttle.Esb) in the .Net space a single endpoint can handle multiple messages or be configured to be more fine-grained by handling specific messages depending on what arrives in the inbox queue. – Eben Roux May 19 '19 at 16:01
1

Domain-Driven Design itself does not prescribe such patterns or guidelines. But it does prescribe that you design around your domain, and not around infrastructure details such as brokers, queues, etc.

That said; and supposing you are doing OOP, treating your domain objects as first class citizens will likely mean that you will fully decouple your domain from your infrastructure, and thus invite common patterns that are good at this, such as hexagonal architecture.

Even then, DDD does not prescribe a particular integration approach either; The fact that you ask about queues indicates that you are considering Asynchronous Integration. There is nothing wrong with that, but it always pays off to defer architecture decisions. Especially if you are "about to" discover this domain through DDD. Try to start simple, loosely-coupled but monolith-first, you might discover that you don't even need queues at all.

Having considered all of the above, in an asynchronous integration scenario with RabbitMQ, it is common to use a pub-sub pattern. All relevant events are published to one exchange without a specific consumer in mind. Consumers set up their own queues and bindings as they require, so there is no one formula that works:

  • One queue per event type per consumer
  • One queue per consumer with multiple bindings for event types or topic patterns
  • Queues shared among consumer instances for load balancing
  • ... and many combinations of these.
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
istepaniuk
  • 4,016
  • 2
  • 32
  • 60
  • Thanks. I got it. When you understand that each consumer set up its queues, everything become clear, it just needs to know where to publish its results. I put queues in plural because a consumer may subscribe to many queues. Do you think it is a good thing ? Should the consumer be broken into many consumers, one for each queue ? or should those queues be merged in one ? – acmoune May 20 '19 at 21:21
  • @acmoune "results" in the form of more events, are published to that same exchange for any part interested. If you are thinking of query style results, those should probably be handled synchronously, ie: just code (embedded domain), REST, etc. You don't mention stack; "consumer" is a vague term here; if you mean service/deployable, then use just ONE until obvious (again, monolith-first, no microservices). In my experience it is easier to run if you have queues per message type, but this will depend on the failure modes & how well your domain and implementation tolerates out-of-order events. – istepaniuk May 21 '19 at 10:16
0

You need one queue per type of consumer.

Consider a type of consumer C1 that handles events of type E1 and E2. A queue Q1 is required into which all events of type E1 and E2 are routed. If another type of consumer C2 handles events of type E3 and E4, an queue Q2 is required into which all events of type E3 and E4 are routed.

  • Is it good to have one actor consuming from more than one queue, on does that means that the queues should be merged somehow, or that the actor is doing too much and must be splitted into two or more actors ? – acmoune May 18 '19 at 21:00
  • One guy did an interesting answer then it was deleted. He said that the queues are not part of the DDD except I am designing a new Rabbit, and that they are just part of the communication infrastructure. I totally agree. My question is not on DDD itself, but as he said, it is instead on how to identify or choose the right queues from rabbitMQ to transport the messages in my DDD. A domain entity should consume events somehow. – acmoune May 18 '19 at 21:32
  • "Consider a type of consumer C1 that handles events of type E1 and E2. A queue Q1 is required into" is not quite true. A consumer can consume multiple queues, E1 and E2 could be in different queues. – istepaniuk May 20 '19 at 11:44