producer拦截器(二)

265 阅读1分钟

类似的我们再写一个拦截器ProducerInterceptorAnalysis2。两个拦截器的作用都是在发送前添加前缀

@Override
public ProducerRecord<String, String> onSend(ProducerRecord<String, String> record) {
    String modifiedValue = "th-" + record.value();
    return new ProducerRecord<>(record.topic(), record.partition(), record.timestamp(), record.key(), modifiedValue,
            record.headers());
}
 
@Override
public void close() {
    System.out.println("[INFO] 拦截器B CLOSED");
}

修改配置文件的最后一行,多个拦截器之间以逗号隔开

properties.put(ProducerConfig.INTERCEPTOR_CLASSES_CONFIG,
                ProducerInterceptorAnalysis.class.getName() + "," + ProducerInterceptorAnalysis2.class.getName());

先观察效果 很明显,调用顺序 A > B, 关闭顺序 B > A,这与Springmvc是一致的。接下来看看kafka是如何实现的.在org.apache.kafka.clients.producer.internals下的ProducerInterceptors.class中打断点走一下流程,其他几个方法也差不多,都是利用迭代器。

private final List<ProducerInterceptor<K, V>> interceptors;
 
public ProducerRecord<K, V> onSend(ProducerRecord<K, V> record) {
    ProducerRecord<K, V> interceptRecord = record;
    Iterator var3 = this.interceptors.iterator();
 
    while(var3.hasNext()) {
        ProducerInterceptor interceptor = (ProducerInterceptor)var3.next();
 
        try {
            interceptRecord = interceptor.onSend(interceptRecord);
        } catch (Exception var6) {
            if (record != null) {
                log.warn("Error executing interceptor onSend callback for topic: {}, partition: {}", new Object[]{record.topic(), record.partition(), var6});
            } else {
                log.warn("Error executing interceptor onSend callback", var6);
            }
        }
    }
 
    return interceptRecord;
}

再看一下在producer中拦截器的调用时机


public Future<RecordMetadata> send(ProducerRecord<K, V> record) {
    return this.send(record, (Callback)null);
}
 
public Future<RecordMetadata> send(ProducerRecord<K, V> record, Callback callback) {
    //interceptors的类型是ProducerInterceptors,onSend()会链式执行所有拦截器的onSend()方法
    ProducerRecord<K, V> interceptedRecord = this.interceptors.onSend(record);
    return this.doSend(interceptedRecord, callback);
}