Druid链接Impala持续失败缘由调查

一个使用Druid链接Impala的服务项目实例抛出了一个com.alibaba.druid.pool.GetConnectionTimeoutException异常,当时的链接池监控数据以下:java

wait millis 5000, active 0, maxActive 50, creating 1
复制代码

看似是普通的获取链接超时的问题,但该实例在随后一直保持对Impala获取链接失败的状态,同一个项目下的其余实例并无发生相似的链接问题,能够排除Impala服务器端的问题,问题定位范围是在通信网络或者Impala客户端(项目实例)上。apache

持续不断的运行日志打印都现实creating 1这个信息,这表示Druid一直保持建立(物理/TCP)链接的状态,这里须要先说明一下Druid建立链接的机制。bash

Druid创建底层链接的方法是调用DruidDataSource.createPhysicalConnection()方法实现的,调用的时机和方式有如下几种:服务器

  • 初始化时直接调用
  • CreateConnectionThread 线程实例调用
  • CreateConnectionTask 任务实例调用

当用户没有设置 createScheduler, 即 createScheduler == null 时, 后续全部链接的建立工做是由 CreateConnectionThread 线程实例去完成。该线程的建立只出如今一个方法中:网络

protected void createAndStartCreatorThread() {
        if (createScheduler == null) {
            String threadName = "Druid-ConnectionPool-Create-" + System.identityHashCode(this);
            createConnectionThread = new CreateConnectionThread(threadName);
            createConnectionThread.start();
            return;
        }

        initedLatch.countDown();
    }
复制代码

该方法仅在初始化DruidDataSource.init()方法调用过一次,即链接建立线程数量为 1socket

同时,在项目的配置以下:ide

initialSize = 0
minIdle = 0
minEvictableIdleTimeMillis = 0
maxEvictableIdleTimeMillis = 0
maxActive = 50
maxWait = 5000
isTestOnBorrow = false
isLogAbandoned
isRemoveAbandoned = true
removeAbandonedTimeout = 60 * 10
复制代码

针对链接超时的配置仅有maxActive参数,表示获取链接的最长时间,该参数在Druid实现,是获取链接的主线程等待链接返回而循环休眠的最大时长。ui

在项目中,使用jstack命令查看CreateConnectionThread线程的状态this

"Druid-ConnectionPool-Create-1942750238" #122 daemon prio=5 os_prio=31 tid=0x00007ff2ba81c000 nid=0x8907 runnable [0x0000700009ec7000]
   java.lang.Thread.State: RUNNABLE
	at java.net.SocketInputStream.socketRead0(Native Method)
	at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
	at java.net.SocketInputStream.read(SocketInputStream.java:171)
	at java.net.SocketInputStream.read(SocketInputStream.java:141)
	at java.io.BufferedInputStream.fill(BufferedInputStream.java:246)
	at java.io.BufferedInputStream.read1(BufferedInputStream.java:286)
	at java.io.BufferedInputStream.read(BufferedInputStream.java:345)
	- locked <0x00000007b01c1240> (a java.io.BufferedInputStream)
	at org.apache.thrift.transport.TIOStreamTransport.read(TIOStreamTransport.java:127)
复制代码

该线程被阻塞在了一个方法上,问题就在这里:建立链接的线程被阻塞在等待与Impala建连的通信数据上,后续全部链接的获取都必然会天然等待到超时。那么该线程的状态能够恢复吗?url

模拟一下这种异常状况,使用nc -l ${impala-port}监听本地的端口,同时用将链接url的地址host到本地,运行程序。由于本地不存在Impala服务,因此天然响应不了这个建连过程,同时咱们将url修改host至正确的Impala地址,会发现CreateConnectionThread线程会一直保持被阻塞状态,没有恢复(取消本地端口监听能够时线程脱离阻塞状态)。

那么如何解决这个问题呢?主要是避免建连线程一直阻塞,有几个方向:

  • 设置建连过程的超时:此类参数是Driver的链接参数,有read timeoutsocket timeout
  • 设置createScheduler变量,避免单线程建连

TODO HiveDriver 建连代码分析

相关文章
相关标签/搜索