使用KafkaProducer的api之前需要得到一个KafkaProducer实例,梳理KafkaProducer的构造函数:KafkaProducer一共五个构造器:
//核心构造器
KafkaProducer(ProducerConfig config,
Serializer<K> keySerializer,
Serializer<V> valueSerializer,
Metadata metadata,
KafkaClient kafkaClient)
四个构造,都是调用的核心构造器,然后核心构造方法是一个非pulbic,不能直接使用,
在使用的时候选择public KafkaProducer(Properties properties),或者 public KafkaProducer(Map map)操作简单,也符合kafka一切可配置化的思想。
可以看到在调用核心构造方法时候,配置项已经转化为ProducerConfig对象。
KafkaProducer的用户和默认配置会在KafkaProducer实例化过程中初始化到KafkaProducer的
producerConfig的成员变量中,private final ProducerConfig producerConfig;
ProducerConfig类中定义了所有的KafkaProducer需要的配置,并且负责实现默认的配置初始化。
AbstractConfig类是ProducerConfig的父类,ProducerConfig实现了将用户的配置覆盖默认配置,并且将配置分类,并提供了获取各种配置的api
分为已经使用配置:已经用到的配置
解析配置:就是用户配置+自定义配置,
原始用户配置:用户配置
默认配置:默认配置
以使用 KafkaProducer(Properties properties)的构造方法为线路进行源码分析。其他构造方法也是一样的。
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;
}
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;
};