Kafka producer pulls metadata

Insert picture description here

1. The main thread tries to fetch the metadata.
2. Wake up the sender thread and wait for the pull to complete. The sender thread pulls the metadata from the kafka cluster through NetWorkClient.
3. The kafka cluster returns the metadata response to the networkclient. 4. After the metadata is
pulled , Follow the new version number, and wake up the main thread
5. The main thread continues to execute

/**
 * 步骤一:
 *      同步等待拉取元数据。
 *  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;
        }
    }

Guess you like

Origin blog.csdn.net/m0_46449152/article/details/114855103