1. 程式人生 > >資料連線池預設配置帶來的坑testOnBorrow=false,cloes_wait 終於解決了

資料連線池預設配置帶來的坑testOnBorrow=false,cloes_wait 終於解決了

首先說一下自己程式中遇到的問題,前一段新寫了一個專案,主要為方便公司業務切庫做準備,為其他專案提供介面(spring boot 專案<spring boot + mongo data jpa+mybatis>) 首先呢 多資料來源沒有使用spring boot 整合mybatis,開始有過自己搭建spring boot 都是單資料來源的,所以沒有自己手寫載入資料來源的程式碼(比較懶),在新專案中使用的是阿里的druid連線池,配置當然更簡單了,除了資料庫地址,驅動類,使用者名稱和密碼其他一起都是預設,開始的時候由於專案更新上線頻率比較多,沒有出現太多的問題,而且訪問比較頻繁,接著慢慢提供介面,後來上線了一個 訪問頻率不大的介面,那麼問題就出現了,隔了一段時間,某一臺伺服器掛了,伺服器 netstat -ant | wc -l  六七千,netstat -ant | tail  連結出現大量的close_wait ,很是頭疼,開始從tcp下手找問題,這種狀態的含義其實是表示在等待關閉。怎麼理解呢?當對方close一個SOCKET後傳送FIN報文給自己,你係統毫無疑問地會迴應一個ACK報文給對 方,此時則進入到CLOSE_WAIT狀態。接下來呢,實際上你真正需要考慮的事情是察看你是否還有資料傳送給對方,如果沒有的話,那麼你也就可以 close這個SOCKET,傳送FIN報文給對方,也即關閉連線。所以你在CLOSE_WAIT狀態下,需要完成的事情是等待你去關閉連線。


看了一下不會出現中途死掉的問題,作為服務端關閉處理應該在tomcat上,spring Boot 內嵌的tomcat不可能這麼弱,後來查了一下dump 發現執行緒卡在

sun.misc.Unsafe.park(Unsafe.java:-2) native
java.util.concurrent.locks.LockSupport.park(LockSupport.java:175) 
java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039) 
com.alibaba.druid.pool.DruidDataSource.takeLast(DruidDataSource.java:1521) 
com.alibaba.druid.pool.DruidDataSource.getConnectionInternal(DruidDataSource.java:1146)

 這時候開始考慮資料庫連線池的問題 ,跟了一下程式碼以及其他專案的配置,其中有一個屬性 testOnBorrow設定為false(預設設定為false) testOnBorrow=false由於不檢測池裡連線的可用性,

於是假如連線池中的連線被資料庫關閉了,應用通過連線池getConnection時,都可能獲取到這些不可

用的連線,且這些連線如果不被其他執行緒回收的話,它們不會被連線池被廢除,也不會重新被建立,

佔用了連線池的名額,專案本身作為服務端,資料庫連結被關閉,客戶端呼叫服務端就會出現大量的timeout,客戶端設定了超時時間,然而主動斷開,服務端必然出現close_wait。spring Boot 內嵌的tomcat 預設最大執行緒數是200,很快就掛掉,雖說多數源,沒有問題的資料來源,連結併發過來也會死掉,所以說加大tomcat 預設執行緒(server.tomcat.max-threads=3000)只是短時間內其他資料來源連結不會死掉,現在對比一下連線池 druid 如圖:


spring boot 整合mybatis 預設使用 jdbc連線池

org.apache.tomcat.jdbc.pool預設testOnBorrow=false 



 

但是在 spring boot 整合mybatis時候 卻預設修改了配置如圖:



 

這篇文章解釋的挺不錯

預設的配置不適用所有場景,需要注意一下。

 但是這個鍋不能丟給druid,testOnborrow =true 很大的消耗效能,從而保證伺服器的穩定,可以配合其他配置來避免這一點,配合testWhileIdle=true(但是預設為false) 和timeBetweenEvictionRunsMillis來避免這種問題,這麼重要的幾個配置,為什麼都要預設為false呢,為了提高效率,從而導致伺服器很大的潛在問題?自認為有點兒得不償失,(最起碼預設一種折中的配置感覺比較好)。

下面的註釋為轉來的。很詳細

tomcatde DHCP的配置

<Resource driverClassName="com.microsoft.sqlserver.jdbc.SQLServerDriver" 

logAbandoned="true" maxActive="20" maxIdle="2" maxWait="5000" name="system" 

removeAbandonedTimeout="60" removeAbandoned="true" 

password="xx" type="javax.sql.DataSource"

url="jdbc:sqlserver://127.0.0.1:1433;DatabaseName=base" 

username="sa"/>

當中的

logAbandoned="true"  removeAbandoned="true" removeAbandonedTimeout="60"

