Flink使用AsyncDataStream异步处理数据--性能提升效果

本文通过实例展示了20条数据同步与异步处理方式下,每条任务2秒耗时情况下,总耗时的明显区别。同步方式下耗时40秒,异步方式下仅8秒,探讨了并行和顺序执行对效率的影响。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

转载请标明出处:
https://bigmaning.blog.csdn.net/article/details/125455916
本文出自:【BigManing的博客】

场景需求

一共有20条数据,每条数据处理需要2秒,分别使用同步、异步方式处理,一共需要多久才能处理完呢?

接下来进行简单的验证,如有疑惑,欢迎指正。

同步方式

使用map算子模拟同步

代码

	/**
     * 同步方式  
     */
    private static void syncHandleData() throws Exception {
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        env.setParallelism(1);
        env.generateSequence(1, 20)
                .map(aLong -> {
                    return handleData(aLong);
                });
        env.execute("test");
    }

    /**
     * 模拟业务 耗时2s操作
     *
     */
    private static Long handleData(Long aLong) throws InterruptedException {
        String dateTime = DateFormatUtils.ISO_DATETIME_FORMAT.format(new Date());
        System.out.println(dateTime + "====> 处理第" + aLong + "个任务... 开始 " + Thread.currentThread().getName());
        // 模拟 耗时2s处理
        Thread.sleep(2000);
        dateTime = DateFormatUtils.ISO_DATETIME_FORMAT.format(new Date());
        System.out.println(dateTime + "====> 处理第" + aLong + "个任务... 结束");
        return aLong;
    }

结果输出

从以下结果可以得出结论:

  1. 每个任务都是按照顺序执行的
  2. 每个任务都是耗时2s()
  3. 总耗时为 20*2 = 40s
2022-06-25T09:53:39====> 处理第1个任务... 开始 Thread-7
2022-06-25T09:53:41====> 处理第1个任务... 结束
2022-06-25T09:53:41====> 处理第2个任务... 开始 Thread-7
2022-06-25T09:53:43====> 处理第2个任务... 结束
2022-06-25T09:53:43====> 处理第3个任务... 开始 Thread-7
2022-06-25T09:53:45====> 处理第3个任务... 结束
2022-06-25T09:53:45====> 处理第4个任务... 开始 Thread-7
2022-06-25T09:53:47====> 处理第4个任务... 结束
2022-06-25T09:53:47====> 处理第5个任务... 开始 Thread-7
2022-06-25T09:53:49====> 处理第5个任务... 结束
2022-06-25T09:53:49====> 处理第6个任务... 开始 Thread-7
2022-06-25T09:53:51====> 处理第6个任务... 结束
2022-06-25T09:53:51====> 处理第7个任务... 开始 Thread-7
2022-06-25T09:53:53====> 处理第7个任务... 结束
2022-06-25T09:53:53====> 处理第8个任务... 开始 Thread-7
2022-06-25T09:53:55====> 处理第8个任务... 结束
2022-06-25T09:53:55====> 处理第9个任务... 开始 Thread-7
2022-06-25T09:53:57====> 处理第9个任务... 结束
2022-06-25T09:53:57====> 处理第10个任务... 开始 Thread-7
2022-06-25T09:53:59====> 处理第10个任务... 结束
2022-06-25T09:53:59====> 处理第11个任务... 开始 Thread-7
2022-06-25T09:54:01====> 处理第11个任务... 结束
2022-06-25T09:54:01====> 处理第12个任务... 开始 Thread-7
2022-06-25T09:54:03====> 处理第12个任务... 结束
2022-06-25T09:54:03====> 处理第13个任务... 开始 Thread-7
2022-06-25T09:54:05====> 处理第13个任务... 结束
2022-06-25T09:54:05====> 处理第14个任务... 开始 Thread-7
2022-06-25T09:54:07====> 处理第14个任务... 结束
2022-06-25T09:54:07====> 处理第15个任务... 开始 Thread-7
2022-06-25T09:54:09====> 处理第15个任务... 结束
2022-06-25T09:54:09====> 处理第16个任务... 开始 Thread-7
2022-06-25T09:54:11====> 处理第16个任务... 结束
2022-06-25T09:54:11====> 处理第17个任务... 开始 Thread-7
2022-06-25T09:54:13====> 处理第17个任务... 结束
2022-06-25T09:54:13====> 处理第18个任务... 开始 Thread-7
2022-06-25T09:54:15====> 处理第18个任务... 结束
2022-06-25T09:54:15====> 处理第19个任务... 开始 Thread-7
2022-06-25T09:54:17====> 处理第19个任务... 结束
2022-06-25T09:54:17====> 处理第20个任务... 开始 Thread-7
2022-06-25T09:54:19====> 处理第20个任务... 结束

异步方式

使用AsyncDataStream数据流,因为我们不需要关注顺序,所以使用unorderedWait方法。如果你需要关注顺序,可以使用orderedWait方法。

