组件版本
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-stream-kafka</artifactId>
<version>2.1.4.RELEASE</version>
</dependency>
背景信息
stream-binder 通过绑定 channel 发送消息很方便,
但 MessageChannel中 send 方法只接收 Message 参数无法指定 partitionKey;
default boolean send(Message<?> message) {
return send(message, INDEFINITE_TIMEOUT);
}
boolean send(Message<?> message, long timeout);
网友推荐
方法 如下
// 指定
partitionKeyExtractorClass
partitionSelectorClass
partitionKeyExpression
需要自己定义Bean并且 实现对应的接口,略显麻烦。
自查源码
可以在构造 Message 时,设置 header信息 来指定 messageKey,后续会用作选取partition。
// partitionKey 为自定义的 业务key (String类型)
setHeader(KafkaHeaders.MESSAGE_KEY, partitionKey.getBytes())
理论依据
在 KafkaProducerMessageHandler 中 有相应的处理逻辑:
// org.springframework.integration.kafka.outbound.KafkaProducerMessageHandler.handleRequestMessage(); L348
protected Object handleRequestMessage(final Message<?> message) {
MessageHeaders messageHeaders = message.getHeaders();
String topic = this.topicExpression != null ?
this.topicExpression.getValue(this.evaluationContext, message, String.class)
: messageHeaders.get(KafkaHeaders.TOPIC, String.class);
Assert.state(StringUtils.hasText(topic), "The 'topic' can not be empty or null");
Integer partitionId = this.partitionIdExpression != null ?
this.partitionIdExpression.getValue(this.evaluationContext, message, Integer.class)
: messageHeaders.get(KafkaHeaders.PARTITION_ID, Integer.class);
// 优先级低于 messageKeyExpression
Object messageKey = this.messageKeyExpression != null
? this.messageKeyExpression.getValue(this.evaluationContext, message)
: messageHeaders.get(KafkaHeaders.MESSAGE_KEY);
Long timestamp = this.timestampExpression != null
? this.timestampExpression.getValue(this.evaluationContext, message, Long.class)
: messageHeaders.get(KafkaHeaders.TIMESTAMP, Long.class);
...
}
DefaultPartitioner 根据 keyBytes 选取 partition
// org.apache.kafka.clients.producer.internals.DefaultPartitioner.partition L69
// hash the keyBytes to choose a partition
return Utils.toPositive(Utils.murmur2(keyBytes)) % numPartitions;