flink rich function的open和close方法执行时机

我们在使用flink的时候,经常会有自定义函数的时候,我们可以继承相关的richXXXFunction类,这个类里面会有open,close方法进行相关初始化和关闭的操作,那么这些方法是什么时候执行的呢?带着这个问题,我们以自定义SourceFunction为例,进行研究。

我们可以自定义source,也比较方便,extends RichSourceFunction 这个类就可以实现,下面的例子就是我们定义一个mysql的source

public class MySource extends RichSourceFunction<Student> {


    PreparedStatement ps;
    private Connection connection;

    /**
     * open() 方法中建立连接,这样不用每次 invoke 的时候都要建立连接和释放连接。
     *
     * @param parameters
     * @throws Exception
     */
    @Override
    public void open(Configuration parameters) throws Exception {
        super.open(parameters);
        connection = getConnection();
        String sql = "select * from stu;";
        ps = connection.prepareStatement(sql);
    }

    /**
     * 程序执行完毕就可以进行,关闭连接和释放资源的动作了
     *
     * @throws Exception
     */
    @Override
    public void close() throws Exception {
        super.close();
        if (connection != null) { //关闭连接和释放资源
            connection.close();
        }
        if (ps != null) {
            ps.close();
        }
    }

    /**
     * DataStream 调用一次 run() 方法用来获取数据
     *
     * @param ctx
     * @throws Exception
     */
    @Override
    public void run(SourceContext<Student> ctx) throws Exception {
        ResultSet resultSet = ps.executeQuery();
        while (resultSet.next()) {
            Student student =
                new Student(
                    resultSet.getString("name"),
                    resultSet.getInt("age"));
            ctx.collect(student);
        }
    }

    @Override
    public void cancel() {}

    private static Connection getConnection() {
        Connection con = null;
        try {
            Class.forName("com.mysql.jdbc.Driver");
            con =
                DriverManager.getConnection(
                    "jdbc:mysql://localhost:3306/hyhdb?useUnicode=true&characterEncoding=UTF-8", "root", "root");
        } catch (Exception e) {
            System.out.println("-----------mysql get connection has exception , msg = " + e.getMessage());
        }
        return con;
    }
}

那么这个例子中的open和close方法什么时候执行呢?

我们可以通过源码了解到,AbstractUdfStreamOperator 这个类中的open和close方法调用的,

	@Override
	public void open() throws Exception {
		super.open();
		FunctionUtils.openFunction(userFunction, new Configuration());
	}

	@Override
	public void close() throws Exception {
		super.close();
		functionsClosed = true;
		FunctionUtils.closeFunction(userFunction);
	}

我们可以从代码看到open和close方法里面又调用了FunctionUtils的相关方法,FunctionUtils这个类是一个工具类,里面的代码实现如下:

     public static void openFunction(Function function, Configuration parameters) throws Exception {
        if (function instanceof RichFunction) {
            RichFunction richFunction = (RichFunction)function;
            richFunction.open(parameters);
        }

    }

 public static void closeFunction(Function function) throws Exception {
        if (function instanceof RichFunction) {
            RichFunction richFunction = (RichFunction)function;
            richFunction.close();
        }

    }

我们看到FunctionUtils里的相关方法,最后判断函数是不是RichFunction类型,如果是的话,那么久调用我们自定义函数的open和close方法。

通过代码我们知道最尾端的调用过程,那么AbstractUdfStreamOperator 这个类中的open和close方法是在什么地方被调用的呢?通过源码的调用过程,我们发现StreamTask类中的

	private void openAllOperators() throws Exception {
		for (StreamOperator<?> operator : operatorChain.getAllOperators()) {
			if (operator != null) {
				operator.open();
			}
		}
	}
private void closeAllOperators() throws Exception {
		// We need to close them first to last, since upstream operators in the chain might emit
		// elements in their close methods.
		StreamOperator<?>[] allOperators = operatorChain.getAllOperators();
		for (int i = allOperators.length - 1; i >= 0; i--) {
			StreamOperator<?> operator = allOperators[i];
			if (operator != null) {
				operator.close();
			}
		}
	}

我们知道我们的开发的程序,最后会转换成相应的task任务,在work上执行,那么flink的框架中,最后会调用到StreamTask,在这个类里面进行操作链的open和close方法执行。

关于操作链operatorChain的相关内容,后续进行分析

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
在自定义 Flink 的 SourceFunction 时,需要在 open() 方法中创建连接,并在 close() 方法中关闭连接。具体来说,可以使用 Flink 的生命周期方法来管理连接的创建和关闭,如下所示: ```java public class MySource implements SourceFunction<String> { private Connection connection; @Override public void open(Configuration parameters) throws Exception { // 创建连接 connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "username", "password"); } @Override public void run(SourceContext<String> ctx) throws Exception { // 从连接中读取消息并发送到 Flink 中 Statement statement = connection.createStatement(); ResultSet resultSet = statement.executeQuery("SELECT * FROM mytable"); while (resultSet.next()) { String message = resultSet.getString("message"); ctx.collect(message); } } @Override public void cancel() { // 取消操作 } @Override public void close() throws Exception { // 关闭连接 if (connection != null) { connection.close(); } } } ``` 在上面的示例中,我们在 open() 方法中创建了一个 JDBC 连接,然后在 run() 方法中使用该连接从数据库中读取数据并发送到 Flink 中。最后,在 close() 方法中关闭连接。 值得注意的是,在 Flink 中,SourceFunction 的 run() 方法是一个无限循环,直到 cancel() 方法被调用才会停止。在 run() 方法中,我们需要使用 SourceContext 来发送数据到 Flink 中。同时,我们也需要在 run() 方法中处理异常并适时地调用 cancel() 方法来停止 SourceFunction 的运行。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值