我们可以通过spring.cloud.stream.kafka.bindings.springCloudBusInput.consumer.group来指定默认总线topic:spingCloudBus的consumer group,比如设置成${spring.application.name}:${spring.application.index},这样我们在kafka manager界面上可以方便的识别出某个服务的offset消费情况。
默认情况下group是一个随机值,在KafkaMessageChannelBinder类的createConsumerEndpoint开头代码:
boolean anonymous = !StringUtils.hasText(group);
Assert.isTrue(!anonymous || !extendedConsumerProperties.getExtension().isEnableDlq(),
"DLQ support is not available for anonymous subscriptions");
String consumerGroup = anonymous ? "anonymous." + UUID.randomUUID().toString() : group;
该类中另外一个方法:
private ConsumerFactory, ?> createKafkaConsumerFactory(boolean anonymous, String consumerGroup,
ExtendedConsumerProperties consumerProperties) {
Map props = new HashMap<>();
props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, ByteArrayDeserializer.class);
props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, ByteArrayDeserializer.class);
props.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, false);
props.put(ConsumerConfig.AUTO_COMMIT_INTERVAL_MS_CONFIG, 100);
if (!ObjectUtils.isEmpty(configurationProperties.getConfiguration())) {
props.putAll(configurationProperties.getConfiguration());
}
if (ObjectUtils.isEmpty(props.get(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG))) {
props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, this.configurationProperties.getKafkaConnectionString());
}
if (!ObjectUtils.isEmpty(consumerProperties.getExtension().getConfiguration())) {
props.putAll(consumerProperties.getExtension().getConfiguration());
}
props.put(ConsumerConfig.GROUP_ID_CONFIG, consumerGroup);
props.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, anonymous ? "latest" : "earliest");
return new DefaultKafkaConsumerFactory<>(props);
}
将通过是否是anonymous来设置auto.offset.reset是从latest还是earliest开始消费,即一个新的group将从最开始还是从最新offset开始消费。
这样如果你设置了group,那么将会从earliest开始消费,那么原来这个topic上的消息将会重新被消费一遍。
这就导致如果我们想从latest开始消费,就不能够定制group name了。该BUG出现在目前最新的GA版本(Dalston.SR3),对应的spring-cloud-stream-binder-kafka是1.2.1版本,1.2.1以上版本修复了这个问题:https://github.com/spring-cloud/spring-cloud-stream-binder-kafka/commit/7355ada4613ad50fe95430f1859d4ea65f004be1#diff-b0b05f37655e15c59cb8dfee2cc5353d
:
private ConsumerFactory, ?> createKafkaConsumerFactory(boolean anonymous, String consumerGroup,
ExtendedConsumerProperties consumerProperties) {
Map props = new HashMap<>();
props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, ByteArrayDeserializer.class);
props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, ByteArrayDeserializer.class);
props.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, false);
props.put(ConsumerConfig.AUTO_COMMIT_INTERVAL_MS_CONFIG, 100);
+ props.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, anonymous ? "latest" : "earliest");
+
if (!ObjectUtils.isEmpty(configurationProperties.getConfiguration())) {
props.putAll(configurationProperties.getConfiguration());
}
if (ObjectUtils.isEmpty(props.get(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG))) {
props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, this.configurationProperties.getKafkaConnectionString());
}
if (!ObjectUtils.isEmpty(consumerProperties.getExtension().getConfiguration())) {
props.putAll(consumerProperties.getExtension().getConfiguration());
}
+
props.put(ConsumerConfig.GROUP_ID_CONFIG, consumerGroup);
- props.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, anonymous ? "latest" : "earliest");
+ if (!ObjectUtils.isEmpty(consumerProperties.getExtension().getStartOffset())) {
+ props.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, consumerProperties.getExtension().getStartOffset().name());
+ }
+
return new DefaultKafkaConsumerFactory<>(props);
}
如果有设置startOffset属性的话,将根据该属性重新赋值,这样我们就可以改变group名称,然后将spring.cloud.stream.kafka.bindings.springCloudBusInput.consumer.startOffset=latest来设置从最新开始消费。
另外http://cloud.spring.io/spring-cloud-static/Dalston.SR3/#_configuration_options_2的官方文档上的描述其实跟实际代码内容不符,估计是patch忘记打上去了:
resetOffsets Whether to reset offsets on the consumer to the value provided by startOffset
.
Default: false
.
The starting offset for new groups, or when resetOffsets
is true
. Allowed values: earliest
, latest
. If the consumer group is set explicitly for the consumer 'binding' (via spring.cloud.stream.bindings.
), then 'startOffset' is set to earliest
; otherwise it is set to latest
for the anonymous
consumer group.
Default: null (equivalent to earliest
).