Search code examples
rabbitmqmicroservicesmessage-queuetask-queue

Is it wrong for a service to be producer and consumer of Rabbit MQ?


I want to create a "Notifications Microservice" that will handle different type of notifications (Google Chat, Email, etc).

For this task, we will create a microservice that contains the logic on how to process these messages, and we'll be using Rabbit MQ to manage the queue.

Now, the question that I have, is if it is possible (or if it is a bad practice) to expose two endpoints in the microservice like this:

registerNotification('channel', $data)

processNotification(Rabbit Message)

So I only have to implement the communication with RabbitMQ in one service, and other services will just register messages using this same service instead of directly talking to RabbitMQ. This way for each channel I could validate in the service that I have everything that I need before enqueuing a message.

Is this a good approach?


Solution

  • I'd suggest splitting your question into two separate ones. As usual, it depends ... there's pros and cons to either one. Below my points without claiming completeness. Assessing those really depends on your specific needs in the end.

    1) Is it a good practice to use a Notification / Event Gateway in front of a message queue (here RabbitMQ)?

    Pros:

    • enforce strong guarantees on message structure / correctness
    • provide advanced authentication / authorization mechanisms if required
    • provide convenience if languages in your stack lack first-class client support
    • abstract away / encapsulate technology choices & deployment considerations from services (publishers)
    • eliminate routing logic for messages from individual services (though, using available routing topologies in RabbitMQ, it's hard to see any added value here)

    Cons:

    • availability becomes a critical concern for your gateway, e.g. assuming you can guarantee an uptime of four nines per service, you are already down to three nines for the composed system by adding this dependency
    • added operational complexity
    • added latency

    An alternative consideration here might be to use a library to achieve some of the pros above. Though, this approach also comes with its own cons.

    2) Is it a good practice to run both message publishers and consumers in one service?

    Pros:

    • quick (shortcut?)
    • initially less deployed instances (until you have to scale up)

    Cons:

    • operational requirements for producers and consumers (workers!) are typically very different
    • harder (and more expensive) to scale the system adequately and fine grained
    • (performance) metrics become difficult to interpret
    • consumers might impact producer latency negatively as everything is competing for the same resources
    • loss of flexibility on the consumer side (quick, low risk deployments)
    • harder to guarantee availability of producers

    I hope this helps to better evaluate your architecture based on your own needs / priorities.