就是用來配置資料庫斷開後自動連線的。

資料庫連線池會在啟動時就建立所需的若干連線,並一直保持連線狀態,

但是當資料庫服務停止後,這些連線就被外部因素給中斷了

網上優化了的配置資訊:

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">  

<property name="driverClassName" value="${db.driverClassName}"/>  

<property name="url" value="${db.url}"/>  

<property name="username" value="${db.username}"/>  

<property name="password" value="${db.password}"/>  

<!--initialSize: 初始化連線-->  

<property name="initialSize" value="5"/>  

<!--maxIdle: 最大空閒連線-->  

<property name="maxIdle" value="10"/>  

<!--minIdle: 最小空閒連線-->  

<property name="minIdle" value="5"/>  

<!--maxActive: 最大連線數量-->  

<property name="maxActive" value="15"/>  

<!--removeAbandoned: 是否自動回收超時連線-->  

<property name="removeAbandoned" value="true"/>  

<!--removeAbandonedTimeout: 超時時間(以秒數為單位)-->  

<property name="removeAbandonedTimeout" value="180"/>  

<!--maxWait: 超時等待時間以毫秒為單位 6000毫秒/1000等於60秒-->  

<property name="maxWait" value="3000"/>  

<property name="validationQuery">  

<value>SELECT 1</value>  

</property>  

<property name="testOnBorrow">  

<value>true</value>  

</property>  

</bean>  

dbcp配置中文版本,自apache 官方文件

原文請見http://commons.apache.org/dbcp/configuration.html。

引數  描述

username  傳遞給JDBC驅動的用於建立連線的使用者名稱

password  傳遞給JDBC驅動的用於建立連線的密碼

url  傳遞給JDBC驅動的用於建立連線的URL

driverClassName  使用的JDBC驅動的完整有效的java 類名

connectionProperties  當建立新連線時被髮送給JDBC驅動的連線引數,

格式必須是 [propertyName=property;]*

注意 :引數user/password將被明確傳遞,所以不需要包括在這裡。

引數  預設值  描述

defaultAutoCommit  true  連線池建立的連線的預設的auto-commit狀態

defaultReadOnly  driver default  連線池建立的連線的預設的read-only狀態. 

如果沒有設定則setReadOnly方法將不會被呼叫. (某些驅動不支援只讀模式,比如:Informix)

defaultTransactionIsolation  driver default  連線池建立的連線的預設的TransactionIsolation狀態. 

下面列表當中的某一個: (參考javadoc)

    * NONE

    * READ_COMMITTED

    * READ_UNCOMMITTED

    * REPEATABLE_READ

    * SERIALIZABLE

defaultCatalog   連線池建立的連線的預設的catalog

引數  預設值  描述

initialSize  0  初始化連線:連線池啟動時建立的初始化連線數量,1.2版本後支援

maxActive  8  最大活動連線:連線池在同一時間能夠分配的最大活動連線的數量, 

如果設定為非正數則表示不限制

maxIdle  8  最大空閒連線:連線池中容許保持空閒狀態的最大連線數量,超過的空閒連線將被釋放,

如果設定為負數表示不限制

minIdle  0  最小空閒連線:連線池中容許保持空閒狀態的最小連線數量,低於這個數量將建立新的連線,

如果設定為0則不建立

maxWait  無限  最大等待時間:當沒有可用連線時,連線池等待連線被歸還的最大時間(以毫秒計數),

超過時間則丟擲異常,如果設定為-1表示無限等待

引數  預設值  描述

validationQuery   SQL查詢,用來驗證從連線池取出的連線,在將連線返回給呼叫者之前.如果指定,

則查詢必須是一個SQL SELECT並且必須返回至少一行記錄

testOnBorrow  true  指明是否在從池中取出連線前進行檢驗,如果檢驗失敗,

則從池中去除連線並嘗試取出另一個.

注意: 設定為true後如果要生效,validationQuery引數必須設定為非空字串

testOnReturn  false  指明是否在歸還到池中前進行檢驗

注意: 設定為true後如果要生效,validationQuery引數必須設定為非空字串

testWhileIdle  false  指明連線是否被空閒連接回收器(如果有)進行檢驗.如果檢測失敗,

則連線將被從池中去除.

注意: 設定為true後如果要生效,validationQuery引數必須設定為非空字串

timeBetweenEvictionRunsMillis  -1  在空閒連接回收器執行緒執行期間休眠的時間值,以毫秒為單位.

 如果設定為非正數,則不執行空閒連接回收器執行緒

numTestsPerEvictionRun  3  在每次空閒連接回收器執行緒(如果有)執行時檢查的連線數量

