RabbitMQ使用自定义标头来存储消息参数

mht*_*sbt 3 messaging rabbitmq

我是RabbitMQ的新手,我在文档中有些迷失.

目前作为一个例子,我正在尝试构建一个监听队列的小型邮件服务器.但我有点卡在我应该放置我的服务所具有的参数(目的地,主题,......)

我应该将它们放在某些编码格式(json)中,在我的消息中,还是应该使用header-construction,如下例所示:

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);
Run Code Online (Sandbox Code Playgroud)

使用标题是否提供额外的好处?例如,是否可以过滤发送到特定目的地的消息?

Der*_*ley 10

我不会使用标题来做你想做的事情.在我看来,这些信息属于信息的主体.

这样看:

消息正文应包含完成所请求工作所需的一切.在这种情况下,它将是发件人,主题,电子邮件内容等.

另一方面,标题是关于AMQP消息的数据位,而不是消息内容.

你的工作要做"电子邮件",这里有很多潜在的混淆.AMQP消息和电子邮件消息之间的术语重叠太多.

话虽这么说,我会选择一个不同的工作例子:计算斐波纳契数列.

在这种情况下,您通过rabbitmq发送的消息将包含一些信息,比如预先计算多少个斐波那契位置,然后再发送多少个.

例如,您可能会发送这样的消息(在本例中为json):

{
  start: 1,
  take: 3
}
Run Code Online (Sandbox Code Playgroud)

这应该产生一个结果,1, 1, 2因为它从第一个位置开始并从序列中返回3个项目.

使用您的特定问题和逻辑:我应该将starttake属性放入消息的标题中吗?

没有.

如果我这样做,那就意味着我的消息是空的,因为有关要完成的工作的所有信息都将包含在标题中.

当我以这种方式看待它时没有意义,因为现在没有消息要发送...只有标题.

另一方面,如果我将这两个数据点保留在消息体中,那么标头将变得更有用,作为发送有关AMQP消息本身的元数据的方式...不是有关消息内容的信息,而是有关消息的想法.

在这种情况下,我说我想从斐波那契序列中返回项目.换句话说,我正在参与RPC(远程过程调用)并期待返回值.

AMQP不直接支持返回值.但是,我可以做的是将队列名称填入标题并将结果发送到该队列.然后,请求斐波那契数字的代码可以监听该队列并获得结果.

所以我在发送消息时可能会这样做:

var properties = new BasicProperties();
properties.Headers = new Dictionary();
properties.Headers.Add("return-queue", "fibreturn");
Run Code Online (Sandbox Code Playgroud)

在这里,我正在设置一个"返回队列"标题 - 有关消息的信息,或者在这种情况下请求信息 - 在标题内.处理斐波那契序列的代码将读取此标头并将响应发送回此队列.

这是更好地使用标头,因为它使标头存储有关消息的信息......在这种情况下,应该发送响应.但是,标题不包含有关要完成的实际工作的信息.这些都直接存储在消息体中.


PS我故意不像你通常那样使用"回复"属性来做RCP.我正在使用它作为一个例子,说明为什么你不应该把你的"目的地"放在标题中.要更好地实现斐波那契序列的想法,请参阅RMQ文档以及它如何正确使用"回复" https://www.rabbitmq.com/tutorials/tutorial-six-dotnet.html

  • 我认为完全不鼓励使用自定义标头是适当的。尽管我确实同意上述数据属于正文,但在设置客户消息标题的情况下确实存在。例如,使用x型标头指定消息类型,以便使用者可以反序列化有效负载。 (2认同)