• spring boot jdbctemplate queryforstream 使用问题


    开发一个功能为了避免内存问题,使用了 jdbctemplate queryforstream,同时日常中会使用链接池,运行一段时间
    会出现链接超时的问题

    参考示例代码

     
    @RestController
    public class Api {
     
        @Autowired
        private JdbcTemplate jdbcTemplate;
     
        @GetMapping(value = {"/demo"})
        public Object demo() throws InterruptedException {
            Stream<Conf> streamB = jdbcTemplate.queryForStream(
                    "select * from sys.sys_config", new BeanPropertyRowMapper<>(Conf.class));
            System.out.println(streamB.findFirst().get().toString());
            return "ok";
        }
    }

    问题原因

    stream 模式需要显示关闭,否则会造成链接不能释放,链接池会满了,之后就不能使用了,参考内部处理

    public <T> Stream<T> queryForStream(String sql, RowMapper<T> rowMapper) throws DataAccessException {
    class StreamStatementCallback implements StatementCallback<Stream<T>>, SqlProvider {
        StreamStatementCallback() {
        }
     
        public Stream<T> doInStatement(Statement stmt) throws SQLException {
            ResultSet rs = stmt.executeQuery(sql);
            Connection con = stmt.getConnection();
            return (Stream)(new JdbcTemplate.ResultSetSpliterator(rs, rowMapper)).stream().onClose(() -> {
                JdbcUtils.closeResultSet(rs);
                JdbcUtils.closeStatement(stmt);
                DataSourceUtils.releaseConnection(con, JdbcTemplate.this.getDataSource());
            });
        }
     
        public String getSql() {
            return sql;
        }
    }
     
    return (Stream)result(this.execute(new StreamStatementCallback(), false));
    }

    解决&改进

    对于stream 进行释放处理,可以声明式关闭或者使用try resource 模式,同时对于系统的监控需要做好,比如集成prometheus

     try(Stream<Conf> streamB = jdbcTemplate.queryForStream(
                    "select * from sys.sys_config", new BeanPropertyRowMapper<>(Conf.class))){
               System.out.println(streamB.findFirst().get().toString());
               return "ok";
      }

    参考集成

     <dependency>
                            <groupId>org.springframework.boot</groupId>
                            <artifactId>spring-boot-starter-actuator</artifactId>
                    </dependency>
                    <dependency>
                            <groupId>io.micrometer</groupId>
                            <artifactId>micrometer-registry-prometheus</artifactId>
            /dependency>

    配置

    management.metrics.use-global-registry=true
    management.endpoint.prometheus.enabled=true
    management.endpoint.info.enabled=true
    management.endpoint.metrics.enabled=true
    management.endpoints.web.base-path=/
    management.endpoints.web.exposure.include=prometheus,info

    效果

     

    说明

    做好系统的可观测基础奢侈是比较重要的,核心点重点提供metrics,做好及时的报警以及联动机制

    参考资料

    https://github.com/prometheus/client_java
    https://github.com/brettwooldridge/HikariCP
    https://micrometer.io/

  • 相关阅读:
    【笔记】nRF24L01软件初始化
    【笔记】关于DSP连接CMD文件及连接存储块的理解
    【笔记】CCS4 出现 warning: entrypoint symbol other than "_c_int00" specified: "code_start" 的解决方法
    【转载】低压电流互感器实用技术问答30例
    【笔记】1、防止电压反充电,2、前后加速,3、开口三角PT(TV)原理
    Linux虚拟文件系统及其实例XORFS
    LINUX内核狂想曲之SLOB分配器
    程序的思想决定程序的世界
    LINUX内核之内存屏障
    插入排序——平均算法复杂度分析
  • 原文地址:https://www.cnblogs.com/rongfengliang/p/16511742.html
Copyright © 2020-2023  润新知