继续关于Kafka文档的阅读

This commit is contained in:
2023-03-02 13:18:51 +08:00
parent 44e6f4122f
commit f7f3ce18ba

View File

@@ -619,12 +619,17 @@ public interface BatchAcknowledgingConsumerAwareMessageListener<K, V> extends Ba
- ConcurrentMessageListenerContainer
KafkaMessageListenerContainer会在单线程中接收所有来自topic和分区的消息。ConcurrentMessageListenerContainer会委托给一个或多个KafkaMessageListenerContainer实例从而提供多线程的消费。
**RecordInterceptor**
可以添加一个RecordInterceptor到ListenerContainer在调用listener之前interceptor会被调用。record拦截器允许对record进行查看和修改。如果interceptor返回结果为null那么listener则不会被调用。而且其还有一个额外的方法可以在listener退出之后被调用退出之后指正常退出或以抛出异常的形式退出
还有一个BatchInterceptor提供了和BatchListener类似的功能。ConsumerAwareRecordInterceptor则是提供了访问consumer对象的功能。
如果想要调用多个Interceptor则是可以使用CompositeRecordInterceptor和CompositeBatchInterceptor。
默认情况下当使用事务时interceptor会在事务开始之前被调用。可以设置listener container的interceptBeforeTx属性为false来令interceptor的调用时机为事务开始之后。
ConcurrentMessageListenerContainer支持“静态成员”即固定消费者即使消费者实例重启如此可以降低事件在消费者之间重新负载均衡的开销当并发量大于1时。`group.instance.id`的后缀为`-n`其中n从1开始。
**KafkaMessageListenerContainer**
可以通过如下构造函数来使用MessageListenerContainer
```java
public KafkaMessageListenerContainer(ConsumerFactory<K, V> consumerFactory,ContainerProperties containerProperties)
@@ -638,3 +643,35 @@ public ContainerProperties(String... topics)
public ContainerProperties(Pattern topicPattern)
```
- 第一个构造方法接收一个TopicPartitionOffset的数组作为参数来显式指定container使用哪些分区通过consumer的assign方法并可以附带一个可选的初始offset。默认情况下如果offset为正值代表其是绝对的offset。若offset为负值则offset代表在默认分区中相对于current last offset的相对位置。并且对于TopicPartitionOffset类其提供了一个接收额外boolean参数的构造方法如果该值设置为true无论init offset为正值或者负值都是相对于consumer当前位置的相对值。当容器启动时offset将会被使用。
- 第二个构造方法接收一个topic数组并且kafka根据`group.id`属性来分配分区在group中对分区进行分配
- 第三个构造方法接收一个正则表达式根据正则表达式来选中topic
想要为容器指定一个MessageListener可以在创建容器时使用ContainerProps.setMessageListener方法。如下是创建容器时设置MessageListener的示例
```java
ContainerProperties containerProps = new ContainerProperties("topic1", "topic2");
containerProps.setMessageListener(new MessageListener<Integer, String>() {
...
});
DefaultKafkaConsumerFactory<Integer, String> cf =
new DefaultKafkaConsumerFactory<>(consumerProps());
KafkaMessageListenerContainer<Integer, String> container =
new KafkaMessageListenerContainer<>(cf, containerProps);
return container;
```
`missingTopicsFatal`可以控制topic不存在时container是否启动`missingTopicsFatal`的值默认为false。如果任一topic在broker中不存在那么container的启动会被终止。
**ConcurrentMessageListenerContainer**
`ConcurrentMessageListenerContainer`唯一的构造方法和`KafkaListenerContainer`类似,如下显示了构造方法的签名:
```java
public ConcurrentMessageListenerContainer(ConsumerFactory<K, V> consumerFactory,ContainerProperties containerProperties)
```
ConcurrentMessageListenerContainer还有一个concurrency属性例如`container.setConcurrency(3)`会创建3个`KafkaMessageListenerContainer`实例。
kafka会根据其组管理功能再消费者之间分配分区。
> **kafka分配策略**
> 当监听多个topic时默认的分区分配策略可能并不是想要的。例如有三个topic每个topic有5个分区那么将concurrency设置为15时只会看到5个活跃的consumer其余的10个consumer都会空闲。
> **RangeAssignor**
> 默认情况下kafka的分区分配策略是通过RangeAssignor来进行分配的其会将每个topic的分区在消费者group中所有消费者实例之间进行分配如果消费者实例数大于分区数则是会将消费者按字典顺序排序且分配分区给排序靠前的人。
> 故而在RangeAssignor策略下只有字典排序靠前的消费者实例才能在每个topic中分配到一个分区前5个消费者每个实例3个分区后面的10个消费者完全空闲。
> **RoundRobinAssignor**
> 相对于RangeAssignorRoundRobinAssingor则是会基于轮询在所有消费者之间均匀的分配所有的分区在上述情况下15个消费者实例每个都会分配到一个分区