记一次Flink遇到性能瓶颈

前言

这周的主要时间花在Flink上面,做了一个简单的从文本文件中读取数据,然后存入数据库的例子,能够正常的实现功能,但是遇到个问题,我有四台机器,自己搭建了一个standalone的集群,不论我把并行度设置多少,跑起来的耗时都非常接近,实在是百思不得其解。机器多似乎并不能帮助它。 把过程记录在此,看后面随着学习的深入能不能解答出这个问题。
image

尝试过的修复方法

集群搭建

出现这个问题后,我从集群的角度来进行了些修改,
1,机器是2核的,slots被设置成了6,那我就有点怀疑是这个设置问题,因为其实只有2核,设置的多了,反而存在抢占资源,导致运行达不到效果,改成2后效果一样,没有改进。这个参数在
taskmanager.numberOfTaskSlots: 2
2,调整内存, taskmanager 从2G调整为4G, 效果也没有变化。
taskmanager.memory.process.size: 4000m
这里说下这个内存,我们设置的是总的Memory,也就是这个Total Process Memory。
image
剔除掉些比较固定的Memory,剩下的大头就是这个Task Heap 和 Managed Memory。
所以我们调整大小后,它两个也就相应的增加了。 我查了下这两个,可以理解为堆内存和堆外内存,
一个是存放我们程序的对象,会被垃圾回收器回收;一个是堆外内存,比如RockDB 和 缓存 sort,hash 等的中间结果。

程序方面修改

最开始的时候我把保存数据库操作写在MapFunction里面,后来改到SinkFunction里面。
SinkFunction里面保存数据库的方法也进行了反复修改,从开始使用Spring的JdbcTemplate,换成后来直接使用最原始JDBC。 而且还踩了一个坑,开始的时候用的注入的JdbcTemplate, 本地运行没有问题,到了集群上面,发到别的机器的时候,注入的东西就是空的了。
换成原始的JDBC速度能提升不少, 我猜想这里的原因是jdbctemplate做了些多余的事情, JDBC打开一次,后面Invoke的时候就直接存了,效率要高些,所以速度上提升不少。
这里把部分代码贴出来, 在Open的时候就预加载好PreparedStatement, Invoke的时候直接传参数,调用就可以了。

public class SinkToMySQL2 extends RichSinkFunction<MarketPrice> {
    private PreparedStatement updatePS;
    private PreparedStatement insertPS;
    private Connection connection;

    @Override
    public void open(Configuration parameters) throws Exception {
        super.open(parameters);
        HikariDataSource dataSource = new HikariDataSource();
        connection = getConnection(dataSource);
        if(connection != null)
        {
            String updateSQL = " update MarketPrice set open_price=?,high_price=?,low_price=?,close_price=? where performance_id = ? and price_as_of_date = ?";
            updatePS = this.connection.prepareStatement(updateSQL);

            String insertSQL = " insert into MarketPrice(performance_id,price_as_of_date,open_price,high_price,low_price,close_price) values (?,?,?,?,?,?)";
            insertPS = this.connection.prepareStatement(insertSQL);
        }

    }

    @Override
    public void close() throws Exception {
        super.close();
        if (updatePS != null) {
            updatePS.close();
        }
        if (insertPS != null) {
            insertPS.close();
        }
        //关闭连接和释放资源
        if (connection != null) {
            connection.close();
        }

    }

    /**
     * 每条数据的插入都要调用一次 invoke() 方法
     *
     * @param marketPrice
     * @param context
     * @throws Exception
     */
    @Override
    public void invoke(MarketPrice marketPrice, Context context) throws Exception {

        log.info("start save for {}", marketPrice.getPerformanceId().toString() );

        updatePS.setDouble(1,marketPrice.getOpenPrice());
        updatePS.setDouble(2,marketPrice.getHighPrice());
        updatePS.setDouble(3,marketPrice.getLowPrice());
        updatePS.setDouble(4,marketPrice.getClosePrice());
        updatePS.setString(5, marketPrice.getPerformanceId().toString());
        updatePS.setInt(6, marketPrice.getPriceAsOfDate());
        int result = updatePS.executeUpdate();


        log.info("finish update for {} result {}", marketPrice.getPerformanceId().toString(), result);

        if(result == 0)
        {
            String insertSQL = " insert into MarketPrice(performance_id,price_as_of_date,open_price,high_price,low_price,close_price) values (?,?,?,?,?,?)";
            insertPS = this.connection.prepareStatement(insertSQL);
            insertPS.setString(1, marketPrice.getPerformanceId().toString());
            insertPS.setInt(2, marketPrice.getPriceAsOfDate());
            insertPS.setDouble(3,marketPrice.getOpenPrice());
            insertPS.setDouble(4,marketPrice.getHighPrice());
            insertPS.setDouble(5,marketPrice.getLowPrice());
            insertPS.setDouble(6,marketPrice.getClosePrice());

            result = insertPS.executeUpdate();
            log.info("finish save for {} result {}", marketPrice.getPerformanceId().toString(), result);
        }
    }

}