代码


    /**
     * 异步方式
     */
    private static void asyncHandleData() throws Exception {
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        env.setParallelism(1);
        DataStreamSource<Long> longDataStreamSource = env.generateSequence(1, 20);
        // 不用关心顺序,异步处理完直接发送到下游
        AsyncDataStream.unorderedWait(longDataStreamSource, new MyRichAsyncFunction(), 1, TimeUnit.MINUTES, 5);
        env.execute("test");
    }

    /**
     * RichAsyncFunction 异步处理Function 实现类
     */
    static class MyRichAsyncFunction extends RichAsyncFunction<Long, Long> {

        private ThreadPoolExecutor threadPoolExecutor;

        @Override
        public void open(Configuration parameters) throws Exception {
            super.open(parameters);
            // 初始化操作
            threadPoolExecutor = new ThreadPoolExecutor(5, 10, 1, TimeUnit.MINUTES, new LinkedBlockingQueue<>());
        }

        @Override
        public void close() throws Exception {
            super.close();
            // 善后操作
            threadPoolExecutor.shutdown();
        }

        @Override
        public void timeout(Long input, ResultFuture<Long> resultFuture) throws Exception {
            // 超时操作
            resultFuture.completeExceptionally(new TimeoutException());
        }

        @Override
        public void asyncInvoke(Long aLong, ResultFuture<Long> resultFuture) throws Exception {
            // 异步客户端处理
            CompletableFuture.runAsync(() -> {
                try {
                    handleData(aLong);
                } catch (InterruptedException e) {
                    resultFuture.completeExceptionally(e);
                    return;
                }
                resultFuture.complete(Collections.singleton(aLong));
            }, threadPoolExecutor);
        }

    }
    
    /**
     * 模拟 耗时2s操作
     */
    private static Long handleData(Long aLong) throws InterruptedException {
        String dateTime = DateFormatUtils.ISO_DATETIME_FORMAT.format(new Date());
        System.out.println(dateTime + "====> 处理第" + aLong + "个任务... 开始 " + Thread.currentThread().getName());
        // 模拟 耗时2s处理
        Thread.sleep(2000);
        dateTime = DateFormatUtils.ISO_DATETIME_FORMAT.format(new Date());
        System.out.println(dateTime + "====> 处理第" + aLong + "个任务... 结束");
        return aLong;
    }

结果输出

从以下结果可以得出结论:

  1. 任务是异步并发处理的
  2. 由于是AsyncDataStream.unorderedWait,所以顺序是无序的
  3. 总耗时为 8s (2022-06-25T10:23:09 - 2022-06-25T10:23:01)
2022-06-25T10:23:01====> 处理第4个任务... 开始 pool-3-thread-4
2022-06-25T10:23:01====> 处理第2个任务... 开始 pool-3-thread-2
2022-06-25T10:23:01====> 处理第5个任务... 开始 pool-3-thread-5
2022-06-25T10:23:01====> 处理第3个任务... 开始 pool-3-thread-3
2022-06-25T10:23:01====> 处理第1个任务... 开始 pool-3-thread-1
2022-06-25T10:23:03====> 处理第4个任务... 结束
2022-06-25T10:23:03====> 处理第2个任务... 结束
2022-06-25T10:23:03====> 处理第1个任务... 结束
2022-06-25T10:23:03====> 处理第3个任务... 结束
2022-06-25T10:23:03====> 处理第5个任务... 结束
2022-06-25T10:23:03====> 处理第6个任务... 开始 pool-3-thread-4
2022-06-25T10:23:03====> 处理第7个任务... 开始 pool-3-thread-2
2022-06-25T10:23:03====> 处理第8个任务... 开始 pool-3-thread-1
2022-06-25T10:23:03====> 处理第9个任务... 开始 pool-3-thread-3
2022-06-25T10:23:03====> 处理第10个任务... 开始 pool-3-thread-5
2022-06-25T10:23:05====> 处理第6个任务... 结束
2022-06-25T10:23:05====> 处理第7个任务... 结束
2022-06-25T10:23:05====> 处理第8个任务... 结束
2022-06-25T10:23:05====> 处理第9个任务... 结束
2022-06-25T10:23:05====> 处理第11个任务... 开始 pool-3-thread-4
2022-06-25T10:23:05====> 处理第10个任务... 结束
2022-06-25T10:23:05====> 处理第12个任务... 开始 pool-3-thread-1
2022-06-25T10:23:05====> 处理第13个任务... 开始 pool-3-thread-2
2022-06-25T10:23:05====> 处理第14个任务... 开始 pool-3-thread-3
2022-06-25T10:23:05====> 处理第15个任务... 开始 pool-3-thread-5
2022-06-25T10:23:07====> 处理第13个任务... 结束
2022-06-25T10:23:07====> 处理第15个任务... 结束
2022-06-25T10:23:07====> 处理第11个任务... 结束
2022-06-25T10:23:07====> 处理第12个任务... 结束
2022-06-25T10:23:07====> 处理第14个任务... 结束
2022-06-25T10:23:07====> 处理第16个任务... 开始 pool-3-thread-3
2022-06-25T10:23:07====> 处理第17个任务... 开始 pool-3-thread-5
2022-06-25T10:23:07====> 处理第18个任务... 开始 pool-3-thread-4
2022-06-25T10:23:07====> 处理第19个任务... 开始 pool-3-thread-1
2022-06-25T10:23:07====> 处理第20个任务... 开始 pool-3-thread-2
2022-06-25T10:23:09====> 处理第18个任务... 结束
2022-06-25T10:23:09====> 处理第17个任务... 结束
2022-06-25T10:23:09====> 处理第16个任务... 结束
2022-06-25T10:23:09====> 处理第19个任务... 结束
2022-06-25T10:23:09====> 处理第20个任务... 结束

