kafka producer 拉取元数据

在这里插入图片描述

1、主线程尝试啦取元数据
2、唤醒sender线程并wait等待拉取完成,sender线程通过NetWorkClient从kafka集群拉取元数据
3、kafka集群给networkclient返回元数据响应
4、拉取到元数据以后,跟新version版本号,并唤醒主线程
5、主线程继续往下执行

/**
 * 步骤一:
 *      同步等待拉取元数据。
 *  maxBlockTimeMs 最多能等待多久。
 */
ClusterAndWaitTime clusterAndWaitTime = waitOnMetadata(record.topic(), record.partition(), maxBlockTimeMs);
 ...
 /**
   * 很明显,真正去获取元数据是这个线程完成。
    */
   waitOnMetadata.sender.wakeup();  -> this.sender = new Sender -> sender.run -> this.client.poll(pollTimeout, now);
     ->  this.selector.poll 
     -> handleCompletedReceives -> metadataUpdater.maybeHandleCompletedReceive -> handleResponse
       -> this.metadata.update(cluster, now);
           public synchronized void update(Cluster cluster, long now) {
    
    
                // 更新版本号,metadata.awaitUpdate   while (this.version <= lastVersion) 退出循环
                this.version += 1;
                ...
                //直接把刚刚传进来的对象赋值给了这个cluster。
	            //cluster代表的是kafka集群的元数据。
	            //初始化的时候,update这个方法没有去服务端拉取数据。
	            this.cluster = cluster;//address
	            ... 
	            // 唤醒awaitUpdate.wait
	            notifyAll(); 
		   }
-----------------------------------------------------------------------------
   waitOnMetadata.metadata.awaitUpdate(version, remainingWaitMs);
    public synchronized void awaitUpdate(final int lastVersion, final long maxWaitMs) throws InterruptedException {
    
    
        if (maxWaitMs < 0) {
    
    
            throw new IllegalArgumentException("Max time to wait for metadata updates should not be < 0 milli seconds");
        }
        //获取当前时间
        long begin = System.currentTimeMillis();
        //看剩余可以使用的时间,一开始是最大等待的时间。
        long remainingWaitMs = maxWaitMs;
        /**version是元数据的版本号。
        //如果当前的这个version小于等于上一次的version。
        //说明元数据还没更新。
        //因为如果sender线程那儿 更新元数据,如果更新成功了,sender线程肯定回去累加这个version。*/
        while (this.version <= lastVersion) {
    
    
            //如果还有剩余的时间。
            if (remainingWaitMs != 0)
                //让当前线程阻塞等待。
                //我们这儿虽然没有去看 sender线程的源码
                //但是我们知道,他那儿肯定会做这样的一个操作
                //如果更新元数据成功了,会唤醒这个线程。
                //这儿被唤醒有两个情况:要么获取到元数据了,被sender线程唤醒,要么就是时间到了。
                wait(remainingWaitMs);
            //如果代码执行到这儿 说明就要么就被唤醒了,要么就到点了。
            //计算一下花了多少时间。
            long elapsed = System.currentTimeMillis() - begin;
            //已经超时了
            if (elapsed >= maxWaitMs)
                //报一个超时的异常。
                throw new TimeoutException("Failed to update metadata after " + maxWaitMs + " ms.");
            //再次计算 可以使用的时间。
            remainingWaitMs = maxWaitMs - elapsed;
        }
    }

猜你喜欢

转载自blog.csdn.net/m0_46449152/article/details/114855103