使用RocketMQ发送Message时,Topic允许的最大长度是多少?

想找到这个问题的答案并不难,在发送Message前,RocketMQ client会对Message进行一些合法性校验:

1
2
3
4
5
6
7
@Override
public SendResult send(
Message msg) throws MQClientException, RemotingException, MQBrokerException, InterruptedException {
Validators.checkMessage(msg, this);
msg.setTopic(withNamespace(msg.getTopic()));
return this.defaultMQProducerImpl.send(msg);
}

其中就有对Topic的校验:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public static void checkTopic(String topic) throws MQClientException {
if (UtilAll.isBlank(topic)) {
throw new MQClientException("The specified topic is blank", null);
}

if (!regularExpressionMatcher(topic, PATTERN)) {
throw new MQClientException(String.format(
"The specified topic[%s] contains illegal characters, allowing only %s", topic,
VALID_PATTERN_STR), null);
}

if (topic.length() > CHARACTER_MAX_LENGTH) {
throw new MQClientException("The specified topic is longer than topic max length 255.", null);
}

//whether the same with system reserved keyword
if (topic.equals(MixAll.AUTO_CREATE_TOPIC_KEY_TOPIC)) {
throw new MQClientException(
String.format("The topic[%s] is conflict with AUTO_CREATE_TOPIC_KEY_TOPIC.", topic), null);
}
}

其中CHARACTER_MAX_LENGTH的值是255,因此我们可以得到结论,Topic的最大长度是255。

然而,假如我们用长度介于128~255之间的Topic发送消息时,会得到一个CODE 13的错误。

1
2
3
4
5
6
7
8
9
10
11
12
org.apache.rocketmq.client.exception.MQBrokerException: CODE: 13  DESC: the message is illegal, maybe msg body or properties length not matched. msg body length limit 128k, msg properties length limit 32k.
For more information, please visit the url, http://rocketmq.apache.org/docs/faq/
at org.apache.rocketmq.client.impl.MQClientAPIImpl.processSendResponse(MQClientAPIImpl.java:709)
at org.apache.rocketmq.client.impl.MQClientAPIImpl.sendMessageSync(MQClientAPIImpl.java:505)
at org.apache.rocketmq.client.impl.MQClientAPIImpl.sendMessage(MQClientAPIImpl.java:487)
at org.apache.rocketmq.client.impl.MQClientAPIImpl.sendMessage(MQClientAPIImpl.java:431)
at org.apache.rocketmq.client.impl.producer.DefaultMQProducerImpl.sendKernelImpl(DefaultMQProducerImpl.java:853)
at org.apache.rocketmq.client.impl.producer.DefaultMQProducerImpl.sendDefaultImpl(DefaultMQProducerImpl.java:583)
at org.apache.rocketmq.client.impl.producer.DefaultMQProducerImpl.send(DefaultMQProducerImpl.java:1342)
at org.apache.rocketmq.client.impl.producer.DefaultMQProducerImpl.send(DefaultMQProducerImpl.java:1288)
at org.apache.rocketmq.client.producer.DefaultMQProducer.send(DefaultMQProducer.java:324)
at org.apache.rocketmq.example.quickstart.Producer.main(Producer.java:63)

这又是怎么回事呢?

跟一下RocketMQ处理消息存储的方法org.apache.rocketmq.store.DefaultMessageStore#putMessage,里面有这么一段:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public PutMessageResult putMessage(MessageExtBrokerInner msg) {
// ......

if (msg.getTopic().length() > Byte.MAX_VALUE) {
log.warn("putMessage message topic length too long " + msg.getTopic().length());
return new PutMessageResult(PutMessageStatus.MESSAGE_ILLEGAL, null);
}

if (msg.getPropertiesString() != null && msg.getPropertiesString().length() > Short.MAX_VALUE) {
log.warn("putMessage message properties length too long " + msg.getPropertiesString().length());
return new PutMessageResult(PutMessageStatus.PROPERTIES_SIZE_EXCEEDED, null);
}

// ......
}

可以看到,当Topic的长度大于Byte.MAX_VALUE时,会拒绝该Message。然而Byte.MAX_VALUE的值是127。不知道在设计时RocketMQ设想的最大长度是127还是255,虽然在日常使用中几乎不会用到这么长的Topic,但这个校验的不一致还是可能带来一些困扰。
另外值得注意的是,properties的最大长度不能超过Short.MAX_VALUE,对应的值是32767,而并未有些文章或书所写的不能超过65536。

目前已提交PR给RocketMQ。