Flink1.11 只写到kafka的第一个分区

Flink1.11.1采用以下代码出现Flink写到kafka第一个分区的现象:

speStream.addSink(new FlinkKafkaProducer(kafkaTopicName, new KafkaProducerSchema(), props, Optional.of(new FlinkFixedPartitioner())));

结论&解决方法:是1.11.1的bug,已在1.11.2中修复,可升级至1.11.2解决。或者传入空的partitioner,如果自定义的paritioner为空,则采用轮询(round-robin)的方式:

 
speStream.addSink(new FlinkKafkaProducer(kafkaTopicName,new SimpleStringSchema(), props), Optional.empty());

speStream.addSink(new FlinkKafkaProducer(kafkaTopicName,new SimpleStringSchema(), props), Optional.ofNullable(null));

Optitional.ofNullable(null) 其实是调用了emoty()方法,返回了空实例,跟上面的Option.empty()一个道理

 

 

出现原因:调用了以下的构造函数:

步骤1、进入FlinkKafkaProducer(注意:咱们上面传入的第二个参数new KafkaProducerSchema()是kafkaSchema。不是keyedSchema)

Flink1.11 只写到kafka的第一个分区_第1张图片

 

 

步骤2、继续进入上面调用的this,可以看到下图中this中的第四个参数,new KafkaSerializationSchemaWrapper:

Flink1.11 只写到kafka的第一个分区_第2张图片

 

步骤3、继续进入步骤2中的this函数,由于我们传入的kafkaSchema是new KafkaSerializationSchemaWrapper,不为null,所以执行红框中的代码。它将FlinkKafkaPartitioner置为null,之前在1中传入FlinkFixedPartitioner是不是就没用?那还传这个参数干啥?(肯定是哪里用到了))

Flink1.11 只写到kafka的第一个分区_第3张图片
 

 

步骤4、上面构造函数走完了,我们看下invoke()函数(invoke函数用于将给定值写入接收器。 每个记录都会调用此函数)。在invoke中,kafkaSchema不为null,但是还需要确认的是KafkaSerializationSchemaWrapper是不是KafkaContextAware的instance呢。所以再去步骤2中看看我们传入的KafkaSerializationSchemaWrapper这个包装类吧~

Flink1.11 只写到kafka的第一个分区_第4张图片

 

5、KafkaSerializationSchemaWrapper:如下图,可以看到KafkaSerializationSchemaWrapper是KafkaContextAware的instance,所以在上面的步骤4中,执行了红框中的代码。那我们是怎么分区的呢,再具体看下在KafkaSerializationSchemaWrapper中,我们传入的第二个参数是FlinkFixedPartitioner这个分区器,看下FlinkFixedPartitioner是怎么分区的吧~

Flink1.11 只写到kafka的第一个分区_第5张图片

 

6、FlinkFixedPartitioner,可以看到在FlinkFixedPartitioner中的open方法中调用了this.parallelInstanceId = parallelInstanceI,而这个open方法并没有在KafkaSerializationSchemaWrapper中被调用。所以 this.parallelInstanceId默认为0,

在步骤5中的图中,67行代码partitioner.partition实际调用的FlinkFixedPartitioner种的partitioner方法,return partitions[parallelInstanceId % partitions.length]; 因为parallelInstanceId为0所以全部都写到kafka的第一个分区了。造成这个的原因是FlinkFixedPartitioner中的open方法没有被调用,如果调用了是不是就可以了?可以看下1.11.2中的KafkaSerializationSchemaWrapper类

Flink1.11 只写到kafka的第一个分区_第6张图片

 

 

7、1.11.2中的KafkaSerializationSchemaWrapper,下图红框中,果然调用了partitioner.open()!搜了下,确实是bug

https://issues.apache.org/jira/browse/FLINK-19285?jql=project%20%3D%20FLINK%20AND%20text%20~%20%22kafka%20partitioner%22

Flink1.11 只写到kafka的第一个分区_第7张图片

 

 

 


 

 

 

 

 

你可能感兴趣的:(flink,kafka)