总结

从多个方面去改进,结果发现还是一样的,就是使用一台机器和使用三台机器,时间上一样的,再怀疑我只能怀疑是某台机器有问题,然后运行的时候,由最慢的机器决定了速度。 我在使用MapFunction的时候有观察到,有的时候,某台机器已经处理上千条,而有的只处理了几十条,到最后完成的时候,大家处理的数量又是很接近的。这样能够解释为什么机器多了,速度却是一样的。但是我没有办法找出哪台机器来。 我自己的本地运行,并行数设置的多,速度上面是有提升的,到了集群就碰到这样的现象,后面看能不能解决它, 先记录在此。

原文链接:https://www.cnblogs.com/dk168/p/17322082.html

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:记一次Flink遇到性能瓶颈 - Python技术站

(0)
上一篇 2023年4月17日
下一篇 2023年4月17日

相关文章

  • 创建SpringBoot工程并集成Mybatis的方法

    创建SpringBoot工程并集成Mybatis,是一项非常常用的技术操作。本文将为大家详细讲解如何基于SpringBoot快速集成Mybatis的步骤和工具。 1.创建SpringBoot工程 SpringBoot提供了官方的SpringBoot CLI和SpringBoot Initializr两种工具,来创建SpringBoot工程。本文使用Sprin…

    Java 2023年5月19日
    00
  • java上乘武功入门–反射

    Java 上乘武功入门——反射的完整攻略 什么是反射 Java 中的反射(Reflection)是指程序可以在运行期间获取其本身的信息的一种机制。Java 反射机制允许程序在运行期间进行自我检查操作,比如检查自身的属性和方法,或者动态地执行方法。反射机制广泛应用于 Java 框架开发中,通过反射机制可以大大提升编码的灵活性和通用性。 反射机制的原理 Java…

    Java 2023年5月26日
    00
  • java实体对象与Map之间的转换工具类代码实例

    下面是关于“java实体对象与Map之间的转换工具类代码实例”的完整攻略: 一、概述 在Java开发中,经常需要将Java实体对象转换为Map对象,或者将Map对象转换为Java实体对象。这时候,我们可以借助工具类来实现转换功能。本文将介绍如何编写一个通用的工具类,实现Java实体对象与Map之间的转换。 二、实现步骤 1.定义Java实体对象和Map对象 …

    Java 2023年5月26日
    00
  • Java编程中更新XML文档的常用方法

    当需要更新XML文档时,Java编程中有多种常用的方法。本文将介绍Java编程中经常使用的两种方法。 方法一:使用DOM编程 DOM(文档对象模型)是一种Java内置的XML解析器。通常,使用DOM解析XML文档时,会将整个XML文件加载到内存中,构建一个XML的DOM树,程序员可以通过修改DOM树的方式来实现对XML文件的更新操作。 示例一:添加一个节点 …

    Java 2023年6月15日
    00
  • 一个开发人员眼中的JSP技术(上)

    下面是一个详细的攻略: 什么是JSP技术? JSP(JavaServer Pages)是一种基于Java语言的web开发技术,它是由Servlets衍生出来的一种技术。它允许将Java代码插入到HTML页面中,使得页面具备动态生成内容的能力。相比于Servlets,JSP技术更加容易开发,并且更适合于构建动态网站。这是因为在JSP中可以通过EL表达式、自定义…

    Java 2023年6月15日
    00
  • Java中实现分布式定时任务的方法

    Java中实现分布式定时任务的方法有很多种,下面我为您介绍一下常见的三种实现方式: 1. 使用Quartz实现分布式定时任务 Quartz是一个功能强大的定时任务框架,它可以支持分布式部署。下面展示Quartz实现分布式定时任务的步骤: 引入Quartz的依赖包,可以通过maven进行引入: xml <dependency> <groupI…

    Java 2023年5月26日
    00
  • SpringBoot2零基础到精通之配置文件与web开发

    配置文件 Spring Boot 项目中的配置文件一般有 application.properties 和 application.yml 两种,它们用于对应不同的属性配置和格式化方式,常见的属性配置包括数据库连接、端口号、日志级别等。其中,application.yml 文件的格式化方式相对更灵活,可以嵌套、缩进和列表项等等。 下面以 MySQL 数据库连…

    Java 2023年5月15日
    00
  • SpringBoot深入理解之内置web容器及配置的总结

    Spring Boot深入理解之内置Web容器及配置的总结 什么是Spring Boot内置Web容器 Spring Boot是一种轻量级Java开发框架,它简化了Spring应用程序的构建和部署过程。它支持内置Web容器,如Tomcat、Jetty和Undertow。这意味着您可以直接使用可执行Jar文件启动Spring应用程序而无需外部Web服务器。 S…

    Java 2023年5月15日
    00
合作推广
合作推广
分享本页
返回顶部