一、简介
flink作为一个数据处理框架,其工作流程简单来说可以理解为:从数据源获取数据→处理数据→输出处理后的数据,source和sink则分别代表从数据源获取数据和输出数据,事实上flink本身提供了很多source和sink,但是在特殊使用场景时依然需要自定义source和sink,flink提供了较为统一的拓展方式,本例中从kafka消费数据就是使用flink官方提供的source,sink则为自定义拓展的写入数据到SQL server的sink。
二、添加依赖
在创建好的模板工程(创建模板工程方式参考https://blog.csdn.net/qq_37720936/article/details/104605758)中修改pom文件(注意第一行的注释,添加的依赖就加在它下面)
<!-- Add connector dependencies here. They must be in the default scope (compile). -->
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-connector-kafka_${scala.binary.version}</artifactId>
<version>${flink.version}</version>
</dependency>
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId>
<version>7.4.1.jre8</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.59</version>
</dependency>
三、核心代码
话不多说,直接上代码
// 测试数据:{"id": "1","name": "z3","age": "23","time": 1589015374489}
// {"id": "1","name": "l4","age": "23","time": 1589015374489}
public static void main(String[] args) throws Exception {
// set up the streaming execution environment
final StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
Properties properties = new Properties();
properties.setProperty("bootstrap.servers", "localhost:9092");
FlinkKafkaConsumer<String> consumer = new FlinkKafkaConsumer<>("test", new SimpleStringSchema(), properties);
// 设置消费模式
consumer.setStartFromGroupOffsets();
DataStream<String> stream = env
.addSource(consumer)
.filter(s -> {
try {
JSONObject.parseObject(s);
} catch (JSONException e) {
return false;
}
return !StrUtil.isBlank(s);
});
stream.addSink(new RichSinkFunction<String>() {
private Connection connection;
@Override
public void open(Configuration parameters) throws Exception {
connection = DriverManager.getConnection("jdbc:sqlserver://ip", "userName", "password");
}
@Override
public void invoke(String value, Context context) throws Exception {
JSONObject jsonObject = JSON.parseObject(value);
connection.createStatement().execute("INSERT database.schema.table (id, name, age, time) VALUES ('"
+ jsonObject.getString("id") + "','"
+ jsonObject.getString("name") + "','"
+ jsonObject.getString("age") + "','"
+ new Date(jsonObject.getLong("time")) + "')");
}
@Override
public void close() throws SQLException {
connection.close();
}
});
env.execute();
}
其中RichSinkFunction就是一个拓展sink的接口,flink中对source和sink提供了多个接口,source接口的继承关系如图,sink基本相同
open、invoke、close三个方法非常直观,就不多说了,中间用了一个filter算子过滤了一下空数据和非jsonObject格式的数据。
kafka和数据库的安装和使用就不多说了,这里使用的是本地搭的测试用单节点kafka,执行代码后(将pom文件中添加依赖那个地方上面两个依赖的<scope>provided</scope>注释掉可以在idea中直接运行代码)在kafka中相应topic中写入测试数据(测试数据中中文会乱码,暂时没找到原因,有大佬知道望告知,感激不尽),程序将自动同步到数据库中。