kafka consumer assign 和 subscribe模式差异分析
转载请注明原创地址:http://www.cnblogs.com/dongxiao-yang/p/7200971.html
最近需要研究flink-connector-kafka的消费行为,发现flink使用了kafka consumer一个比较底层一点的assign接口而不是之前比较常用的subscirbe,于是研究下二者之间的差异。
首先看api文档:http://kafka.apache.org/0110/javadoc/index.html?org/apache/kafka/clients/consumer/KafkaConsumer.html
public void assign(Collection<TopicPartition> partitions)
unsubscribe().
Manual topic assignment through this method does not use the consumer's group management functionality. As such, there will be no rebalance operation triggered when group membership or cluster and topic metadata change. Note that it is not possible to use both manual partition assignment with assign(Collection) and group assignment with subscribe(Collection, ConsumerRebalanceListener).
与subscirbe方法不同,assign方法由用户直接手动consumer实例消费哪些具体分区,根据api上述描述,assign的consumer不会拥有kafka的group management机制,也就是当group内消费者数量变化的时候不会有reblance行为发生。assign的方法不能和subscribe方法同时使用。
然后看一下具体实现源码:
public class KafkaConsumer<K, V> implements Consumer<K, V>{
...........
private final SubscriptionState subscriptions;
  public void subscribe(Pattern pattern, ConsumerRebalanceListener listener) {
...........
  this.subscriptions.subscribe(new HashSet<>(topics), listener);
...........
}
......
    public void assign(Collection<TopicPartition> partitions) {
...........
    this.subscriptions.assignFromUser(new HashSet<>(partitions));
...........
}
每一个KafkaConsumer实例内部都拥有一个SubscriptionState对象,subscribe内部调用了subscribe方法,assign内部调用了assignFromUser方法,看一下这两个方法的具体实现:
    private enum SubscriptionType {
        NONE, AUTO_TOPICS, AUTO_PATTERN, USER_ASSIGNED
    } 
 private void setSubscriptionType(SubscriptionType type) {
        if (this.subscriptionType == SubscriptionType.NONE)
            this.subscriptionType = type;
        else if (this.subscriptionType != type)
            throw new IllegalStateException(SUBSCRIPTION_EXCEPTION_MESSAGE);
    }
    public void subscribe(Set<String> topics, ConsumerRebalanceListener listener) {
        if (listener == null)
            throw new IllegalArgumentException("RebalanceListener cannot be null");
        setSubscriptionType(SubscriptionType.AUTO_TOPICS);
        this.listener = listener;
        changeSubscription(topics);
    }
    public void assignFromUser(Set<TopicPartition> partitions) {
        setSubscriptionType(SubscriptionType.USER_ASSIGNED);
        if (!this.assignment.partitionSet().equals(partitions)) {
            fireOnAssignment(partitions);
            Map<TopicPartition, TopicPartitionState> partitionToState = new HashMap<>();
            for (TopicPartition partition : partitions) {
                TopicPartitionState state = assignment.stateValue(partition);
                if (state == null)
                    state = new TopicPartitionState();
                partitionToState.put(partition, state);
            }
            this.assignment.set(partitionToState);
            this.needsFetchCommittedOffsets = true;
        }
    }
由上述代码可知,SubscriptionState 内部拥有一个SubscriptionType类型的枚举变量subscriptionType,枚举共拥有NONE, AUTO_TOPICS, AUTO_PATTERN, USER_ASSIGNED四种状态类型,subscribe方法会把subscriptionType状态设置为AUTO_TOPICS,assignFromUser会设置为USER_ASSIGNED。尤其是setSubscriptionType设置枚举的方法内部:else if (this.subscriptionType != type) throw new IllegalStateException(SUBSCRIPTION_EXCEPTION_MESSAGE); 代码保证了,如果同一个consumer已经调用了某一种订阅模式,再次试图更改为另一种模式的时候程序会直接抛出错误。
poll方法调用情况下的不同实现
上述两种模式初始化的consumer在fetch数据的时候调用的是同样的poll方法,每次poll会调用pollOnce方法内的
coordinator.poll(time.milliseconds());
具体源码如下
public void poll(long now) {
        invokeCompletedOffsetCommitCallbacks();
        if (subscriptions.partitionsAutoAssigned() && coordinatorUnknown()) {
            ensureCoordinatorReady();
            now = time.milliseconds();
        }
        if (needRejoin()) {
            // due to a race condition between the initial metadata fetch and the initial rebalance,
            // we need to ensure that the metadata is fresh before joining initially. This ensures
            // that we have matched the pattern against the cluster's topics at least once before joining.
            if (subscriptions.hasPatternSubscription())
                client.ensureFreshMetadata();
            ensureActiveGroup();
            now = time.milliseconds();
        }
        pollHeartbeat(now);
        maybeAutoCommitOffsetsAsync(now);
    }
    public boolean needRejoin() {
        if (!subscriptions.partitionsAutoAssigned())
            return false;
        // we need to rejoin if we performed the assignment and metadata has changed
        if (assignmentSnapshot != null && !assignmentSnapshot.equals(metadataSnapshot))
            return true;
        // we need to join if our subscription has changed since the last join
        if (joinedSubscription != null && !joinedSubscription.equals(subscriptions.subscription()))
            return true;
        return super.needRejoin();
    }
public boolean partitionsAutoAssigned() {
return this.subscriptionType == SubscriptionType.AUTO_TOPICS || this.subscriptionType == SubscriptionType.AUTO_PATTERN;
}
ConsumerCoordinator的poll方法会判断consumer的前述SubscriptionType类型,只有类型是AUTO_TOPICS或者AUTO_PATTERN(subscribe方法的另一种参数重载),才会与ConsumerCoordinator进行交互,判断是否需要reblance等行为。
所以正如api文档描述,assign的consumer不会拥有kafka的group management机制,也就是当group内消费者数量变化的时候不会有reblance行为发生。
kafka consumer assign 和 subscribe模式差异分析的更多相关文章
- 利用Kafka的Assign模式实现超大群组(10万+)消息推送
		
引言 IM即时通信场景下,最重要的一个能力就是推送:在线的直接通过长连接网关服务转发,离线的通过APNS或者极光等系统进行推送. 本文主要是针对在线用户推送场景来进行总结和探讨:如何利用Kafka ...
 - 读Kafka Consumer源码
		
最近一直在关注阿里的一个开源项目:OpenMessaging OpenMessaging, which includes the establishment of industry guideline ...
 - Apache Kafka Consumer 消费者集
		
1.目标 在我们的上一篇文章中,我们讨论了Kafka Producer.今天,我们将讨论Kafka Consumer.首先,我们将看到什么是Kafka Consumer和Kafka Consumer的 ...
 - 初始 Kafka Consumer 消费者
		
温馨提示:整个 Kafka 专栏基于 kafka-2.2.1 版本. 1.KafkaConsumer 概述 根据 KafkaConsumer 类上的注释上来看 KafkaConsumer 具有如下特征 ...
 - kafka consumer 配置详解
		
1.Consumer Group 与 topic 订阅 每个Consumer 进程都会划归到一个逻辑的Consumer Group中,逻辑的订阅者是Consumer Group.所以一条message ...
 - Kafka Consumer API样例
		
Kafka Consumer API样例 1. 自动确认Offset 说明参照:http://blog.csdn.net/xianzhen376/article/details/51167333 Pr ...
 - KafkaConsumer assign VS subscribe
		
背景 在kafka中,正常情况下,同一个group.id下的不同消费者不会消费同样的partition,也即某个partition在任何时刻都只能被具有相同group.id的consumer中的一个消 ...
 - 【原创】Kafka Consumer多线程实例
		
Kafka 0.9版本开始推出了Java版本的consumer,优化了coordinator的设计以及摆脱了对zookeeper的依赖.社区最近也在探讨正式用这套consumer API替换Scala ...
 - 【原创】kafka consumer源代码分析
		
顾名思义,就是kafka的consumer api包. 一.ConsumerConfig.scala Kafka consumer的配置类,除了一些默认值常量及验证参数的方法之外,就是consumer ...
 
随机推荐
- luogu P1855 榨取kkksc03
			
题目描述 以下皆为真实的故事. 洛谷2的团队功能是其他任何oj和工具难以达到的.借助洛谷强大的服务器资源,任何学校都可以在洛谷上零成本的搭建oj并高效率的完成训练计划. 为什么说是搭建oj呢?为什么高 ...
 - small test on 5.30 night  T1
			
数学题使劲推就对了. 让我们设 g(x) = ∑ C(i,x) * b^i ,然后后面验算了一张纸QWQ,懒得再打一遍了,回家我就把这张演算纸补上QWQ,先上代码. #include<cstd ...
 - 【莫队算法】【权值分块】bzoj3339 Rmq Problem
			
如题. #include<cstdio> #include<algorithm> #include<cmath> using namespace std; #def ...
 - 《深入理解Spark-核心思想与源码分析》(三)第三章SparkContext的初始化
			
3.1 SparkContext概述 SparkConf负责配置参数,主要通过ConcurrentHaspMap来维护各种Spark的配置属性. class SparkConf(loadDefault ...
 - 更新升级10.11 cocoapods安装出问题最简单的解决方法
			
这是因为10.11把cocoapods直接干掉了 sudo gem install -n /usr/local/bin cocoapods 再加一句,完美解决 sudo xcode-select -- ...
 - 在WPF中合并两个ObservableCollection
			
WPF中的ObservableCollection是一个非常常用的集合对象,我们可以通过将它绑定到ListBox之类的集合控件上时,当集合发生变更时,会同步更新到界面上.但是,有的时候我们需要合并两个 ...
 - Matlab与神经网络入门
			
第一节.神经网络基本原理 1. 人工神经元( Artificial Neuron )模型 人工神经元是神经网络的基本元素,其原理可以用下图表示: 图1. 人工神经元模型 图中x1~xn是从其他神经 ...
 - Android Service完全解析,关于服务你所需知道的一切
			
来自:http://www.360doc.com/content/14/0415/18/2793098_369238276.shtml 相信大多数朋友对Service这个名词都不会陌生,没错,一个老练 ...
 - 14、高可用keepalived搭建及切换
			
keepalived主从切换试验: 1.先搭建192.168.1.20与192.168.1.21的主主架构 192.168.1.76为VIP 2.在2机都安装keepalived tar - ...
 - pymongo增删查改以及条件查询
			
---恢复内容开始--- 下载Pymongo pip install pymongo pip install pymongo==x.x.x指定下载版本 连接数据库 from pymongo impor ...