Java版本Flink异步IO连接MySQL

Java版本Flink异步IO连接MySQL

Flink异步IO简介

Flink异步IO
当与外部系统交互时,例如直接访问外部数据库中的数据,比如在MapFunction执行SQL查询操作,这是一个同步交互的过程:向数据库发送请求,MapFunction等待,直到收到响应。在许多情况下,这种等待占据了函数的绝大多数时间。与数据库的异步交互意味着单个并行函数实例可以同时处理许多请求并同时接收响应。这样,发送其他请求和接收响应就可以占用等待时间。至少,等待时间会分摊到多个请求上。这在绝大多数情况下会使得系统具有更大的吞吐量。

  • 同步IO异步IO 对比图
    在这里插入图片描述

创建测试库表

  • 创建数据库
create database db_test charset utf8mb4;
  • 创建表
create table t_user(
	id int,
	user_name varchar(50),
	age int 
);
  • 插入测试数据
INSERT INTO t_user VALUES(1, '张三', 20), (3, '王五', 18), (5, '李四', 21)

代码实现

  • maven依赖 (pom.xml)
<dependency>
	<groupId>com.alibaba</groupId>
	<artifactId>druid</artifactId>
	<version>1.2.8</version>
</dependency>
<dependency>
	<groupId>mysql</groupId>
	<artifactId>mysql-connector-java</artifactId>
	<version>8.0.28</version>
</dependency>
  • 代码
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidPooledConnection;
import org.apache.flink.configuration.Configuration;
import org.apache.flink.streaming.api.datastream.AsyncDataStream;
import org.apache.flink.streaming.api.datastream.DataStreamSource;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.streaming.api.functions.async.ResultFuture;
import org.apache.flink.streaming.api.functions.async.RichAsyncFunction;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Collections;
import java.util.concurrent.*;
import java.util.function.Supplier;

public class FlinkMySQLAsync {

    public static void main(String[] args) throws Exception {
        // 获取执行环境
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        // 方便测试,设置并行度为1
        env.setParallelism(1);
        
        // 测试数据
        DataStreamSource<User> userStream = env.fromElements(
                new User("1"),
                new User("2"),
                new User("3"),
                new User("4"),
                new User("5")
        );

        // 获取异步流,将异步函数和流进行整合
        AsyncDataStream.
                unorderedWait(userStream, new MysqlAsyncFunction(), 10, TimeUnit.SECONDS).
                print();

        // 执行任务
        env.execute();
    }

    // 自定义异步函数类
    static class MysqlAsyncFunction extends RichAsyncFunction<User, User> {

        // 连接池
        private DruidDataSource druidDataSource;

        // 线程池
        private ExecutorService executorService;

        @Override
        public void open(Configuration parameters) throws Exception {
            // 创建连接池、配置连接参数
            druidDataSource = new DruidDataSource();
            druidDataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
            druidDataSource.setUsername("root");
            druidDataSource.setPassword("root");
            druidDataSource.setUrl("jdbc:mysql://localhost:3306/db_test?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC");

            // 创建线程池,用于执行异步操作
            executorService = new ThreadPoolExecutor(5, 15, 1,
                    TimeUnit.MINUTES,
                    new LinkedBlockingDeque<>(100));
        }
        
		// 释放资源
        @Override
        public void close() throws Exception {
        
            // 关闭连接池
            if (druidDataSource != null){
                druidDataSource.close();
            }
            
            // 关闭线程池
            if (executorService != null){
                executorService.shutdown();
            }
        }
        
        // 在此方法中执行异步操作
        @Override
        public void asyncInvoke(User user, ResultFuture<User> resultFuture) throws Exception {

            // 执行异步操作
            Future<User> future = executorService.submit(new Callable<User>() {
                @Override
                public User call() throws Exception {
                    // 从连接池中获取连接
                    DruidPooledConnection connection = druidDataSource.getConnection();
                    // 预编译SQL
                    PreparedStatement preparedStatement = connection.prepareStatement("select * from t_user where id = ?");
                    // 设置参数
                    preparedStatement.setString(1, user.getUserId());
                    // 执行SQL并获取结果
                    ResultSet resultSet = preparedStatement.executeQuery();

                    try {
                        // 封装结果
                        while (resultSet.next()) {
                            String userName = resultSet.getString("user_name");
                            int age = resultSet.getInt("age");
                            user.setUserName(userName);
                            user.setAge(age);
                        }
                    } finally {
                        resultSet.close();
                        preparedStatement.close();
                        connection.close();
                    }
                    return user;
                }
            });

            // 获取异步结果并输出
            CompletableFuture.supplyAsync(new Supplier<User>() {
                @Override
                public User get() {
                    try {
                        return future.get();
                    } catch (InterruptedException | ExecutionException e) {
                        return user;
                    }
                }
            }).thenAccept((User result) -> {
                resultFuture.complete(Collections.singleton(result));
            });

        }
    }

    // 实体类
    static class User {

        private String userId;

        private String userName;

        private int age;

        public User(String id) {
            this.userId = id;
        }

        public String getUserId() {
            return userId;
        }

        public void setUserId(String userId) {
            this.userId = userId;
        }

        public String getUserName() {
            return userName;
        }

        public void setUserName(String userName) {
            this.userName = userName;
        }

        public int getAge() {
            return age;
        }

        public void setAge(int age) {
            this.age = age;
        }

        @Override
        public String toString() {
            return "User{" +
                    "userId='" + userId + '\'' +
                    ", userName='" + userName + '\'' +
                    ", age=" + age +
                    '}';
        }
    }
}
  • 查看控制台输出,结果是无序的证明整个过程是异步的
User{userId='4', userName='null', age=0}
User{userId='3', userName='王五', age=18}
User{userId='2', userName='null', age=0}
User{userId='1', userName='张三', age=20}
User{userId='5', userName='李四', age=21}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值