minEvictableIdleTimeMillis  1000 * 60 * 30  連線在池中保持空閒而不被空閒連接回收器執行緒

(如果有)回收的最小時間值,單位毫秒

引數  預設值  描述

poolPreparedStatements  false  開啟池的prepared statement 池功能

maxOpenPreparedStatements  不限制  statement池能夠同時分配的開啟的statements的最大數量, 

如果設定為0表示不限制

這裡可以開啟PreparedStatements池. 當開啟時, 將為每個連線建立一個statement池,

並且被下面方法建立的PreparedStatements將被快取起來:

    * public PreparedStatement prepareStatement(String sql)

    * public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency)

注意: 確認連線還有剩餘資源可以留給其他statement

引數  預設值  描述

accessToUnderlyingConnectionAllowed  false  控制PoolGuard是否容許獲取底層連線

如果容許則可以使用下面的方式來獲取底層連線:

    Connection conn = ds.getConnection();

    Connection dconn = ((DelegatingConnection) conn).getInnermostDelegate();

    ...

    conn.close();

預設false不開啟, 這是一個有潛在危險的功能, 不適當的編碼會造成傷害.

(關閉底層連線或者在守護連線已經關閉的情況下繼續使用它).請謹慎使用,

並且僅當需要直接訪問驅動的特定功能時使用.

注意: 不要關閉底層連線, 只能關閉前面的那個.

引數  預設值  描述

removeAbandoned  false  標記是否刪除洩露的連線,如果他們超過了removeAbandonedTimout的限制.

如果設定為true, 連線被認為是被洩露並且可以被刪除,如果空閒時間超過removeAbandonedTimeout. 

設定為true可以為寫法糟糕的沒有關閉連線的程式修復資料庫連線.

removeAbandonedTimeout  300  洩露的連線可以被刪除的超時值, 單位秒

logAbandoned  false  標記當Statement或連線被洩露時是否列印程式的stack traces日誌。

被洩露的Statements和連線的日誌新增在每個連線開啟或者生成新的Statement,

因為需要生成stack trace。

如果開啟"removeAbandoned",那麼連線在被認為洩露時可能被池回收. 這個機制在(getNumIdle() < 2)

 and (getNumActive() > getMaxActive() - 3)時被觸發.

舉例當maxActive=20, 活動連線為18,空閒連線為1時可以觸發"removeAbandoned".

但是活動連線只有在沒有被使用的時間超過"removeAbandonedTimeout"時才被刪除,預設300秒.

在resultset中游歷不被計算為被使用.

相關推薦

資料連線預設配置帶來testOnBorrow=falsecloes_wait 終於解決

首先說一下自己程式中遇到的問題,前一段新寫了一個專案,主要為方便公司業務切庫做準備,為其他專案提供介面(spring boot 專案<spring boot + mongo data jpa+mybatis>) 首先呢 多資料來源沒有使用spring boot 整合mybatis,開始有過自己

關於最近一直糾纏我的c3p0-config.xml配置檔案找不到的問題終於解決\(^o^)/

從一開始看官方的文件中的說明,關於配置c3p0連線池,如果要使用xml來配置,需要將xml檔案放在classpath的路徑下。所以我就放好了 結果執行後,等待了很久,最後得到一堆紅色的讓人崩潰的error 心態瞬間崩了,喝了一口 雪碧纖維+ (這不是廣告-_-)冷靜一

使用druid連線帶來testOnBorrow=false

使用druid連線池帶來的坑testOnBorrow=false   首先說一下自己程式中遇到的問題,前一段時間新寫了一個專案,主要架構改進,為前端提供介面(spring +springmvc+mybatis) 在新專案中使用的是阿里的druid連線池,配置簡單,除了資料

idea配置阿里Druid資料連線在SSM框架中使用

阿里Druid資料連線池在SSM框架中的配置使用 一、Druid資料連線池簡介 Druid是Java語言中最好的資料庫連線池。Druid能夠提供強大的監控和擴充套件功能。 效能好,同時自帶監控頁面,可以實時監控應用的連線池情況以及其中效能差的sql,方便我們找出應用中連線池方面的問題。

spring配置hibernate 資料來源(資料連線)

