連線池 druid

xz43發表於2015-11-03

Druid是一個強大的新興資料庫連線池,相容DBCP,是阿里巴巴做的開源專案.

不僅提供了強悍的資料來源實現,還內建了一個比較靠譜的監控元件。 

GitHub專案主頁: 

QQ群:  點選連結加入群【阿里開源技術交流

演示地址: 

常見問題回答請參考: 

一篇CSDN對Druid的介紹  druid簡單教程

因為想要監控資料,又不願意誰都可以訪問,所以想要配置個密碼.在開源群裡一問,就知道原來內部已經有實現了.

先貼完成後的程式碼:

web.xml 部分:


[html] view plaincopy
  1. <!-- Druid,監控資料庫,以及WEB訪問連線資訊 -->  
  2. <!-- 參考: %E9%85%8D%E7%BD%AE_%E9%85%8D%E7%BD%AEWebStatFilter -->  
  3. <filter>  
  4.     <filter-name>DruidWebStatFilter</filter-name>  
  5.     <filter-class>com.alibaba.druid.support.http.WebStatFilter</filter-class>  
  6.     <init-param>  
  7.         <param-name>exclusions</param-name>  
  8.         <param-value>*.js,*.gif,*.jpg,*.png,*.css,*.ico,*.jsp,/druid/*,/download/*</param-value>  
  9.     </init-param>  
  10.     <init-param>  
  11.         <param-name>sessionStatMaxCount</param-name>  
  12.         <param-value>2000</param-value>  
  13.     </init-param>  
  14.     <init-param>  
  15.         <param-name>sessionStatEnable</param-name>  
  16.         <param-value>true</param-value>  
  17.     </init-param>  
  18.     <init-param>  
  19.         <param-name>principalSessionName</param-name>  
  20.         <param-value>session_user_key</param-value>  
  21.     </init-param>  
  22.     <init-param>  
  23.         <param-name>profileEnable</param-name>  
  24.         <param-value>true</param-value>  
  25.     </init-param>  
  26. </filter>  
  27. <filter-mapping>  
  28.     <filter-name>DruidWebStatFilter</filter-name>  
  29.     <url-pattern>/*</url-pattern>  
  30. </filter-mapping>  
  31. <!-- 配置 Druid 監控資訊顯示頁面 -->  
  32. <servlet>  
  33.     <servlet-name>DruidStatView</servlet-name>  
  34.     <servlet-class>com.alibaba.druid.support.http.StatViewServlet</servlet-class>  
  35.     <init-param>  
  36.         <!-- 允許清空統計資料 -->  
  37.         <param-name>resetEnable</param-name>  
  38.         <param-value>true</param-value>  
  39.     </init-param>  
  40.     <init-param>  
  41.         <!-- 使用者名稱 -->  
  42.         <param-name>loginUsername</param-name>  
  43.         <param-value>druid</param-value>  
  44.     </init-param>  
  45.     <init-param>  
  46.         <!-- 密碼 -->  
  47.         <param-name>loginPassword</param-name>  
  48.         <param-value>druid</param-value>  
  49.     </init-param>  
  50. </servlet>  
  51. <servlet-mapping>  
  52.     <servlet-name>DruidStatView</servlet-name>  
  53.     <url-pattern>/druid/*</url-pattern>  
  54. </servlet-mapping>  

下面分享一下如何查詢的。


首先,因為使用的是 MAVEN, 所以檢視原始碼時maven會自動幫你下載. 我們在 web.xml 中點選com.alibaba.druid.support.http.StatViewServlet 進入class檔案,等一會原始碼下載好就可以檢視. 發現有類似下面這樣的程式碼: 


[java] view plaincopy
  1. public class StatViewServlet extends ResourceSerlvet {  
  2.   
  3.     private final static Log      LOG                     = LogFactory.getLog(StatViewServlet.class);  
  4.   
  5.     private static final long     serialVersionUID        = 1L;  
  6.   
  7.     public static final String    PARAM_NAME_RESET_ENABLE = "resetEnable";  
  8.   
  9.     public static final String    PARAM_NAME_JMX_URL      = "jmxUrl";  
  10.     public static final String    PARAM_NAME_JMX_USERNAME = "jmxUsername";  
  11.     public static final String    PARAM_NAME_JMX_PASSWORD = "jmxPassword";  
  12.   
  13.     private DruidStatService      statService             = DruidStatService.getInstance();  
  14.   
  15.     /** web.xml中配置的jmx的連線地址 */  
  16.     private String                jmxUrl                  = null;  
  17.     /** web.xml中配置的jmx的使用者名稱 */  
  18.     private String                jmxUsername             = null;  
  19.     /** web.xml中配置的jmx的密碼 */  
  20.     private String                jmxPassword             = null;  
  21. .........  

