如何在RabbitMQ

时间:2017-09-08 10:18:10

标签: java rabbitmq messaging rabbitmq-exchange

我想开发可以将消息动态路由到不同队列(超过10000个队列)的解决方案。这就是我到目前为止所做的:

  • 使用设置为topic的类型进行交换。这样我就可以根据路由密钥将消息路由到不同的队列。
  • 10000个队列,其路由密钥为#.%numberOfQueue.#%numberOfQueue%是该队列的简单数值(但对于更有意义的队列,可能会更改)。
  • 生成器生成带有路由密钥的消息:5.10.15.105.10000这意味着消息应该通过密钥5,10,15,105和10000路由到队列,因为它们符合该队列的模式。

这就是从Java客户端API看起来的样子:

String exchangeName = "rabbit.test.exchange";
String exchangeType = "topic";
boolean exchangeDurable = true;
boolean queueDurable = true;
boolean queueExclusive = false;
boolean queueAutoDelete = false;
Map<String, Object> queueArguments = null;

for (int i = 0; i < numberOfQueues; i++) {
    String queueNameIterated = "rabbit.test" + i + ".queue";
    channel.exchangeDeclare(exchangeName, exchangeType, exchangeDurable);
    channel.queueDeclare(queueNameIterated, queueDurable, queueExclusive, queueAutoDelete, queueArguments);

    String routingKey = "#." + i + ".#";
    channel.queueBind(queueNameIterated, exchangeName, routingKey);
}

这就是{0}为0到9998队列的所有消息生成的routingKey

private String generateRoutingKey() {
    StringBuilder keyBuilder = new StringBuilder();
    for (int i = 0; i < numberOfQueues - 2; i++) {
        keyBuilder.append(i);
        keyBuilder.append('.');
    }
    String result = keyBuilder.append(numberOfQueues - 2).toString();
    LOGGER.info("generated key: {}", result);
    return result;
}

似乎很好。问题是我无法使用routingKey这种channel.basicPublish()方法:

  

线程“main”中的异常java.lang.IllegalArgumentException:短字符串太长; utf-8编码长度= 48884,最大值= 255。       在com.rabbitmq.client.impl.ValueWriter.writeShortstr(ValueWriter.java:50)       at com.rabbitmq.client.impl.MethodArgumentWriter.writeShortstr(MethodArgumentWriter.java:74)       at com.rabbitmq.client.impl.AMQImpl $ Basic $ Publish.writeArgumentsTo(AMQImpl.java:2319)       在com.rabbitmq.client.impl.Method.toFrame(Method.java:85)       在com.rabbitmq.client.impl.AMQCommand.transmit(AMQCommand.java:104)       在com.rabbitmq.client.impl.AMQChannel.quiescingTransmit(AMQChannel.java:396)       在com.rabbitmq.client.impl.AMQChannel.transmit(AMQChannel.java:372)       在com.rabbitmq.client.impl.ChannelN.basicPublish(ChannelN.java:690)       在com.rabbitmq.client.impl.ChannelN.basicPublish(ChannelN.java:672)       在com.rabbitmq.client.impl.ChannelN.basicPublish(ChannelN.java:662)       at com.rabbitmq.client.impl.recovery.AutorecoveringChannel.basicPublish(AutorecoveringChannel.java:192)

我有要求:

  • 从队列生成消息的生产者中动态选择。它可能只是一个队列,所有队列或1000个队列。
  • 我有超过10000个不同的队列,可能需要向他们发送相同的消息。

所以问题是:

  1. 我可以使用这么长的钥匙吗?如果能 - 怎么做?
  2. 也许我可以通过exchange或队列的不同配置实现相同的目标?
  3. 也许有一些哈希函数可以有效地分配目标并在255个符号中崩溃?如果是这样,它应该提供处理不同发布的方法(例如如何只发送到编号为555和8989的队列?)?
  4. 也许有一些不同的关键策略可以这样使用?
  5. 我还能达到我的要求吗?

1 个答案:

答案 0 :(得分:0)

我很久以前就开始使用RabbitQM了,希望我能帮助你。路由密钥中可以有多个单词,最多可达255个字节(如RabbitMQ Tutorial 5 - Topics中所述)。因此,主题交换似乎不适合您的用例。

在这种情况下,也许您可​​以使用headers exchange?根据概念描述:

  

标头交换设计用于在多个属性上进行路由,这些属性更容易表示为邮件头而不是路由密钥。标头交换忽略路由密钥属性。相反,用于路由的属性取自headers属性。如果标头的值等于绑定时指定的值,则认为消息是匹配的。

有关示例,请参阅herehere。正如我所说,我刚开始使用RabbitMQ,因此,我不确定这是否适合您。如果我以后有时间,我会尝试为你构建一个简单的例子。