背景

在应用端通过mybatis的interceptor自定义Plugin拦截Executor, 统计输出sql的执行耗时。

今天生产发生一个很奇怪的问题: 莫名其妙卡顿15分钟+,其后正常返回sql正常结果! 使用druid版本是1.0.2。。。。。

日志分析

统计发现:

  1. 出现该情况的单量有6笔,集中在特定的2个小时之内,都是查询sql;都发生在1台应用服务器上。
  2. 在这几笔订单卡住的时间内,轮询任务触发又正常查询成功并正确处理成功!
  3. 数据库层面没有慢sql;且数据库实例的指标监控稳定,应用监控除sql耗时监控异常外,其他一切正常。
  4. 日志没有输出error

推测是否是在getConnection过程中出现了等待。但因获取连接时的日志过少找不到具体的原因!

DruidDataSource的testConnectionInternal

网上的类似问题说的原因是Druid在从连接池中获取的连接(代码详见:DruidDataSource的getConnectionDirect),在开启testWhileIdle时,如果活跃时间距离当前比较久,那么将验证该连接是否有效,无效会discardConnection并再次去pool内获取。

这个过程可能被数据库层面的防火墙策略已经关闭该连接,而客户端还傻傻的发sql验证直到超时。。。。

在该测试连接的方法中有一个查询超时超时时间:validationQueryTimeout。测试中是-1, 执行的是默认时间。。。。这个默认时间没有找到!! (有找到MappedStatementConfig由SqlMapConfiguration的defaultStatementTimeout)

深入理解JDBC的超时设置

应用与数据库间的timeout层级实例:
转帖:深入理解JDBC的超时设置

上层的timeout依赖于下层的timeout,只有下层的timeout无误时,上层的timeout才能确保正常。eg.  当socket timeout出现问题时,上层的statement timeout和transaction timeout都将失效。
 statement timeout 无法处理网络连接失败时的超时,它能做的仅仅是限制statement的操作时间;网络连接失败时的timeout必须交由JDBC来处理;JDBC的socket timeout会受到操作系统socket timeout设置的影响。

  1. Transaction Timeout: 一般存在于框架(Spring, EJB)或应用级。spring在配置事务切面的时候可以配置timeout。

  2. Statement Timeout: 通过调用JDBC的java.sql.Statement.setQueryTimeout(int timeout) API进行设置。 以myBatis为例,statement timeout的默认值可以通过sql-map-config.xml中的defaultStatementTimeout 属性进行设置。同时,也可以设置sqlmap中select,insert,update标签的timeout属性,从而对不同sql语句的超时时间进行独立的配置。

  3. JDBC的statement timeout:  通过调用Connection的createStatement()方法创建statement来executeQuery时,会注册一个 TimerTask ->CancelTask 用来给Timer -> ConnectionImpl.getCancelTimer()来处理timeout事项:发送 "KILL QUERY” 。 代码详见: StatementImpl 及 ConnectionImpl

  4. JDBC的socket timeout: 

    1. 由于TCP/IP的结构原因,socket没有办法探测到网络错误,因此应用也无法主动发现数据库连接断开。如果没有设置socket timeout的话,应用在数据库返回结果前会无期限地等下去,这种连接被称为dead connection。 为了避免dead connections,socket必须要有超时配置。socket timeout可以通过JDBC设置,socket timeout能够避免应用在发生网络错误时产生无休止等待的情况,缩短服务失效的时间。不推荐使用socket timeout来限制statement的执行时长,因此socket timeout的值必须要高于statement timeout,否则,socket timeout将会先生效,这样statement timeout就变得毫无意义,也无法生效。
      eg.   jdbc:mysql://xxx.xx.xxx.xxx:3306/database?connectTimeout=60000&socketTimeout=60000

  5. 操作系统的socket timeout配置

番外

MySQL JDBC的queryTimeout的一个坑

在该文章中说Statement.setQueryTimeout : 如果设置的超时时间过长,在当大批量的SQL同时执行时,每一个SQL都会创建一个CancelTask对象,虽然很快执行完,且会调用CancelTask.cancel()方法,但是CancelTask方法的源代码仅仅是将自己的状态修改为:CANCELLED,而并不会直接从队列中移除这个对象, 导致OOM。 建议在cancel()后需要purge一下。

解: MySQL Connector Java 5.1.44  版本 的 StatementImpl 已经有了purge; 且 在1.8版本的JDK对Timer的cancel()也增加了移除queue内容

Timer

     public int purge() {
int result = 0; synchronized(queue) {
for (int i = queue.size(); i > 0; i--) {
if (queue.get(i).state == TimerTask.CANCELLED) {
queue.quickRemove(i);
result++;
}
} if (result != 0)
queue.heapify();
} return result;
}
} public void cancel() {
synchronized(queue) {
thread.newTasksMayBeScheduled = false;
queue.clear();
queue.notify(); // In case queue was already empty.
}
}

类似问题

通过网上blog查找发现有相似的问题存在:

    1. https://www.oschina.net/question/1450045_2157629

    2. https://www.2cto.com/database/201505/402016.html

    3. 在issues中搜索druid的testWhileIdle问题: https://github.com/alibaba/druid/issues/1260