現在常用的開源資料連線池主要有c3p0、dbcp和proxool三種,其中:  hibernate開發組推薦使用c3p0;  spring開發組推薦使用dbcp(dbcp連線池有weblogic連線池同樣的問題,就是強行關閉連線或資料庫重啟後,無法reconnect,

spring學習筆記(17)資料庫配置[1]spring資料連線詳解

資料連線池 在spring中,常使用資料庫連線池來完成對資料庫的連線配置,類似於執行緒池的定義,資料庫連線池就是維護有一定數量資料庫連線的一個緩衝池,一方面,能夠即取即用,免去初始化的時間,另一方面,用完的資料連線會歸還到連線池中,這樣就免去了不必要的連線建立

spring下druidc3p0,proxool,dbcp四個資料連線的使用和配置

由於那天Oracle的資料連線是隻能使用dbcp的資料庫連線池才連線上了,所以決定試一下當下所有得資料庫連線池連線orcale和mysql,先上程式碼 配置檔案的程式碼 1 #=================dbcp連線池======================# 2 #Oracle資料庫連線

資料庫連線-資料來源配置

常用的c3p0,DBPC,Druid三大連線池 DBPC <!-- 配置dbcp資料來源 --> <bean id="dataSource2" destroy-method="close" class="org.apache.commons.dbcp.BasicDataSourc

初識資料連線

什麼是資料連線池? 資料庫連線池負責分配、管理和釋放資料庫連線,它允許應用程式重複使用一個現有的資料庫連線,而不是再重新建立一個;釋放空閒時間超過最大空閒時間的資料庫連線來避免因為沒有釋放資料庫連線而引起的資料庫連線遺漏。 為什麼要使用資料連線池? 原因:建立資料庫連線是相當耗時和耗費資

web———資料連線的工作機制是什麼?

1.資料庫連線池屬於建立時間昂貴,並且數量有限的資源。如果每次執行sql時都建立新的連線,使用完即刻關閉連線,不僅會造成資源的浪費,而且在併發量大的情況下還會拖慢甚至拖垮資料庫。(測試得出結果單獨執行緒建立資料庫建立時間遠遠大於執行時間) 2. 因此需要使用連線池的概念:預先建立好一批資

spring jdbc --注:c3p0資料庫連線或druid連線使用配置整理

是Maven配置檔案:pom.xml的程式碼內容: <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:sch

2.3四種執行緒連線配置和使用(和自定義執行緒

四種執行緒連線池的配置和使用 最終呼叫類和方法 {引數有 核心執行緒數目,最大執行緒數目,存活時間(當前執行緒執行完這個任務之後,等待下一個任務到來的最長等待時間。如果在這個時間內沒有新的任務來到,那當前執行緒就會退出),時間單位,等待佇列(用於存放待執行的任務)} public

(mysql版)德魯伊連線配置方法

Mysql的連線池配置方法 先去下載兩個包,匯入bin中百度網盤連結,密碼:n3en 在javaweb專案中的src裡面建立一個字尾為:properties 的File檔案,然後在此檔案頁面中寫下一下程式碼: username=root password

Java程式中insert 執行慢的原因以及c3p0連線配置

今天遇到一個問題,程式中一個insert 操作特別慢, 一直從來沒有遇到過,select 操作如果資料量大的話,是有可能出現這種情況的,但是單條insert插入操作出現這種情況,不知道從何查原因了,debug了確定了就是insert這個操作慢,一開始分析是不是mysql原因,在Navicat上ins

HttpClient4.3 連線引數配置及原始碼解讀

目前所在公司使用HttpClient 4.3.3版本傳送Rest請求,呼叫介面。最近出現了呼叫查詢介面服務慢的生產問題,在排查整個呼叫鏈可能存在的問題時(從客戶端發起Http請求->ESB->服務端處理請求,查詢資料並返回),發現原本的HttpClient連線池中的一些引數配置可能存在問題,如de

c3p0連線xml配置檔案報錯的處理

有下劃線並提示 The word is not correctly spelled, 此問題是Eclipse校驗單詞拼寫造成的。 解決辦法如下:   Window--Preference輸入spell,然後把第一個複選框“Enable spell checking“去掉對勾就

tomcat自帶連線dbcp配置以及優化說明

轉自:http://www.totcms.com/html/201602-29/20160229114145.htm 一個網站每天大概有20萬的訪問量,使用的tomcat自帶dbcp連線池,一般網站訪問很好,速度也很快,但是過一段時間後,總是報timeout waiting for idl

測試c3p0資料連線的使用----簡單筆記

加入jar包 上程式碼 配置檔案 <c3p0-config> <!-- This app is massive! --> <named-config name="myconfig"> <!-- 設定常用

SpringBoot多資料來源連線超時配置(MySQL+SQLServer)

單資料來源超時配置 spring.datasource.url=jdbc:mysql://127.0.0.1:3306/dcmserver?characterEncoding=utf-8 spring.datasource.username=root spring.data

httpclient連線配置方法

HttpClient和Lucene一樣,每個版本的API都變化很大,這有點讓人頭疼。 筆者碰到的情況最早在hadoop環境用httpclient發起httpjson請求,在本地除錯的時候用的4.5.2版本,放到hadoop環境中執行報錯,無奈只好將httpclient降級成