当前位置:网站首页 > 数据科学与大数据 > 正文

druid数据库连接池不释放(druid连接池配置文件)




  最近在某个项目的生产环境碰到一个数据库连接问题,使用的连接池是alibaba的druid_1.1.10,问题表现为:DBA监测到应用集群到oracle的连接数总会在半夜降低,并且大大低于每个节点druid配置的minIdle总和。

  一开始怀疑此问题产生的原因是oracle侧主动关闭了连接,但很难去验证这个点,一方面是和DBA沟通起来比较麻烦,另一方面是没有确切的证据,纯粹靠猜想很难服众,所以退而求其次,尝试在druid连接池上去找原因。既然是半夜这种交易量小的时间点降低连接数,那么应该和druid对空闲连接的处理有关。

  在github拉取了druid源码后,载入idea,使用minEvictableIdleTimeMillis进行了全局搜索,在结果列表中找到了一些可能与连接回收有关的类,最终定位到了DruidDataSource的内部类DestoryTask,简单的扫了一眼代码之后,基本就能确定DestroyTask是用于负责检测和销毁空闲连接的类了。

  由于druid源码编译还得花时间研究,我直接搭建了一个简单的springboot工程,引入druid后对DruidDataSource的init()方法打断点,启动应用开始一步步调试...


  DruidDataSource init时会启动一个销毁连接的线程,由于destoryScheduler为空,因此创建了DestroyConnectionThread线程去执行,如下图:

   DestroyConnectionThread做的事情很简单,就是每隔固定的时间去执行一下DestoryTask的run方法,执行的间隔时间基于druid配置timeBetweenEvictionRunsMillis的值:

   DestoryTask的run方法调用shrink方法,该方法是空闲连接检查的核心方法,至于removeAbandoned方法是用于回收借出去但一直未归还的连接(这种连接可能导致连接泄露),它与druid的配置removeAbandoned有关,这里就不细讲了:

  shrink方法逻辑如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

    

 

 

 

 

 

 

  

  

  

 

 

 

 

 

 

 

 

  

  

 

 

 

 

 

 

 

  

 

  

 

 

 

 

 

 

 


  根据调试过程中的源码分析,可知druid_1.1.10判断连接是否销毁还是保活的逻辑如下(只讨论checkTime为true的情况):

  到这里,我们就可以下一个结论了:druid对于空闲连接还是有可能回收的,只要它未开启keepAlive并且闲置时间过长就会回收空闲连接,从而使得连接池中的连接数小于配置的minIdle值。

  为了验证结论,我开启了druid monitor的web页面访问,然后在如下的页面中去观察池中连接的情况:

  与druid空闲连接回收的相关参数配置如下图:

  首先不开启keepAlive功能(druid也是默认关闭的),在应用启动的时候,从druid monitor中观察到连接池中的连接数如下:

  等待大约2~3分钟之后(再此期间不要发起任何数据库请求),再次观察连接池中的连接数,可以发现连接数为0:

  接着配置"spring.datasource.druid.keep-alive=true"以打开keepAlive,重启应用并重复上述过程,结果如下:

  可以发现keepAlive起作用了,池中连接数维持在20,结论得到验证。接着回过头去查看了一下maxEvictableIdleTimeMillis这个参数的默认值为,刚好7个小时,差不多能和DBA监测到的连接降低时间对上。


  在解决问题的过程中,参考了官方文档以及他人在druid项目中提的issue,经历了怀疑问题、确认问题、解决问题三个阶段,不过个人在调试过程中仍然发现有如下问题:

(1)官方的配置文档中对属性minEvictableIdleTimeMillis做了如下描述:

  然而实际上代码体现出来的逻辑并不是这么一回事,maxEvictableIdleTimeMillis更像起到了决定性的作用。

(2)timeBetweenEvictionRunsMillis、minEvictableIdleTimeMillis、maxEvictableIdleTimeMillis这三者设置的大小如果满足一定条件,也会导致keepAlive失效。根据源码,如果在某一轮扫描中(间隔时间timeBetweenEvictionRunsMillis),检测到连接的空闲时间小于minEvictableIdleTimeMillis,那么这些连接不需要keepAlive,自然也不会更新lastActiveTimeMillis,这里存在一个临界条件,使得连接空闲时间同时大于minEvictableIdleTimeMillis和maxEvictableIdleTimeMillis,这个临界条件触发的前提是:

1

2

3

  下面是我的一个测试,druid相关配置情况如图:

  启用应用并静静等待1~2分钟,通过druid monitor查看连接池状态:

  通过浏览器调用一个http查询接口,连接池连接数恢复:

  静静等待1~2分钟,可以看到连接池中的连接又被清空:

  结论:虽然maxEvictableIdleTimeMillis这个参数我们一般不配置,它的默认值也比较大(7小时),但是实际在配置druid时,还是建议考虑keepAlive失效的因素,作为配置的一个考量。


  • issue链接:Druid数据源 , 池中连接数poolingCount 小于 最小空闲连接数 minIdle · Issue #2323 · alibaba/druid · GitHub
  • 配置文档链接:DruidDataSource配置 · alibaba/druid Wiki · GitHub
到此这篇druid数据库连接池不释放(druid连接池配置文件)的文章就介绍到这了,更多相关内容请继续浏览下面的相关推荐文章,希望大家都能在编程的领域有一番成就!

版权声明


相关文章:

  • jdbc数据传输加密(jdbc ssl 数据传输加密)2025-09-23 16:09:08
  • cmip6模式(cmip6模式数据有缺测值嘛)2025-09-23 16:09:08
  • 数据特征分析(数据特征分析方法)2025-09-23 16:09:08
  • point数据分析训练营(point 数据分析)2025-09-23 16:09:08
  • 全文数据库有什么(全文数据库的特点和用途)2025-09-23 16:09:08
  • oppo数据转移小米(oppo数据迁移小米)2025-09-23 16:09:08
  • 达梦数据库设置连接超时(达梦数据库设置连接数)2025-09-23 16:09:08
  • 动态库存表数据不能自动更新(excel表库存动态更新用什么函数)2025-09-23 16:09:08
  • 自动驾驶 数据(自动驾驶数据处理项目)2025-09-23 16:09:08
  • 如何连接redis数据库(怎么连接redis数据库)2025-09-23 16:09:08
  • 全屏图片