JDBC未设置socket超时导致应用程序的线程池阻塞

55 篇文章 1 订阅
27 篇文章 0 订阅

应用阻塞,查看堆栈发现线程阻塞在线程池的同步方法上,而进入同步方法的线程在等待socket读。

推测为网络问题导致的连接阻塞,但应用未设置socket超时而一直等待。网上说JDBC通过socket实现,无法主动探知网络错误,而socket通过TCP/IP实现应用也无法主动发现数据库连接断开。如果没有设置socket timeout的话,应用在数据库返回结果前会无期限地等下去,这种连接被称为dead connection。为了避免dead connections,socket必须要有超时配置。socket timeout可以通过JDBC的api设置也可在操作系统设置。套接字底层是基于TCP的,所以socket的超时和TCP超时是相同的。

为了防止下次出现这种情况设置了JDBC的socket连接超时socketTimeout

 不同驱动的socketTimeout配置项

JDBC DriverconnectTimeout配置项socketTimeout配置项url格式示例
MySQL DriverconnectTimeout(默认值:0,单位:ms)socketTimeout(默认值:0,单位:ms)jdbc:mysql://[host:port],[host:port]…/[database][?propertyName1][=propertyValue1][&propertyName2][=propertyValue2]…jdbc:mysql://xxx.xx.xxx.xxx:3306/database?connectTimeout=60000&socketTimeout=60000
MS-SQL DriverjTDS DriverloginTimeout(默认值:0,单位:s)socketTimeout(默认值:0,单位:s)jdbc:jtds:<server_type>://<server>[:<port>][/<database>][;<property>=<value>[;...]]jdbc:jtds:sqlserver://server:port/database;loginTimeout=60;socketTimeout=60
Oracle Thin Driveroracle.net.CONNECT_TIMEOUT (默认值:0,单位:ms)oracle.jdbc.ReadTimeout(默认值:0,单位:ms)不支持 通过url配置,只能通过OracleDatasource.setConnectionProperties() API设置,使用DBCP时可以调用BasicDatasource.setConnectionProperties()或 BasicDatasource.addConnectionProperties()进行设置 
CUBRID Thin Driver无独立配置项(默认值:5,000,单位:ms)无独立配置项(默认值:5,000,单位:ms)  

看网上说必须设置socket超时,设置connect超时不生效,因为socket更底层一些,需要通过JDBC的api设置。如图显示socket超时的设置

附:TCP的三次握手和四次挥手

vi /etc/sysctl.conf 修改

net.ipv4.tcp_syn_retries参数

该参数同样可以在/proc/sys/net/ipv4/tcp_syn_retries进行设置.

net.ipv4.tcp_syn_retries参数是tcp的syn最大重发次数。tcp建立连接的过程从客户端发送syn包开始。如果客户端没有收到这个syn包的回复,内核会重试多次发送syn包,每次重试的间隔都会逐渐增加,避免发送太多的syn包影响网络。tcp_syn_retries越大阻塞时间越长。

如果是httpclient也是一样的增加超时处理:

httpClient3.1只支持3种timeout的设置:

  1. connectionTimeout  :  socket建立链接的超时时间,Httpclient包中通过一个异步线程去创建socket链接,对应的超时控制。
  2. timeoutInMilliseconds :  socket read数据的超时时间, socket.setSoTimeout(timeout);
  3. httpConnectionTimeout :  如果那个的是MultiThreadedHttpConnectionManager,对应的是从连接池获取链接的超时时间

        HttpClient client = new HttpClient();
        client.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, CONNECTION_TIMEOUT);
        client.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT, SO_TIMEOUT);

 

参考文章:

https://www.jianshu.com/p/2deaf51bf715

https://blog.csdn.net/san_yun/article/details/84447334

https://blog.csdn.net/sinat_17736151/article/details/82804404

https://blog.csdn.net/largetalk/article/details/16863689

http://willbryant.net/overriding_the_default_linux_kernel_20_second_tcp_socket_connect_timeout

https://blog.csdn.net/profesir/article/details/52534390

https://www.cnblogs.com/whuqin/p/5580895.html

https://blog.csdn.net/jiaomingliang/article/details/45950591

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值