转载地址:https://my.oschina.net/u/3434392/blog/3017866

druid socket timeout超时15分钟(转载)的更多相关文章

  1. VC socket Connect 超时时间设置

    设置connect超时很简单,CSDN上也有人提到过使用select,但却没有一个令人满意与完整的答案.偶所讲的也正是select函数,此函数集成在winsock1.1中,简单点讲,"作用使 ...

  2. connect socket的超时设置

    最近项目中,有个需求是检测某ip地址是否是通的,使用了socket的connect函数.但是,当ip地址写错的话,connect就会一直阻塞在那里,大概2.3分钟才能返回连接失败.这对于用户来说是不可 ...

  3. 15分钟从零开始搭建支持10w+用户的生产环境(三)

    上一篇文章介绍了这个架构中,选择MongoDB做为数据库的原因,及相关的安装操作. 原文地址:15分钟从零开始搭建支持10w+用户的生产环境(二)   三.WebServer 在SOA和gRPC大行其 ...

  4. 15分钟从零开始搭建支持10w+用户的生产环境(四)

    上一篇文章,介绍了这个架构中,WebServer的选择,以及整个架构中扩展时的思路. 原文地址:15分钟从零开始搭建支持10w+用户的生产环境(三)   五.架构实践 前边用了三篇文章,详细介绍了这个 ...

  5. Bash脚本15分钟进阶教程

    转载: Bash脚本15分钟进阶教程 这里的技术技巧最初是来自谷歌的"Testing on the Toilet" (TOTT).这里是一个修订和扩增版本. 脚本安全 我的所有ba ...

  6. C# Socket连接超时设置

    问题描述:         对于C# Socket没有超时设置的选项,默认情况下进行Socket连接,返回连接失败需要20-30s时间,严重影响用户体验 问题解决: Socket服务器端: Socke ...

  7. perl Socket接收超时设置

    一般来说, IO::Socket::INET里的Timeout设置是对于conncet的 如果你想设置recv接收超时, 可以这样设置: usr Socket: ...... , )); #注意这里p ...

  8. 15分钟在笔记本上搭建 Kubernetes + Istio开发环境

    11月13~15日,KubeCon 上海大会召开,云原生是这个秋天最火热的技术.很多同学来问如何上手 Kubernetes和Istio 服务网格开发.本文将帮助你利用Docker CE桌面版,15分钟 ...

  9. socket.timeout: The read operation timed out 更改pip源至国内镜像,显著提升下载速度

    出现socket.timeout: The read operation timed out  错误的时候,可能是pip源不稳定,改改试试看!  经常在使用Python的时候需要安装各种模块,而pip ...

随机推荐

  1. 096-PHP循环使用next取数组元素

    <?php function return_item($arr,$num=0){ //定义函数 for($i=0;$i<$num;$i++){ //循环向前移动数组指针 next($arr ...

  2. C++ do while无限循环~

    #include<iostream> using namespace std; #include<Windows.h> int main() { ; ; system(&quo ...

  3. POJ 1770 树形DP

    咋一看确实想到的是树形DP,但是我一开始也马上想到环的情况,这样应该是不可以进行树形DP的,然后我自以为是地想用有向图代替无向图,而且总是从能量高的指向能量低的,这样自以为消除了环,但是其实是不对滴, ...

  4. 关于c++静态类的说法

    看了网上的观点,大致有这几种比较好的. 观点一:根据现代的C++观点,静态类没有必要存在于C++中. 一个类是对一个概念的描述,类的本质是它维护了一个不变式,也就是说它有一个状态,它所有的接口都是为了 ...

  5. 面向对象-main函数

    面向对象-main函数 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任.   一.编写main函数测试代码 /** * * @author 尹正杰 * */ public class ...

  6. PHP ~ 设置和读取 Cookie

    一,设置 Cookie setcookie("user",$user,time()+3600);     // user 为用户名,$user 为变量的值   二,读取 Cooki ...

  7. 七、CI框架之分配变量数组,循环输出

    一.添加并传递变量 二.在View界面输出 输出显示 不忘初心,如果您认为这篇文章有价值,认同作者的付出,可以微信二维码打赏任意金额给作者(微信号:382477247)哦,谢谢.

  8. IDEA的一些常用设置

    一.给方法之间添加分割线 效果: 二.自动导包 三.字体以及大小和行间距 四.注释的字体颜色 五.项目编码 六.省点模式(开启省点模式后会取消代码检查和提示等,需要注意) 七.代码垂直或者水平分区显示 ...

  9. 2020PHP面试-PHP篇

    一.列举一些PHP的设计模式 单例模式:保证在整个应用程序的生命周期中,任何一个时刻,单例类的实例都只存在一个,同时这个类还必须提供一个访问该类的全局访问点. 工厂模式:定义一个创建对象的接口,但是让 ...

  10. PAT Advanced 1018 Public Bike Management (30) [Dijkstra算法 + DFS]

    题目 There is a public bike service in Hangzhou City which provides great convenience to the tourists ...