flink 初探之SqlServer简单操作
flink操作数据库主要从3个方面入手
1、数据源(source)
2、数据处理
3、数据处理的结果保存(sink)
flink本身支持多种不同的source和sink,学会了一种便可举一反三。
(一) 首先是source的部分,也就是从sqlSever获取数据的部分
自定义的source需要继承自RichSourceFunction
他有两个主要的方法:open和run
我们将数据库连接的部分放在open方法中,在这个任务初始化的时候就可以被执行到
@Override
public void open(Configuration parameters) throws Exception {
super.open(parameters);
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
String url = "jdbc:sqlserver://127.0.0.1:1433;databaseName = sdc";
connection = DriverManager.getConnection(url,"sa","sa123456");
ExecutionConfig.GlobalJobParameters globalParams = getRuntimeContext().getExecutionConfig().getGlobalJobParameters();
Configuration globConf = (Configuration) globalParams;
//beginTime = globConf.getString("beginTime", null);
beginTime="2022-12-10 00:00:00";
}
接着就是不断的从数据库中拿到数据,只要在run方法只能不断的产生数据,产生的数据便可以被flink不断的去处理。
@Override
public void run(SourceContext<Map<String, Object>> sourceContext) throws Exception {
PreparedStatement ps = null;
while (true) {
Date bgd=DateUtils.parseDate(beginTime,"yyyy-MM-dd HH:mm:ss");
Date bgd2= DateUtils.addHours(bgd,1);
if(new Date().before(bgd2)){
continue;
}
DateFormat dateformat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String endTime=dateformat.format(bgd2);
ps = (PreparedStatement) connection
.prepareStatement(
"SELECT TOP(1000) [id]\n" +
" ,[msg]\n" +
" ,[save_time]\n" +
" ,[ip]\n" +
" ,[sr_ip]\n" +
" ,[sr_port]\n" +
" ,[port]\n" +
" ,[tag_ip]\n" +
" ,[tag_port]\n" +
" FROM [sdc].[dbo].[syslog] where [save_time] between '" + beginTime
+"' and '"+endTime+"'");
ResultSet resultSet = ps.executeQuery();
while (resultSet.next()) {
Map<String, Object> map = new HashMap<>();
map.put("id", resultSet.getString("id"));
map.put("msg", resultSet.getString("msg"));
map.put("saveTime", resultSet.getString("save_time"));
map.put("ip", resultSet.getString("ip"));
sourceContext.collect(map);
}
beginTime = dateformat.format(bgd2);
}
(二)接着是处理逻辑的部分
拿到数据之后要做的肯定就是处理它
public class logHandel {
public static void main(String[] args) throws Exception {
final StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
//设置数据来源
DataStream<Map<String,Object>> mapDataStream=env.addSource(new SqlSeverSource()).name("moruiTest");
//处理数据来源
DataStream<Map<String,Object>> alert=mapDataStream.filter(f->f.get("ip").toString().indexOf("192.168.2.1")>0).flatMap(new ToJson()).filter(f->f.get("action").toString().equals("deny"));
//得到结果
alert.addSink(new mySink()).name("sink输出");
//字符串部分为任务名称
env.execute("run flink");
}
public static class ToJson implements FlatMapFunction<Map<String,Object>, Map<String,Object>> {
@Override
public void flatMap(Map<String, Object> stringObjectMap, Collector<Map<String, Object>> collector) throws Exception {
String jsonStr= "{"+stringObjectMap.get("msg").toString()+"}";
jsonStr=jsonStr.replace(" ", ",");
Gson gson = new Gson();
Map<String, Object> map = new HashMap<String, Object>();
map = gson.fromJson(jsonStr, map.getClass());
map.put("ip",stringObjectMap.get("ip").toString());
map.put("saveTime",stringObjectMap.get("saveTime").toString());
map.put("msg",stringObjectMap.get("msg").toString());
collector.collect(map);
System.out.println("");
}
}
}
在上述代码中我们将数据来源进行处理并通过sink进行保存
(三)最后一部分贴出sink部分的代码
public class mySink extends RichSinkFunction<Map<String, Object>> {
private Connection connection=null;
PreparedStatement ps=null;
@Override
public void open(Configuration parameters) throws Exception {
super.open(parameters);
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
String url = "jdbc:sqlserver://127.0.0.1:1433;databaseName = sdc";
connection = DriverManager.getConnection(url,"sa","sa123456");
ps= connection.prepareStatement("insert into denyInfo (msg,save_time) values (?,?)");
}
@Override
public void invoke(Map<String, Object> value, Context context) throws Exception {
super.invoke(value, context);
if(value.containsKey("msg")) {
System.out.println("输出结果:" + value.get("msg").toString());
ps.setString(1, value.get("msg").toString());
ps.setString(2, value.get("saveTime").toString());
ps.execute();
}
}
@Override
public void close() throws Exception {
ps.close();
connection.close();
super.close();
}
}
## 完整代码请关注公众号:技术野生菌
写在最后
通过每天一个小demo的方式记录一个技术的学习经过,不断进步。从最简单的事情开始吧,加油!