druid discard long time none received connection问题解析

摘要:
Druid个人使用摘要:1.从服务器成功接收到的最后一个包有问题。我将jar包升级到1.2.2版本。放弃长时间无接收连接问题。在不更改程序的情况下设置timeBetweenEffectionRunsMillis参数。添加系统。程序Putdruid的getProperties()默认使用usePingMethod方法。此方法不更新连接返回时间,导致lastPacketReceivedTimeMs大于timeBetweenEffectionRunsMillis。互联网上的其他方法觉得他们要么理解得太好,要么不给出具体的实现,要么复制粘贴,希望能帮助遇到这个问题的人。

最新项目中用的druid连接数据库遇到一个困扰很久的问题

1 开始用的druid版本是1.1.22版本,由于业务需求,单个连接需要执行很久,理论上不需要用到自动回收,但为了安全,还是加了自动回收,时间设置的2个小时。

随着程序运行,程序经常报The last packet successfully received from the server was XXXXX milliseconds ago.  The last packet sent successfully to the server was 0 mill
iseconds ago错误,网上搜索了下答案,有说配置项,改数据库事件设置,试过都没有解决,后续看到https://cloud.tencent.com/developer/article/1397508 分析,觉得有一定道理,就开始后续之路

2.druid包升级到1.2.2,原来的问题是没有了,新的问题出现了,discard long time none received connection,又继续网上搜索答案,出来的结果一塌糊涂,很多说版本回退到1.1.22,心里不由的说wc,这...

有点扯,继续进行搜索测试,修改配置项validationQuery,修改testWhileIdle,修改...继续测试,问题依旧,又搜索到运行时添加druid.mysql.usePingMethod=false,但是没说怎样添加,没办法下载源码进行查看,导入源码后发现如下:

 if (valid && isMySql) { // unexcepted branch
                    long lastPacketReceivedTimeMs = MySqlUtils.getLastPacketReceivedTimeMs(conn);
                    if (lastPacketReceivedTimeMs > 0) {
                        long mysqlIdleMillis = currentTimeMillis - lastPacketReceivedTimeMs;
                        if (lastPacketReceivedTimeMs > 0 //
                                && mysqlIdleMillis >= timeBetweenEvictionRunsMillis) {
                            discardConnection(holder);
                            String errorMsg = "discard long time none received connection. "
                                    + ", jdbcUrl : " + jdbcUrl
                                    + ", version : " + VERSION.getVersionNumber()
                                    + ", lastPacketReceivedIdleMillis : " + mysqlIdleMillis;
                            LOG.warn(errorMsg);
                            return false;
                        }
                    }
                }

这在配置中加timeBetweenEvictionRunsMillis:1800000 就可以了,个人理解是一次操作数据库大于这个时间就会被清除,更直观些就是查询或其他操作在数据库执行时间,这里单位是毫秒。

紧接着查看源码druid.mysql.usePingMethod=false这个设置,既然网上有人说,就看看好使不,源码如下:

 configFromProperties(System.getProperties());
    }

    @Override
    public void configFromProperties(Properties properties) {
        String property = properties.getProperty("druid.mysql.usePingMethod");
        if ("true".equals(property)) {
            setUsePingMethod(true);
        } else if ("false".equals(property)) {
            setUsePingMethod(false);
        }
    }

druid加载System.getProperties(),查看属性中的druid.mysql.usePingMethod的对应值,如果false,就不用ping方法,否者用ping方法,进一步查看不用ping方法就是用默认select 1,System.getProperties()查看了下一般是系统的一些参数,但是可以put(key,value),程序启动时间加载进去就可以,项目中用到了定时器(根据自己项目写就可以,加载一次就ok了),就在初始化时间设置了具体值,代码如下:

