This is an automated email from the ASF dual-hosted git repository.

healchow pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-inlong.git


The following commit(s) were added to refs/heads/master by this push:
     new 4aeb0d2  [INLONG-2250][Feature][InLong-Sort] Support Kafka sink in 
InLong-Sort  (#2251)
4aeb0d2 is described below

commit 4aeb0d2e92b3e0a3c3c6d0b4df437b50790b3c5f
Author: Kevin Wen <[email protected]>
AuthorDate: Sun Jan 23 10:12:55 2022 +0800

    [INLONG-2250][Feature][InLong-Sort] Support Kafka sink in InLong-Sort  
(#2251)
---
 inlong-sort/pom.xml                                |  6 ++
 .../inlong/sort/configuration/Constants.java       |  7 ++
 .../serialization/AvroSerializationInfo.java       | 24 ++++++
 .../serialization/CanalSerializationInfo.java      | 24 ++++++
 .../serialization/JsonSerializationInfo.java       | 24 ++++++
 .../SerializationInfo.java}                        | 36 ++-------
 .../inlong/sort/protocol/sink/KafkaSinkInfo.java   | 88 ++++++++++++++++++++++
 .../apache/inlong/sort/protocol/sink/SinkInfo.java |  2 +
 inlong-sort/sort-single-tenant/pom.xml             |  5 ++
 .../inlong/sort/singletenant/flink/Entrance.java   | 15 +++-
 .../singletenant/flink/kafka/KafkaSinkBuilder.java | 63 ++++++++++++++++
 .../serialization/SerializationSchemaBuilder.java  | 40 ++++++++++
 12 files changed, 303 insertions(+), 31 deletions(-)

diff --git a/inlong-sort/pom.xml b/inlong-sort/pom.xml
index d725006..52d0e25 100644
--- a/inlong-sort/pom.xml
+++ b/inlong-sort/pom.xml
@@ -163,6 +163,12 @@
             </dependency>
 
             <dependency>
+                <groupId>org.apache.flink</groupId>
+                <artifactId>flink-connector-kafka_2.11</artifactId>
+                <version>${flink.version}</version>
+            </dependency>
+
+            <dependency>
                 <groupId>com.google.guava</groupId>
                 <artifactId>guava</artifactId>
                 <version>${guava.version}</version>
diff --git 
a/inlong-sort/sort-common/src/main/java/org/apache/inlong/sort/configuration/Constants.java
 
b/inlong-sort/sort-common/src/main/java/org/apache/inlong/sort/configuration/Constants.java
index 35f90b0..4a01685 100644
--- 
a/inlong-sort/sort-common/src/main/java/org/apache/inlong/sort/configuration/Constants.java
+++ 
b/inlong-sort/sort-common/src/main/java/org/apache/inlong/sort/configuration/Constants.java
@@ -194,6 +194,13 @@ public class Constants {
                     .defaultValue(false);
 
     // ------------------------------------------------------------------------
+    //  Kafka sink related configs
+    // ------------------------------------------------------------------------
+    public static final ConfigOption<Integer> SINK_KAFKA_PRODUCER_POOL_SIZE =
+            key("sink.kafka.producer.pool.size")
+                    .defaultValue(5);
+
+    // ------------------------------------------------------------------------
     //  Hive sink related configs
     // ------------------------------------------------------------------------
     public static final ConfigOption<Long> HIKARICP_IDLE_TIMEOUT_MS =
diff --git 
a/inlong-sort/sort-common/src/main/java/org/apache/inlong/sort/protocol/serialization/AvroSerializationInfo.java
 
b/inlong-sort/sort-common/src/main/java/org/apache/inlong/sort/protocol/serialization/AvroSerializationInfo.java
new file mode 100644
index 0000000..c9a82cf
--- /dev/null
+++ 
b/inlong-sort/sort-common/src/main/java/org/apache/inlong/sort/protocol/serialization/AvroSerializationInfo.java
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.inlong.sort.protocol.serialization;
+
+public class AvroSerializationInfo implements SerializationInfo {
+
+    private static final long serialVersionUID = 8446721117598285868L;
+
+}
diff --git 
a/inlong-sort/sort-common/src/main/java/org/apache/inlong/sort/protocol/serialization/CanalSerializationInfo.java
 
b/inlong-sort/sort-common/src/main/java/org/apache/inlong/sort/protocol/serialization/CanalSerializationInfo.java
new file mode 100644
index 0000000..633b10b
--- /dev/null
+++ 
b/inlong-sort/sort-common/src/main/java/org/apache/inlong/sort/protocol/serialization/CanalSerializationInfo.java
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.inlong.sort.protocol.serialization;
+
+public class CanalSerializationInfo implements SerializationInfo {
+
+    private static final long serialVersionUID = 479443152335788151L;
+
+}
diff --git 
a/inlong-sort/sort-common/src/main/java/org/apache/inlong/sort/protocol/serialization/JsonSerializationInfo.java
 
b/inlong-sort/sort-common/src/main/java/org/apache/inlong/sort/protocol/serialization/JsonSerializationInfo.java
new file mode 100644
index 0000000..37ea81b
--- /dev/null
+++ 
b/inlong-sort/sort-common/src/main/java/org/apache/inlong/sort/protocol/serialization/JsonSerializationInfo.java
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.inlong.sort.protocol.serialization;
+
+public class JsonSerializationInfo implements SerializationInfo {
+
+    private static final long serialVersionUID = -4774030753680011998L;
+
+}
diff --git 
a/inlong-sort/sort-common/src/main/java/org/apache/inlong/sort/protocol/sink/SinkInfo.java
 
b/inlong-sort/sort-common/src/main/java/org/apache/inlong/sort/protocol/serialization/SerializationInfo.java
similarity index 50%
copy from 
inlong-sort/sort-common/src/main/java/org/apache/inlong/sort/protocol/sink/SinkInfo.java
copy to 
inlong-sort/sort-common/src/main/java/org/apache/inlong/sort/protocol/serialization/SerializationInfo.java
index 277224d..82db9d7 100644
--- 
a/inlong-sort/sort-common/src/main/java/org/apache/inlong/sort/protocol/sink/SinkInfo.java
+++ 
b/inlong-sort/sort-common/src/main/java/org/apache/inlong/sort/protocol/serialization/SerializationInfo.java
@@ -15,43 +15,21 @@
  * limitations under the License.
  */
 
-package org.apache.inlong.sort.protocol.sink;
+package org.apache.inlong.sort.protocol.serialization;
 
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import java.io.Serializable;
-import 
org.apache.flink.shaded.jackson2.com.fasterxml.jackson.annotation.JsonProperty;
 import 
org.apache.flink.shaded.jackson2.com.fasterxml.jackson.annotation.JsonSubTypes;
-import 
org.apache.flink.shaded.jackson2.com.fasterxml.jackson.annotation.JsonSubTypes.Type;
 import 
org.apache.flink.shaded.jackson2.com.fasterxml.jackson.annotation.JsonTypeInfo;
-import org.apache.inlong.sort.configuration.Constants;
-import org.apache.inlong.sort.protocol.FieldInfo;
 
-/**
- * The base class of the data sink in the metadata.
- */
+import java.io.Serializable;
+
 @JsonTypeInfo(
         use = JsonTypeInfo.Id.NAME,
         include = JsonTypeInfo.As.PROPERTY,
         property = "type")
 @JsonSubTypes({
-        @Type(value = ClickHouseSinkInfo.class, name = 
Constants.SINK_TYPE_CLICKHOUSE),
-        @Type(value = HiveSinkInfo.class, name = Constants.SINK_TYPE_HIVE),
-        @Type(value = IcebergSinkInfo.class, name = 
Constants.SINK_TYPE_ICEBERG)}
-)
-public abstract class SinkInfo implements Serializable {
-
-    private static final long serialVersionUID = 1485856855405721745L;
-
-    @JsonProperty("fields")
-    private final FieldInfo[] fields;
-
-    public SinkInfo(@JsonProperty("fields") FieldInfo[] fields) {
-        this.fields = checkNotNull(fields);
-    }
+        @JsonSubTypes.Type(value = JsonSerializationInfo.class, name = "json"),
+        @JsonSubTypes.Type(value = CanalSerializationInfo.class, name = 
"canal"),
+        @JsonSubTypes.Type(value = AvroSerializationInfo.class, name = 
"avro")})
+public interface SerializationInfo extends Serializable {
 
-    @JsonProperty("fields")
-    public FieldInfo[] getFields() {
-        return fields;
-    }
 }
diff --git 
a/inlong-sort/sort-common/src/main/java/org/apache/inlong/sort/protocol/sink/KafkaSinkInfo.java
 
b/inlong-sort/sort-common/src/main/java/org/apache/inlong/sort/protocol/sink/KafkaSinkInfo.java
new file mode 100644
index 0000000..d884a09
--- /dev/null
+++ 
b/inlong-sort/sort-common/src/main/java/org/apache/inlong/sort/protocol/sink/KafkaSinkInfo.java
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.inlong.sort.protocol.sink;
+
+import 
org.apache.flink.shaded.jackson2.com.fasterxml.jackson.annotation.JsonCreator;
+import 
org.apache.flink.shaded.jackson2.com.fasterxml.jackson.annotation.JsonProperty;
+import org.apache.inlong.sort.protocol.FieldInfo;
+import org.apache.inlong.sort.protocol.serialization.SerializationInfo;
+
+import java.util.Objects;
+
+public class KafkaSinkInfo extends SinkInfo {
+
+    private static final long serialVersionUID = 161617117094475954L;
+
+    @JsonProperty("address")
+    private final String address;
+
+    @JsonProperty("topic")
+    private final String topic;
+
+    @JsonProperty("serialization_info")
+    private final SerializationInfo serializationInfo;
+
+    @JsonCreator
+    public KafkaSinkInfo(
+            @JsonProperty("fields") FieldInfo[] fields,
+            @JsonProperty("address") String address,
+            @JsonProperty("topic") String topic,
+            @JsonProperty("serialization_info") SerializationInfo 
serializationInfo
+    ) {
+        super(fields);
+        this.address = address;
+        this.topic = topic;
+        this.serializationInfo = serializationInfo;
+    }
+
+    @JsonProperty("address")
+    public String getAddress() {
+        return address;
+    }
+
+    @JsonProperty("topic")
+    public String getTopic() {
+        return topic;
+    }
+
+    @JsonProperty("serialization_info")
+    public SerializationInfo getSerializationInfo() {
+        return serializationInfo;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+
+        KafkaSinkInfo that = (KafkaSinkInfo) o;
+        return Objects.equals(address, that.address)
+                && Objects.equals(topic, that.topic)
+                && Objects.equals(serializationInfo, that.serializationInfo);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(address, topic, serializationInfo);
+    }
+}
diff --git 
a/inlong-sort/sort-common/src/main/java/org/apache/inlong/sort/protocol/sink/SinkInfo.java
 
b/inlong-sort/sort-common/src/main/java/org/apache/inlong/sort/protocol/sink/SinkInfo.java
index 277224d..99da50b 100644
--- 
a/inlong-sort/sort-common/src/main/java/org/apache/inlong/sort/protocol/sink/SinkInfo.java
+++ 
b/inlong-sort/sort-common/src/main/java/org/apache/inlong/sort/protocol/sink/SinkInfo.java
@@ -37,6 +37,8 @@ import org.apache.inlong.sort.protocol.FieldInfo;
 @JsonSubTypes({
         @Type(value = ClickHouseSinkInfo.class, name = 
Constants.SINK_TYPE_CLICKHOUSE),
         @Type(value = HiveSinkInfo.class, name = Constants.SINK_TYPE_HIVE),
+        @Type(value = KafkaSinkInfo.class, name = Constants.SINK_TYPE_KAFKA),
+        @Type(value = HiveSinkInfo.class, name = Constants.SINK_TYPE_HIVE),
         @Type(value = IcebergSinkInfo.class, name = 
Constants.SINK_TYPE_ICEBERG)}
 )
 public abstract class SinkInfo implements Serializable {
diff --git a/inlong-sort/sort-single-tenant/pom.xml 
b/inlong-sort/sort-single-tenant/pom.xml
index 6fd719d..f2b3425 100644
--- a/inlong-sort/sort-single-tenant/pom.xml
+++ b/inlong-sort/sort-single-tenant/pom.xml
@@ -75,6 +75,11 @@
             <artifactId>hadoop-common</artifactId>
         </dependency>
 
+        <dependency>
+            <groupId>org.apache.flink</groupId>
+            
<artifactId>flink-connector-kafka_${flink.scala.binary.version}</artifactId>
+        </dependency>
+
     </dependencies>
 
 </project>
\ No newline at end of file
diff --git 
a/inlong-sort/sort-single-tenant/src/main/java/org/apache/inlong/sort/singletenant/flink/Entrance.java
 
b/inlong-sort/sort-single-tenant/src/main/java/org/apache/inlong/sort/singletenant/flink/Entrance.java
index b87bd90..d6faa16 100644
--- 
a/inlong-sort/sort-single-tenant/src/main/java/org/apache/inlong/sort/singletenant/flink/Entrance.java
+++ 
b/inlong-sort/sort-single-tenant/src/main/java/org/apache/inlong/sort/singletenant/flink/Entrance.java
@@ -18,10 +18,13 @@
 package org.apache.inlong.sort.singletenant.flink;
 
 import static com.google.common.base.Preconditions.checkNotNull;
+import static 
org.apache.inlong.sort.singletenant.flink.kafka.KafkaSinkBuilder.buildKafkaSink;
 
 import com.google.common.base.Preconditions;
 import java.io.File;
 import java.io.IOException;
+import java.util.Map;
+
 import 
org.apache.flink.shaded.jackson2.com.fasterxml.jackson.databind.ObjectMapper;
 import org.apache.flink.streaming.api.datastream.DataStream;
 import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
@@ -31,6 +34,7 @@ import org.apache.iceberg.flink.sink.FlinkSink;
 import org.apache.inlong.sort.configuration.Configuration;
 import org.apache.inlong.sort.configuration.Constants;
 import org.apache.inlong.sort.protocol.DataFlowInfo;
+import org.apache.inlong.sort.protocol.sink.KafkaSinkInfo;
 import org.apache.inlong.sort.protocol.sink.IcebergSinkInfo;
 import org.apache.inlong.sort.protocol.sink.SinkInfo;
 import org.apache.inlong.sort.protocol.source.PulsarSourceInfo;
@@ -63,7 +67,8 @@ public class Entrance {
         buildSinkStream(
                 sourceStream,
                 config,
-                dataFlowInfo.getSinkInfo());
+                dataFlowInfo.getSinkInfo(),
+                dataFlowInfo.getProperties());
 
         env.execute(clusterId);
     }
@@ -96,7 +101,8 @@ public class Entrance {
     private static void buildSinkStream(
             DataStream<Row> sourceStream,
             Configuration config,
-            SinkInfo sinkInfo) {
+            SinkInfo sinkInfo,
+            Map<String, Object> properties) {
         final String sinkType = 
checkNotNull(config.getString(Constants.SINK_TYPE));
         final int sinkParallelism = 
config.getInteger(Constants.SINK_PARALLELISM);
 
@@ -119,6 +125,11 @@ public class Entrance {
                         .build();
                 break;
             case Constants.SINK_TYPE_KAFKA:
+                sourceStream
+                        .addSink(buildKafkaSink((KafkaSinkInfo) sinkInfo, 
properties, config))
+                        .uid(Constants.SINK_UID)
+                        .name("Kafka Sink")
+                        .setParallelism(sinkParallelism);
                 break;
             default:
                 throw new IllegalArgumentException("Unsupported sink type " + 
sinkType);
diff --git 
a/inlong-sort/sort-single-tenant/src/main/java/org/apache/inlong/sort/singletenant/flink/kafka/KafkaSinkBuilder.java
 
b/inlong-sort/sort-single-tenant/src/main/java/org/apache/inlong/sort/singletenant/flink/kafka/KafkaSinkBuilder.java
new file mode 100644
index 0000000..c1b1b69
--- /dev/null
+++ 
b/inlong-sort/sort-single-tenant/src/main/java/org/apache/inlong/sort/singletenant/flink/kafka/KafkaSinkBuilder.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.inlong.sort.singletenant.flink.kafka;
+
+import org.apache.flink.api.common.serialization.SerializationSchema;
+import org.apache.flink.streaming.api.functions.sink.SinkFunction;
+import org.apache.flink.streaming.connectors.kafka.FlinkKafkaProducer;
+import 
org.apache.flink.streaming.connectors.kafka.partitioner.FlinkFixedPartitioner;
+import org.apache.flink.types.Row;
+import org.apache.inlong.sort.configuration.Configuration;
+import 
org.apache.inlong.sort.singletenant.flink.serialization.SerializationSchemaBuilder;
+import org.apache.inlong.sort.protocol.sink.KafkaSinkInfo;
+import org.apache.kafka.clients.producer.ProducerConfig;
+
+import java.util.Map;
+import java.util.Properties;
+
+import static 
org.apache.inlong.sort.configuration.Constants.SINK_KAFKA_PRODUCER_POOL_SIZE;
+
+public class KafkaSinkBuilder {
+
+    public static SinkFunction<Row> buildKafkaSink(
+            KafkaSinkInfo kafkaSinkInfo,
+            Map<String, Object> properties,
+            Configuration config
+    ) {
+        String topic = kafkaSinkInfo.getTopic();
+        Properties producerProperties = buildProducerProperties(properties, 
kafkaSinkInfo.getAddress());
+        SerializationSchema<Row> serializationSchema =
+                
SerializationSchemaBuilder.buildSerializationSchema(kafkaSinkInfo.getSerializationInfo());
+
+        return new FlinkKafkaProducer<>(
+                topic,
+                serializationSchema,
+                producerProperties,
+                new FlinkFixedPartitioner<>(),
+                FlinkKafkaProducer.Semantic.EXACTLY_ONCE,
+                config.getInteger(SINK_KAFKA_PRODUCER_POOL_SIZE)
+        );
+    }
+
+    private static Properties buildProducerProperties(Map<String, Object> 
properties, String address) {
+        Properties producerProperties = new Properties();
+        producerProperties.putAll(properties);
+        producerProperties.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, 
address);
+        return producerProperties;
+    }
+}
diff --git 
a/inlong-sort/sort-single-tenant/src/main/java/org/apache/inlong/sort/singletenant/flink/serialization/SerializationSchemaBuilder.java
 
b/inlong-sort/sort-single-tenant/src/main/java/org/apache/inlong/sort/singletenant/flink/serialization/SerializationSchemaBuilder.java
new file mode 100644
index 0000000..e41ef47
--- /dev/null
+++ 
b/inlong-sort/sort-single-tenant/src/main/java/org/apache/inlong/sort/singletenant/flink/serialization/SerializationSchemaBuilder.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.inlong.sort.singletenant.flink.serialization;
+
+import org.apache.flink.api.common.serialization.SerializationSchema;
+import org.apache.flink.types.Row;
+import org.apache.inlong.sort.protocol.serialization.SerializationInfo;
+
+import java.nio.charset.StandardCharsets;
+
+public class SerializationSchemaBuilder {
+
+    // TODO: support json, canal and avro format
+    public static SerializationSchema<Row> 
buildSerializationSchema(SerializationInfo serializationInfo) {
+        return new SerializationSchema<Row>() {
+
+            private static final long serialVersionUID = -6818985955456373916L;
+
+            @Override
+            public byte[] serialize(Row element) {
+                return element.toString().getBytes(StandardCharsets.UTF_8);
+            }
+        };
+    }
+}

Reply via email to