I want to develop solutions that can dynamically route messages to different queues (more than 10000 queues). That's what I have so far:
- Exchange with type set to
topic
. So that I can route messages to different queues based on routing keys. - 10000 queues that have routing key as
#.%numberOfQueue.#
. The%numberOfQueue%
is simple numeric value for that queue (but it might be changed for more meaningfull ones). - Producer producing message with routing key like that:
5.10.15.105.10000
which means that message should be routed to queue with keys 5, 10, 15, 105 and 10000 as they comform the patterns of that queues.
That's how it looks like from java client 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);
}
That's how routingKey
generated for all messages for queues from 0 to 9998:
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;
}
Seems good. The problem is that I can't use such long routingKey
with channel.basicPublish()
method:
Exception in thread "main" java.lang.IllegalArgumentException: Short string too long; utf-8 encoded length = 48884, max = 255. at 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) at com.rabbitmq.client.impl.Method.toFrame(Method.java:85) at com.rabbitmq.client.impl.AMQCommand.transmit(AMQCommand.java:104) at com.rabbitmq.client.impl.AMQChannel.quiescingTransmit(AMQChannel.java:396) at com.rabbitmq.client.impl.AMQChannel.transmit(AMQChannel.java:372) at com.rabbitmq.client.impl.ChannelN.basicPublish(ChannelN.java:690) at com.rabbitmq.client.impl.ChannelN.basicPublish(ChannelN.java:672) at com.rabbitmq.client.impl.ChannelN.basicPublish(ChannelN.java:662) at com.rabbitmq.client.impl.recovery.AutorecoveringChannel.basicPublish(AutorecoveringChannel.java:192)
I have requirements:
- Dynamically choose from producer in which queues produce the messages. It might be just one queue, all queues or 1000 queues.
- I have more than 10000 different queues and it might be needed to produce same message to them.
So the questions are:
- Can I use such long key? If can - how to do it?
- Maybe I can achieve the same goal by different configuration of
exchange
or queues? - Maybe there are some hash function that can effectivily distinguesh destinations and collapse that in 255 symbols? If so, It should provide way to deal with different publishings (for example how to send to only queues numbered 555 and 8989?)?
- Maybe there are some different key strategy that could be used in that way?
- How else I can achieve my requirements?