【生产者篇】 KafkaProducer实例化-初始化配置

1、KafkaProducer构造方法

使用KafkaProducer的api之前需要得到一个KafkaProducer实例,梳理KafkaProducer的构造函数:KafkaProducer一共五个构造器:
【生产者篇】 KafkaProducer实例化-初始化配置_第1张图片

//核心构造器    
KafkaProducer(ProducerConfig config,
                  Serializer<K> keySerializer,
                  Serializer<V> valueSerializer,
                  Metadata metadata,
                  KafkaClient kafkaClient)

四个构造,都是调用的核心构造器,然后核心构造方法是一个非pulbic,不能直接使用,

在使用的时候选择public KafkaProducer(Properties properties),或者 public KafkaProducer(Map map)操作简单,也符合kafka一切可配置化的思想。

可以看到在调用核心构造方法时候,配置项已经转化为ProducerConfig对象。

2、KafkaProducer配置实现简介:
  1. KafkaProducer的用户和默认配置会在KafkaProducer实例化过程中初始化到KafkaProducer的

    producerConfig的成员变量中,private final ProducerConfig producerConfig;

  2. ProducerConfig类中定义了所有的KafkaProducer需要的配置,并且负责实现默认的配置初始化。

  3. AbstractConfig类是ProducerConfig的父类,ProducerConfig实现了将用户的配置覆盖默认配置,并且将配置分类,并提供了获取各种配置的api

分为已经使用配置:已经用到的配置

解析配置:就是用户配置+自定义配置,

原始用户配置:用户配置

默认配置:默认配置

3、KafkaProducer的配置初始化源码分析

以使用 KafkaProducer(Properties properties)的构造方法为线路进行源码分析。其他构造方法也是一样的。

将properties变成ProducerConfig对象
public KafkaProducer(Properties properties) {
    this(new ProducerConfig(properties), null, null, null, null);
}
初始化默认配置
    public ProducerConfig(Properties props) {
        /**调用父类
         * CONFIG是在静态代码块中进行的,静态代码块优先于构造方法
         *
         * 在这里CONFIG 对象已经被初始化了
         * 就是所有的默认的初始化配置已经完成。
         *
         * 调用父类进行解析配置
         */
        super(CONFIG, props);
    }
初始化默认配置的静态代码块
/**
 * 初始化默认配置的静态代码块
 * 所有的配置将会被CONFIG对象包装
 
  默认初始化60项配置
 *
 */
static {
    CONFIG = new ConfigDef().define(BOOTSTRAP_SERVERS_CONFIG, Type.LIST, Collections.emptyList(), new ConfigDef.NonNullValidator(), Importance.HIGH, CommonClientConfigs.BOOTSTRAP_SERVERS_DOC)
            .define(BUFFER_MEMORY_CONFIG, Type.LONG, 32 * 1024 * 1024L, atLeast(0L), Importance.HIGH, BUFFER_MEMORY_DOC)
.......
解析配置
/**
 * 解析配置
 *
 * @param definition 默认配置
 * @param originals  自定义配置
 * @param doLog
 */
public AbstractConfig(ConfigDef definition, Map<?, ?> originals, boolean doLog) {
    //校验配置key的类型
    for (Map.Entry<?, ?> entry : originals.entrySet())
        if (!(entry.getKey() instanceof String))
            throw new ConfigException(entry.getKey().toString(), entry.getValue(), "Key must be a string.");
    this.originals = (Map<String, ?>) originals;

    //解析用户配置到values中
    this.values = definition.parse(this.originals);
    Map<String, Object> configUpdates = postProcessParsedConfig(Collections.unmodifiableMap(this.values));
    for (Map.Entry<String, Object> update : configUpdates.entrySet()) {
        this.values.put(update.getKey(), update.getValue());
    }
    //解析默认配置到values中,
    definition.parse(this.values);

    //定义使用的配置
    this.used = Collections.synchronizedSet(new HashSet<String>());

    this.definition = definition;
    if (doLog)
        logAll();
}

先解析的用户配置,再解析的默认配置如何保证不被覆盖呢:

    public Map<String, Object> parse(Map<?, ?> props) {
        // Check all configurations are defined
        List<String> undefinedConfigKeys = undefinedDependentConfigs();
        if (!undefinedConfigKeys.isEmpty()) {
            String joined = Utils.join(undefinedConfigKeys, ",");
            throw new ConfigException("Some configurations in are referred in the dependents, but not defined: " + joined);
        }
        //遍历所有的配置项
        Map<String, Object> values = new HashMap<>();
        for (ConfigKey key : configKeys.values())
            //将所有的配值放进values.map中,value的计算
            values.put(key.name, parseValue(key, props.get(key.name), props.containsKey(key.name)));
        return values;
    }
/**
 *
 * @param key   配置项
 * @param value 用户value
 * @param isSet 用户定义的配置中是否包含该配置项
 * @return
 */
Object parseValue(ConfigKey key, Object value, boolean isSet) {
    Object parsedValue;
    if (isSet) {
        //如果包含则使用用户的value,就是props中的value
        parsedValue = parseType(key.name, value, key.type);
        // props map doesn't contain setting, the key is required because no default value specified - its an error
    } else if (NO_DEFAULT_VALUE.equals(key.defaultValue)) {
        throw new ConfigException("Missing required configuration \"" + key.name + "\" which has no default value.");
    } else {
        // 如果不包含则使用默认的value
        parsedValue = key.defaultValue;
    }
    if (key.validator != null) {
        key.validator.ensureValid(key.name, parsedValue);
    }
    return parsedValue;
}
4、改写入门demo生产者代码
  public static void main(String[] args) {
        KafkaProducer<String, String> producer =new KafkaProducer<>(initProperties());
        ProducerRecord<String, String> record = 
            new ProducerRecord (topic,"hellotest","hellotest");
                producer.send(record);
                producer.flush();
                producer.close();
    }
/**
 * 将配置提取, ProducerConfig 维护着需要的各种配置
 * 生产者需要的任何配置都可以在这里一 一添加
 */
public static Properties initProperties(){
    Properties properties = new Properties();
    properties.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG,
            StringSerializer.class.getName());
    properties.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG,
            StringSerializer.class.getName());
    properties.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, url);
    //.......其他配置
    return properties;
};
fig.VALUE_SERIALIZER_CLASS_CONFIG,
            StringSerializer.class.getName());
    properties.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, url);
    //.......其他配置
    return properties;
};

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