RabbitMQ using custom headers to store message-parameters
Asked Answered
C

1

12

I'm new to RabbitMQ, and I'm somewhat lost in the documentation.

Currently, as an example, I'm trying to build a small mailer-service that listens to a queue, but I'm somewhat stuck on where I should put the parameters that my service has (destination, subject, ...)

Should I put them inside some encoded format (json), inside my messages, or should I use the header-construction, like the following example:

string message = "Hello World!";
var body = Encoding.UTF8.GetBytes(message);

var properties = new BasicProperties();
properties.Headers = new Dictionary<string, object>();
properties.Headers.Add("destination", "matthias123@localhost");

channel.BasicPublish(exchange: "", routingKey: "sendmail", basicProperties: properties,body: body);

Does using the headers offer additional benefits? Like, for example, would it be possible to filter messages that are sent to a specific destination?

Cadman answered 4/3, 2017 at 8:19 Comment(0)
S
19

I wouldn't use headers for what you are trying to do. That information belongs in the body of the message, in my opinion.

Look at it this way:

The body of the message should contain everything you need to complete the work requested. In this case, it would be the sender, subject, email content, etc.

Headers on the other hand, are bits of data about the AMQP message, not the message contents.

There's a lot of potential confusion here with your work to be done being "email". Too much overlap in terminology between the AMQP message, and email message.

That being said, I'll pick a different example of work to do: calculate the fibonacci sequence.

In this case, the message you send across rabbitmq would contain something like how many places of fibonacci to calculate up front and then how many to send back, after that.

For example you might send a message like this (as json in this case):

{
  start: 1,
  take: 3
}

This should produce a result of 1, 1, 2 because it starts at the first position and returns 3 items from the sequence.

Using your specific question and logic: should I put the start and take attributes into headers of the message?

No.

If I did, that would mean my message is empty as all of the information about the work to be done would be contained in the headers.

It doesn't make sense when I look at it this way because now there is no message to send... only headers.

On the other hand, if I keep these two points of data in the message body, the headers become more useful as a way to send metadata about the AMQP message itself... Not information about the content of the message, but information about the idea of the message.

In this case I'm saying that I want to return items from the fibonacci sequence. In other words, I'm engaging in RPC (remote procedure call) and am expecting a return value.

AMQP doesn't support return values directly. What I can do, however, is stuff a queue name into the headers and send the result to that queue. Then the code that requested the fibonacci numbers can listen to that queue and get the results.

So I might do something like this when sending the message:

var properties = new BasicProperties();
properties.Headers = new Dictionary();
properties.Headers.Add("return-queue", "fibreturn");

Here I'm setting up a "return-queue" header - information about the message, or request for information in this case - inside of the headers. The code that handles the fibonacci sequence will read this header and send the response back to this queue.

This is a better use of headers, as it makes the header store information about the message... In this case, where the response should be sent. The headers don't contain information about the actual work to be done, though. That is all stored in the message body directly.


P.S. I am purposely not using the "reply-to" property like you normally should, to do RCP. I'm using this as an example of why you shouldn't put your "destination" in the headers. For a better implementation of the fibonacci sequence idea, see the RMQ docs and how it uses "reply-to" correctly https://www.rabbitmq.com/tutorials/tutorial-six-dotnet.html

Since answered 5/3, 2017 at 13:9 Comment(3)
I think discouraging use of custom headers altogether is in appropriate. While I do agree that the data mentioned above belongs in the body there is valid case for setting customer message headers. For example specifying the message type with an x-type header so consumer can deserialize the payload.Suter
the header content-type is not a custom header.Wellman
(edit timed out). Plus, in this answer he suggests that you can put anything in the headers that is metadata ABOUT the payload. In fact, that's what headers are FOR. But the data you need to operate on? It should be in the payload. I'd caution against writing your letter on an empty envelope.Wellman

© 2022 - 2024 — McMap. All rights reserved.