【生产者篇】拦截器源码分析

生产者拦截器可以对消息进行预处理。分析下KafkaProducer的拦截器相关源码

1、拦截消息的地方

调用KafkaProduer的send方法时候第一步就是拦截器对消息进行处理:

public Future<RecordMetadata> send(ProducerRecord<K, V> record, Callback callback) {
    //拦截器处理
    ProducerRecord<K, V> interceptedRecord = this.interceptors.onSend(record);
    //发送消息后续操作
    return doSend(interceptedRecord, callback);
}
2、interceptors初始化时机

在KafkaProduer实例化时机读取配置中的interceptor.classes获取配置的拦截器组。然后使用ProducerInterceptors进行包装

//KafkaProduer核心构造方法  忽略无关代码
//...
List<ProducerInterceptor<K, V>> interceptorList = (List)(new ProducerConfig(userProvidedConfigs, false))
    .getConfiguredInstances(ProducerConfig.INTERCEPTOR_CLASSES_CONFIG, ProducerInterceptor.class);
//初始化拦截器
this.interceptors = new ProducerInterceptors<>(interceptorList);
//...

默认值初始化是个空集合:

properties.put("interceptor.classes", "全类名");
interceptor.classes从源码配置找到:
properties.put(ProducerConfig.INTERCEPTOR_CLASSES_CONFIG, "全类名");
/**
初始化源码:
.define(INTERCEPTOR_CLASSES_CONFIG,Type.LIST,Collections.emptyList().... 
这里的全类名在源码中初始化的时候是一个配置list类型,
在KafkaProducer核心的构造方法中:也就是实例化KafkaProducer会读取自定义的拦截器集合。
*/

3、拦截器容器:ProducerInterceptors类

【生产者篇】拦截器源码分析_第1张图片

ProducerInterceptors 拦截器容器,持有一组拦截器链 List> interceptors

拦截器是有顺序的,就是配置顺序

onSend(),方法就是按照配置顺序依次执行每个自定义拦截器重写的onsend方法,这个方法,如果有中途的拦截器抛出异常,那就继续执行下一个拦截器进行处理,该拦截器失效。

onAcknowledgement(),就是收到ack的回调方法,每个拦截器都会执行,

onSendError(),发送失败的回调方法,每个拦截器都会

拦截器接口:

自定义拦截器的onAcknowledgement方法先于callback被调用见
博客5-1 2.2分析


ProducerInterceptor
//拦截器执行的方法
 public ProducerRecord<K, V> onSend(ProducerRecord<K, V> record);
//当收到ack或者发送失败异常将会被调用
//类似于send方法的callback,但是先于callback被调用
//这个方法execute in the background I/O thread ,所以尽量不要使用什么复杂或者耗时操作,
//避免性能损耗
 public void onAcknowledgement(RecordMetadata metadata, Exception exception);
4、拦截处理onSend()源码:
public ProducerRecord<K, V> onSend(ProducerRecord<K, V> record) {
    ProducerRecord<K, V> interceptRecord = record;
    //遍历interceptors中的拦截器,依次执行onSend方法,默认没有拦截器,for内部不执行
    for (ProducerInterceptor<K, V> interceptor : this.interceptors) {
        try {
            //如果有中途的拦截器抛出异常,那就继续执行下一个拦截器进行处理,该拦截器作用失效。
            interceptRecord = interceptor.onSend(interceptRecord);
        } catch (Exception e) {
            // do not propagate interceptor exception, log and continue calling other interceptors
            // be careful not to throw exception from here
            if (record != null)
                log.warn("Error executing interceptor onSend callback for topic: {}, partition: {}", record.topic(),
                    record.partition(), e);
            else
                log.warn("Error executing interceptor onSend callback", e);
        }
    }
    return interceptRecord;
}

n(“Error executing interceptor onSend callback”, e);
}
}
return interceptRecord;
}


你可能感兴趣的:(Kafka,kafka2.0,源码分析)