public void contextInitialized(ServletContextEvent arg0) {
        try {
            System.getProperties().put("druid.mysql.usePingMethod", "false");
            // 获取Scheduler实例
            scheduler = new StdSchedulerFactory().getScheduler();
...

然后取消timeBetweenEvictionRunsMillis设置进行测试,程序跑1个小时没有任何问题,到此问题解决。

druid个人使用总结:

1.The last packet successfully received from the server was问题升级jar包,我是升级到1.2.2版本

2.discard long time none received connection问题不改程序情况下设置timeBetweenEvictionRunsMillis参数(注意是毫秒),改程序下加System.getProperties().put("druid.mysql.usePingMethod", "false")

druid默认使用usePingMethod方法,此方法并不会更新连接返回时间,导致lastPacketReceivedTimeMs大于timeBetweenEvictionRunsMillis

网上其他的方法感觉要不理解太深,没有给出具体实现,要不就是复制粘贴的,希望对遇到此问题的人有所帮助。

--------------------------------------------------------分割线---------------------------------------------------------------------------

本以为到此就ok了,运行了一段时间,日志查看又报The last packet successfully received from the server was XXXX  。。。。

这次崩溃了,看来这个问题不是druid版本的问题,经过了两天的搜索和各种测试,在测试环境下终于100%还原了生产的错误,直接说结果,就是没有解决,重新修改了代码逻辑。

你没有看错,就是没有找到解决方法,接下来说下我测试的各种方法,首先是修改druid配置参数

minIdle=10
validationQuery=select 1
testWhileIdle=true
testOnBorrow=false
testOnReturn=false
keepAlive=true

  这些参数的各种组合我基本上都试过来了,我的测试场景是用druid获取连接,执行一次查询,当前线程停N分钟,当N>15分钟时间,以上各种组合都报The last packet successfully received from the server was XXXX错误,只有一种情况例外,就是运行程序和数据库在同一台服务器上,例如连接的数据库是127.0.0.1,并且在网上搜索发现,有人给出过这个解决方案,就是用localhost或者127.0.0.1。但是我所遇到的是在不同服务器上,最后是修改了逻辑,A模块运行完成后关闭服务,等待B模块运行完成后再重新getconnection。

最终的总结和疑问:

 1.项目和数据库在同一台服务器上时,可以用127.0.0.1去连接本机数据库避免这个问题的出现。

 2.不在同一服务器上时,修改代码逻辑,数据库连接空闲时间控制在10分钟以内不会报这个错误。

疑问:

 1.用c3p0测试,同样出现这个问题,这个错误应该是数据库抛出的异常,并非是jar抛出的?

 2.druid有keepAlive=true设置,不明白为什么没有去执行,或者执行的效果和我测试想到的不一致?

 3.我个人想的是连接空闲10分钟后jar去发送一个select 1的查询,更新下最后包返回的事件,但是这样会出现一个问题,会不会影响实际应用单个执行大于10分钟的应用效果,比如查询4,5张表的关联数据报表,用时20分钟,如果发送select 1去查询,返回的结果是1显然不符合实际业务,但是又没有找到合适的方法去保持连接,由于实际应用没有用到,等到碰到后再进行测试总结,以后有新的进展再进行更新。

免责声明:文章转载自《druid discard long time none received connection问题解析》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇EMQ X 插件持久化系列 (五)MySQL MQTT 数据存储APP设计尺寸规范大全,APP界面设计新手教程【官方版】(转)下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Druid 集群方式部署 —— 启动服务

启动 Master 服务器 拷贝 Druid 的分发包和你修改过的配置到 Master 服务器上。 如果你已经在你的本地计算机上修改了配置,你可以使用 rsync 来进行拷贝。 rsync -az apache-druid-apache-druid-0.21.1/ MASTER_SERVER:apache-druid-apache-druid-0.21....

多数据源切换-Druid

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。本文链接:https://blog.csdn.net/qq_37279783/article/details/82013702 这是实际应用场景中的多数据源切换案例 逻辑思路如下: 1.系统初始化,加载所有数据库中配置的数据源,加载进去spring容器...

Druid 独立服务器方式部署文档

Druid 包含有一组可用的参考配置和用于单机部署的启动脚本: nano-quickstart micro-quickstart small medium large xlarge micro-quickstart 适合于笔记本电脑等小型计算机,主要用于能够快速评估 Druid 的使用场景。 其他的配置包含有针对使用独立服务器进行部署的配置,这些配置通...

诡异的druid链接池链接断开故障经验总结

背景 症状 排查 修复 背景 最近在陆续做机房升级相关工作,配合DBA对产线数据库链接方式做个调整,将原来直接链接读库的地址切换到统一的读负载均衡的代理 haproxy 上,方便机柜和服务器的搬迁。 切换之后线上时不时的会发生 discard connection 错误,导致程序报 500 错误,但不是每次都必现的。 开发框架: spring boo...

利用 druid 解析器解析SQL

最近参与一个开源项目,一个功能的实现,用到了 druid 解析器来解析SQL,记录下如果使用 druid 来解析SQL,实现对SQL的拦截改写。 1. 对 insert 语句进行解析: private static String convertInsertSQL(String sql){ try{ MySqlStatementParser...

springboot postgresql druid连接池和jpa,jdbctemplate执行sql查询

1.maven依赖配置(pom.xml) 1 <dependency> 2 <groupId>org.springframework.boot</groupId> 3 <artifactId>spring-boot-starter</...