延伸

使用orderedWait会有什么样的表现呢?

代码修改如下:


    /**
     * 异步方式
     */
    private static void asyncHandleData() throws Exception {
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        env.setParallelism(1);
        DataStreamSource<Long> longDataStreamSource = env.generateSequence(1, 20);
        // 关心顺序,使用orderedWait, 异步处理完 并且是位于队列第一个 才发送到下游
        AsyncDataStream.orderedWait(longDataStreamSource, new MyRichAsyncFunction(), 1, TimeUnit.MINUTES, 5)//     
                //  验证 orderedWait   
                .print("打印结果:");
        env.execute("test");
    }

运行结果:

2022-06-25T10:39:57====> 处理第2个任务... 开始 pool-3-thread-2
2022-06-25T10:39:57====> 处理第4个任务... 开始 pool-3-thread-4
2022-06-25T10:39:57====> 处理第5个任务... 开始 pool-3-thread-5
2022-06-25T10:39:57====> 处理第3个任务... 开始 pool-3-thread-3
2022-06-25T10:39:57====> 处理第1个任务... 开始 pool-3-thread-1
2022-06-25T10:39:59====> 处理第4个任务... 结束
2022-06-25T10:39:59====> 处理第1个任务... 结束
2022-06-25T10:39:59====> 处理第2个任务... 结束
2022-06-25T10:39:59====> 处理第3个任务... 结束
2022-06-25T10:39:59====> 处理第5个任务... 结束
打印结果:> 1
打印结果:> 2
打印结果:> 3
打印结果:> 4
打印结果:> 5
2022-06-25T10:39:59====> 处理第6个任务... 开始 pool-3-thread-1
2022-06-25T10:39:59====> 处理第7个任务... 开始 pool-3-thread-2
2022-06-25T10:39:59====> 处理第8个任务... 开始 pool-3-thread-4
2022-06-25T10:39:59====> 处理第9个任务... 开始 pool-3-thread-3
2022-06-25T10:39:59====> 处理第10个任务... 开始 pool-3-thread-5
2022-06-25T10:40:01====> 处理第9个任务... 结束
2022-06-25T10:40:01====> 处理第6个任务... 结束
2022-06-25T10:40:01====> 处理第8个任务... 结束
2022-06-25T10:40:01====> 处理第7个任务... 结束
2022-06-25T10:40:01====> 处理第10个任务... 结束
打印结果:> 6
打印结果:> 7
打印结果:> 8
打印结果:> 9
打印结果:> 10
2022-06-25T10:40:01====> 处理第11个任务... 开始 pool-3-thread-3
2022-06-25T10:40:01====> 处理第12个任务... 开始 pool-3-thread-1
2022-06-25T10:40:01====> 处理第13个任务... 开始 pool-3-thread-4
2022-06-25T10:40:01====> 处理第14个任务... 开始 pool-3-thread-2
2022-06-25T10:40:01====> 处理第15个任务... 开始 pool-3-thread-5
2022-06-25T10:40:03====> 处理第11个任务... 结束
2022-06-25T10:40:03====> 处理第12个任务... 结束
2022-06-25T10:40:03====> 处理第13个任务... 结束
打印结果:> 11
打印结果:> 12
打印结果:> 13
2022-06-25T10:40:03====> 处理第14个任务... 结束
2022-06-25T10:40:03====> 处理第15个任务... 结束
2022-06-25T10:40:03====> 处理第16个任务... 开始 pool-3-thread-2
打印结果:> 14
2022-06-25T10:40:03====> 处理第17个任务... 开始 pool-3-thread-1
打印结果:> 15
2022-06-25T10:40:03====> 处理第18个任务... 开始 pool-3-thread-4
2022-06-25T10:40:03====> 处理第19个任务... 开始 pool-3-thread-3
2022-06-25T10:40:03====> 处理第20个任务... 开始 pool-3-thread-5
2022-06-25T10:40:05====> 处理第16个任务... 结束
打印结果:> 16
2022-06-25T10:40:05====> 处理第17个任务... 结束
2022-06-25T10:40:05====> 处理第19个任务... 结束
2022-06-25T10:40:05====> 处理第18个任务... 结束
打印结果:> 17
2022-06-25T10:40:05====> 处理第20个任务... 结束
打印结果:> 18
打印结果:> 19
打印结果:> 20
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值