Flink 1.11.1 FlinkKafkaProducer写入topic0分区问题记录

Flink 1.11.1 FlinkKafkaProducer写入topic0分区问题记录

  • 问题记录:

问题记录:

flink版本:1.11.1
使用FlinkKafkaProducer往下游发送数据,代码如下:

Properties props = new Properties();

            props.setProperty(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG,"kafkatest:9092");

            FlinkKafkaProducer producer = new FlinkKafkaProducer<>("partition_test_3",new SimpleStringSchema(),props);

            dataStream.flatMap(new RichFlatMapFunction() {
                @Override
                public void flatMap(String s, Collector collector) throws Exception {
                    int thisSubtask = getRuntimeContext().getIndexOfThisSubtask();
                    int parallelSubtasks = getRuntimeContext().getNumberOfParallelSubtasks();
                    System.out.println("thisSubtask:"+thisSubtask+", parallelSubtasks:"+parallelSubtasks+" value:"+s);
                    collector.collect(s);
                }
            }).addSink(producer);

上游kafkatopic有10个分区,flink开启10并行度消费topic,发现下游topic 三个partition,只有一个partition_0有数据。
Flink 1.11.1 FlinkKafkaProducer写入topic0分区问题记录_第1张图片
查看flink 1.11.1 FlinkKafkaProducer源码发现,最终创建FlinkKafkaProducer调用下图红框部分
Flink 1.11.1 FlinkKafkaProducer写入topic0分区问题记录_第2张图片其中:KafkaSerializationSchema 参数传递的是KafkaSerializationSchemaWrapper。而FlinkKakfaProducer在没有指定分区器的情况下默认使用的是
FlinkFixedPartitioner,源码如下:

public class FlinkFixedPartitioner extends FlinkKafkaPartitioner {

	private static final long serialVersionUID = -3785320239953858777L;

	private int parallelInstanceId;

	@Override
	public void open(int parallelInstanceId, int parallelInstances) {
		Preconditions.checkArgument(parallelInstanceId >= 0, "Id of this subtask cannot be negative.");
		Preconditions.checkArgument(parallelInstances > 0, "Number of subtasks must be larger than 0.");

		this.parallelInstanceId = parallelInstanceId;
	}

	@Override
	public int partition(T record, byte[] key, byte[] value, String targetTopic, int[] partitions) {
		Preconditions.checkArgument(
			partitions != null && partitions.length > 0,
			"Partitions of the target topic is empty.");

		return partitions[parallelInstanceId % partitions.length];
	}

	@Override
	public boolean equals(Object o) {
		return this == o || o instanceof FlinkFixedPartitioner;
	}

	@Override
	public int hashCode() {
		return FlinkFixedPartitioner.class.hashCode();
	}
}

可以看到
FlinkFixedPartitioner继承自FlinkKafkaPartitioner,并重写了open方法,其获取分区的逻辑是Flink当前的 子任务号对topic的partition数量取模(partitions[parallelInstanceId % partitions.length])
但是实际上1.11.1为什么只写到一个分区了呢?
看到FlinkKafkaPartitioner源码:
Flink 1.11.1 FlinkKafkaProducer写入topic0分区问题记录_第3张图片
使用之前如果没有进行重写open方法,那么子任务号,默认就是0。
这时候返回去看 KafkaSerializationSchemaWrapper。
发现其并没有对partitioner进行open重写。
Flink 1.11.1 FlinkKafkaProducer写入topic0分区问题记录_第4张图片
Flink Issues:
https://issues.apache.org/jira/browse/FLINK-19285?jql=project%20%3D%20FLINK%20AND%20text%20~%20%22kafka%20partitioner%22
官方在Flink1.11.2中已修复,那来看一下1.11.2版本中的KafkaSerializationSchemaWrapper:
Flink 1.11.1 FlinkKafkaProducer写入topic0分区问题记录_第5张图片
果然进行了FlinkFixedPartitioner的初始化。
1.11.2 代码测试:
上游10个分区,flink并行度10,下游topic三个分区,更换

 
            org.apache.flink
            flink-connector-kafka_2.11
            1.11.2
        

任务执行后下游三个分区均有数据写入!

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