可以看出,繼承了StatViewServlet extends ResourceSerlvet


而在其中的 jmxUrl、jmxUsername 和 jmxPassword 很顯然是連線遠端 JMX時使用的,那麼我就想著去看看父類: com.alibaba.druid.support.http.ResourceSerlvet


[java] view plaincopy
  1. @SuppressWarnings("serial")  
  2. public abstract class ResourceSerlvet extends HttpServlet {  
  3.   
  4.     private final static Log   LOG                 = LogFactory.getLog(ResourceSerlvet.class);  
  5.   
  6.     public static final String SESSION_USER_KEY    = "druid-user";  
  7.     public static final String PARAM_NAME_USERNAME = "loginUsername";  
  8.     public static final String PARAM_NAME_PASSWORD = "loginPassword";  
  9.     public static final String PARAM_NAME_ALLOW    = "allow";  
  10.     public static final String PARAM_NAME_DENY     = "deny";  
  11.     public static final String PARAM_REMOTE_ADDR   = "remoteAddress";  
  12.   
  13.     protected String           username            = null;  
  14.     protected String           password            = null;  
  15. ..........  

看到了 username 和 password,很高興,先配置了試試,但是配置這兩個初始化引數後沒起作用,於是繼續查詢. 看到了 service方法,我們知道,Servlet的業務邏輯就是從這裡開始的。



[java] view plaincopy
  1. public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {  
  2.     ......  
  3.     if (isRequireAuth() //  
  4.         && !ContainsUser(request)//  
  5.         && !("/login.html".equals(path) //  
  6.              || path.startsWith("/css")//  
  7.              || path.startsWith("/js"//  
  8.         || path.startsWith("/img"))) {  
  9.         if (contextPath == null || contextPath.equals("") || contextPath.equals("/")) {  
  10.             response.sendRedirect("/druid/login.html");  
  11.         } else {  
  12.             if ("".equals(path)) {  
  13.                 response.sendRedirect("druid/login.html");  
  14.             } else {  
  15.                 response.sendRedirect("login.html");  
  16.             }  
  17.         }  
  18.         return;  
  19.     }  
  20. ......  

發現呼叫了  isRequireAuth() 方法,看著像是判斷是否需要授權驗證,於是進去看



[java] view plaincopy
  1. public boolean isRequireAuth() {  
  2.     return this.username != null;  
  3. }  


那現在知道是 username 在作怪,也設定了,但是沒有起作用,於是搜尋 username ,

[java] view plaincopy
  1. public void init() throws ServletException {  
  2.     initAuthEnv();  
  3. }  
  4.   
  5. private void initAuthEnv() {  
  6.     String paramUserName = getInitParameter(PARAM_NAME_USERNAME);  
  7.     if (!StringUtils.isEmpty(paramUserName)) {  
  8.         this.username = paramUserName;  
  9.     }  
  10.   
  11.     String paramPassword = getInitParameter(PARAM_NAME_PASSWORD);  
  12.     if (!StringUtils.isEmpty(paramPassword)) {  
  13.         this.password = paramPassword;  
  14.     }  
  15.   ......  
然後發現了初始化驗證環境時使用了PARAM_NAME_USERNAME這個引數,順便的學習了一個新API: getInitParameter 方法獲取 Servlet的初始化引數, 是HttpServlet的父類 GenericServlet 類提供的:
[java] view plaincopy
  1. String paramUserName = getInitParameter(PARAM_NAME_USERNAME);  
那麼很簡單,找到 PARAM_NAME_USERNAME 即可:
[java] view plaincopy
  1. public static final String PARAM_NAME_USERNAME = "loginUsername";  
  2. public static final String PARAM_NAME_PASSWORD = "loginPassword";  
於是在 web.xml 中換上,OK,成功進行了攔截.

 配置屬性列表

配置

預設值

說明

name

配置這個屬性的意義在於,如果存在多個資料來源,監控的時候可以透過名字來區分開來。
如果沒有配置,將會生成一個名字,格式是:"DataSource-" + System.identityHashCode(this)

jdbcUrl

連線資料庫的url,不同資料庫不一樣。例如:
mysql : jdbc:mysql://10.20.153.104:3306/druid2 
oracle : jdbc:oracle:thin:@10.20.149.85:1521:ocnauto

username

連線資料庫的使用者名稱

password

連線資料庫的密碼。如果你不希望密碼直接寫在配置檔案中,可以使用ConfigFilter。詳細看這裡:

driverClassName

根據url自動識別

這一項可配可不配,如果不配置druid會根據url自動識別dbType,然後選擇相應的driverClassName

initialSize

0

初始化時建立物理連線的個數。初始化發生在顯示呼叫init方法,或者第一次getConnection

maxActive

8

最大連線池數量

maxIdle

8

已經不再使用,配置了也沒效果

minIdle

最小連線池數量

maxWait

獲取連線時最大等待時間,單位毫秒。配置了maxWait之後,預設啟用公平鎖,併發效率會有所下降,如果需要可以透過配置useUnfairLock屬性為true使用非公平鎖。

poolPreparedStatements

false

是否快取preparedStatement,也就是PSCachePSCache對支援遊標的資料庫效能提升巨大,比如說oracle。在mysql下建議關閉。

maxOpenPreparedStatements

-1

要啟用PSCache,必須配置大於0,當大於0時,poolPreparedStatements自動觸發修改為true。在Druid中,不會存在OraclePSCache佔用記憶體過多的問題,可以把這個數值配置大一些,比如說100

validationQuery

用來檢測連線是否有效的sql,要求是一個查詢語句。如果validationQuerynulltestOnBorrowtestOnReturntestWhileIdle都不會其作用。

testOnBorrow

true

申請連線時執行validationQuery檢測連線是否有效,做了這個配置會降低效能。

testOnReturn

false

歸還連線時執行validationQuery檢測連線是否有效,做了這個配置會降低效能

testWhileIdle

false

建議配置為true,不影響效能,並且保證安全性。申請連線的時候檢測,如果空閒時間大於timeBetweenEvictionRunsMillis,執行validationQuery檢測連線是否有效。

timeBetweenEvictionRunsMillis

有兩個含義:
1) Destroy
執行緒會檢測連線的間隔時間 2) testWhileIdle的判斷依據,詳細看testWhileIdle屬性的說明

numTestsPerEvictionRun

不再使用,一個DruidDataSource只支援一個EvictionRun

minEvictableIdleTimeMillis

connectionInitSqls

物理連線初始化的時候執行的sql

exceptionSorter

根據dbType自動識別

當資料庫丟擲一些不可恢復的異常時,拋棄連線

filters

屬性型別是字串,透過別名的方式配置擴充套件外掛,常用的外掛有:
監控統計用的filter:stat 日誌用的filter:log4j 防禦sql注入的filter:wall

proxyFilters

型別是List<com.alibaba.druid.filter.Filter>,如果同時配置了filtersproxyFilters,是組合關係,並非替換關係

 

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/9399028/viewspace-1821979/,如需轉載,請註明出處,否則將追究法律責任。

相關文章