日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

阿里云sql监控配置-druid

發(fā)布時(shí)間:2023/11/30 编程问答 65 豆豆
生活随笔 收集整理的這篇文章主要介紹了 阿里云sql监控配置-druid 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

? 今天我們說說數(shù)據(jù)源和數(shù)據(jù)庫(kù)連接池,熟悉java開發(fā)的同仁應(yīng)該都了解C3PO,在這里不做過多的贅述了,今天我們說的是阿里DRUID,druid是后起之秀,因?yàn)樗膬?yōu)秀很快占領(lǐng)了使用市場(chǎng),下邊我們一起來看看druid數(shù)據(jù)源的配置以及druid監(jiān)控的配置和監(jiān)控的實(shí)現(xiàn)邏輯。

1、druid數(shù)據(jù)源配置

? ? ? ?下面是druid的數(shù)據(jù)源配置項(xiàng),這些配置項(xiàng)都是com.alibaba.druid.pool.DruidDataSource類和其基類com.alibaba.druid.pool.DruidAbstractDataSource的public final屬性,這些配置型和C3P0的數(shù)據(jù)源配置項(xiàng)基本一樣,有個(gè)別的是明白發(fā)生了變化但是參數(shù)所表示的意思不變,還有一些參數(shù)是druid自己擴(kuò)展的,其中filters屬性就是杰出代表,次屬性是DruidAbstractDataSource類的,是一個(gè)List<Filter>的集合,此屬性提供了三個(gè)可選值:監(jiān)控統(tǒng)計(jì)用的stat、日志用的log4j、?防御sql注入的wall,這三個(gè)值可以單獨(dú)使用也可以兩兩組合或者一起使用,組合使用的時(shí)候不同值之間用逗號(hào)隔開。有人可能會(huì)有疑問了,不是一個(gè)List集合嗎,為什么這里卻是用逗號(hào)分隔的,那是因?yàn)閐ruid在賦值的時(shí)候有特殊處理,至于是如何處理的在下邊我們會(huì)說到。

配置缺省值說明
name?配置這個(gè)屬性的意義在于,如果存在多個(gè)數(shù)據(jù)源,監(jiān)控的時(shí)候
可以通過名字來區(qū)分開來。如果沒有配置,將會(huì)生成一個(gè)名字,
格式是:"DataSource-" + System.identityHashCode(this)
jdbcUrl?連接數(shù)據(jù)庫(kù)的url,不同數(shù)據(jù)庫(kù)不一樣。例如:
mysql : jdbc:mysql://10.20.153.104:3306/druid2?
oracle : jdbc:oracle:thin:@10.20.149.85:1521:ocnauto
username?連接數(shù)據(jù)庫(kù)的用戶名
password?連接數(shù)據(jù)庫(kù)的密碼。如果你不希望密碼直接寫在配置文件中,
可以使用ConfigFilter。詳細(xì)看這里:
https://github.com/alibaba/druid/wiki/%E4%BD%BF%E7%94%A8ConfigFilter
driverClassName根據(jù)url自動(dòng)識(shí)別這一項(xiàng)可配可不配,如果不配置druid會(huì)根據(jù)url自動(dòng)識(shí)別dbType,
然后選擇相應(yīng)的driverClassName
initialSize0初始化時(shí)建立物理連接的個(gè)數(shù)。初始化發(fā)生在顯示調(diào)用init方法,
或者第一次getConnection時(shí)
maxActive8最大連接池?cái)?shù)量
maxIdle8已經(jīng)不再使用,配置了也沒效果
minIdle?最小連接池?cái)?shù)量
maxWait?獲取連接時(shí)最大等待時(shí)間,單位毫秒。配置了maxWait之后,
缺省啟用公平鎖,并發(fā)效率會(huì)有所下降,
如果需要可以通過配置useUnfairLock屬性為true使用非公平鎖。
poolPreparedStatementsfalse是否緩存preparedStatement,也就是PSCache。
PSCache對(duì)支持游標(biāo)的數(shù)據(jù)庫(kù)性能提升巨大,比如說oracle。
在mysql5.5以下的版本中沒有PSCache功能,建議關(guān)閉掉。
5.5及以上版本有PSCache,建議開啟。
maxOpenPreparedStatements-1要啟用PSCache,必須配置大于0,當(dāng)大于0時(shí),
poolPreparedStatements自動(dòng)觸發(fā)修改為true。
在Druid中,不會(huì)存在Oracle下PSCache占用內(nèi)存過多的問題,
可以把這個(gè)數(shù)值配置大一些,比如說100
validationQuery?用來檢測(cè)連接是否有效的sql,要求是一個(gè)查詢語句。
如果validationQuery為null,testOnBorrow、testOnReturn、
testWhileIdle都不會(huì)其作用。
testOnBorrowtrue申請(qǐng)連接時(shí)執(zhí)行validationQuery檢測(cè)連接是否有效,
做了這個(gè)配置會(huì)降低性能。
testOnReturnfalse歸還連接時(shí)執(zhí)行validationQuery檢測(cè)連接是否有效,
做了這個(gè)配置會(huì)降低性能
testWhileIdlefalse建議配置為true,不影響性能,并且保證安全性。
申請(qǐng)連接的時(shí)候檢測(cè),如果空閑時(shí)間大于
timeBetweenEvictionRunsMillis,
執(zhí)行validationQuery檢測(cè)連接是否有效。
timeBetweenEvictionRunsMillis?有兩個(gè)含義:
1) Destroy線程會(huì)檢測(cè)連接的間隔時(shí)間
?2) testWhileIdle的判斷依據(jù),詳細(xì)看testWhileIdle屬性的說明
numTestsPerEvictionRun?不再使用,一個(gè)DruidDataSource只支持一個(gè)EvictionRun
minEvictableIdleTimeMillis?Destory線程中如果檢測(cè)到當(dāng)前連接的最后活躍時(shí)間和當(dāng)前時(shí)間的差值大于
minEvictableIdleTimeMillis,則關(guān)閉當(dāng)前連接。
connectionInitSqls?物理連接初始化的時(shí)候執(zhí)行的sql
exceptionSorter根據(jù)dbType自動(dòng)識(shí)別當(dāng)數(shù)據(jù)庫(kù)拋出一些不可恢復(fù)的異常時(shí),拋棄連接
filters?屬性類型是字符串,通過別名的方式配置擴(kuò)展插件,
常用的插件有:
監(jiān)控統(tǒng)計(jì)用的filter:stat?
日志用的filter:log4j
?防御sql注入的filter:wall
proxyFilters?類型是List<com.alibaba.druid.filter.Filter>,
如果同時(shí)配置了filters和proxyFilters,
是組合關(guān)系,并非替換關(guān)系
removeAbandoned?對(duì)于建立時(shí)間超過removeAbandonedTimeout的連接強(qiáng)制關(guān)閉
removeAbandonedTimeout?指定連接建立多長(zhǎng)時(shí)間就需要被強(qiáng)制關(guān)閉
logAbandoned?指定發(fā)生removeabandoned的時(shí)候,是否記錄當(dāng)前線程的堆棧信息到日志中

2、druid監(jiān)控的配置與監(jiān)控訪問

?要使用druid監(jiān)控需要做好兩個(gè)配置:

1)、在配置數(shù)據(jù)源時(shí)需要配置filters并且賦值你需要使用的監(jiān)控項(xiàng)(stat、log4j、wall);

2)、需要在項(xiàng)目的web.xml中配置druid的自定義servlet(com.alibaba.druid.support.http.StatViewServlet),配置樣例如下代碼所示:

<servlet> <servlet-name>DruidStatView</servlet-name> <servlet-class>com.alibaba.druid.support.http.StatViewServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>DruidStatView</servlet-name> <url-pattern>/druid/*</url-pattern> </servlet-mapping>

3)、監(jiān)控系統(tǒng)的訪問:http://IP:PORT/projectName/druid/(http://localhost:8088/cd_management/druid/sql.html),監(jiān)控效果如下圖所示:

3、filters屬性的賦值邏輯

? ? ? ? 上面有提到filters的配置項(xiàng)有三個(gè),可以隨機(jī)組合也可以一起使用,也有提到filters是一個(gè)List集合,那我們來看看druid是如何賦值的,如下源碼所示,賦值時(shí)調(diào)用的setFilters(String filters)方法,最終是通過逗號(hào)分隔為數(shù)組然后遍歷調(diào)用FilterManager.loadFilter(this.filters, item.trim()),然后用反射機(jī)制生成相應(yīng)的對(duì)象并添加到Filter集合。

public void setFilters(String filters) throws SQLException {if (filters != null && filters.startsWith("!")) { filters = filters.substring(1); this.clearFilters(); } this.addFilters(filters); } public void addFilters(String filters) throws SQLException { if (filters == null || filters.length() == 0) { return; } String[] filterArray = filters.split("\\,"); for (String item : filterArray) { FilterManager.loadFilter(this.filters, item.trim()); } } public static void loadFilter(List<Filter> filters, String filterName) throws SQLException {if (filterName.length() == 0) { return; } String filterClassNames = getFilter(filterName); if (filterClassNames != null) { for (String filterClassName : filterClassNames.split(",")) { if (existsFilter(filters, filterClassName)) { continue; } Class<?> filterClass = Utils.loadClass(filterClassName); if (filterClass == null) { LOG.error("load filter error, filter not found : " + filterClassName); continue; } Filter filter; try { filter = (Filter) filterClass.newInstance(); } catch (ClassCastException e) { LOG.error("load filter error.", e); continue; } catch (InstantiationException e) { throw new SQLException("load managed jdbc driver event listener error. " + filterName, e); } catch (IllegalAccessException e) { throw new SQLException("load managed jdbc driver event listener error. " + filterName, e); } filters.add(filter); } return; } if (existsFilter(filters, filterName)) { return; } Class<?> filterClass = Utils.loadClass(filterName); if (filterClass == null) { LOG.error("load filter error, filter not found : " + filterName); return; } try { Filter filter = (Filter) filterClass.newInstance(); filters.add(filter); } catch (Exception e) { throw new SQLException("load managed jdbc driver event listener error. " + filterName, e); } }

4、druid監(jiān)控實(shí)現(xiàn)邏輯

? ? ?要說明druid監(jiān)控邏輯從如下三個(gè)方面切入分析:

? ? ? 1)、監(jiān)控的數(shù)據(jù)什么時(shí)候生成

? ? ? ?在這里我們拿Spring和druid整合案例來分析說明druid監(jiān)控?cái)?shù)據(jù)的生成,上面我們有提到要使用druid的監(jiān)控空能需要配置filters,并且filters可以配置多個(gè),這里druid關(guān)于這些filter的處理其實(shí)借鑒了過濾器鏈的原理,druid關(guān)于監(jiān)控?cái)?shù)據(jù)的收集處理邏輯是這樣的,我們從Spring的JdbcTemplate類開始看,如下源碼一,是一個(gè)查詢的處理,rs = ps.executeQuery()是PreparedStatement開始執(zhí)行sql從數(shù)據(jù)庫(kù)查詢數(shù)據(jù)的開始,這里我們給ps對(duì)象賦予的是DruidPooledPreparedStatement類對(duì)象,所以進(jìn)入DruidPooledPreparedStatement類我們來看它的具體實(shí)現(xiàn)。

? ? ? ? 源碼二是DruidPooledPreparedStatement類對(duì)executeQuery方法的實(shí)現(xiàn),這個(gè)方法里面最關(guān)鍵的是ResultSet rs = stmt.executeQuery()這句,stmt是PreparedStatementProxyImpl類的類對(duì)象。

? ? ? ? 源碼三是PreparedStatementProxyImpl類對(duì)executeQuery方法的實(shí)現(xiàn),這個(gè)方法實(shí)現(xiàn)中調(diào)用了父類的createChain()方法,源碼四為父類方法實(shí)現(xiàn),這個(gè)方法的返回值是一個(gè)過濾器鏈類FilterChainImpl類對(duì)象,FilterChainImpl類的

preparedStatement_executeQuery(PreparedStatementProxy statement)方法實(shí)現(xiàn)如源碼五。

public <T> T query(PreparedStatementCreator psc, final PreparedStatementSetter pss, final ResultSetExtractor<T> rse)throws DataAccessException { Assert.notNull(rse, "ResultSetExtractor must not be null"); logger.debug("Executing prepared SQL query"); return execute(psc, new PreparedStatementCallback<T>() { @Override public T doInPreparedStatement(PreparedStatement ps) throws SQLException { ResultSet rs = null; try { if (pss != null) { pss.setValues(ps); } rs = ps.executeQuery(); ResultSet rsToUse = rs; if (nativeJdbcExtractor != null) { rsToUse = nativeJdbcExtractor.getNativeResultSet(rs); } return rse.extractData(rsToUse); } finally { JdbcUtils.closeResultSet(rs); if (pss instanceof ParameterDisposer) { ((ParameterDisposer) pss).cleanupParameters(); } } } }); } public ResultSet executeQuery() throws SQLException {checkOpen();incrementExecuteCount();transactionRecord(sql);oracleSetRowPrefetch();conn.beforeExecute();try {ResultSet rs = stmt.executeQuery(); if (rs == null) { return null; } DruidPooledResultSet poolableResultSet = new DruidPooledResultSet(this, rs); addResultSetTrace(poolableResultSet); return poolableResultSet; } catch (Throwable t) { errorCheck(t); throw checkException(t); } finally { conn.afterExecute(); } } public ResultSet executeQuery() throws SQLException {firstResultSet = true;updateCount = null; lastExecuteSql = sql; lastExecuteType = StatementExecuteType.ExecuteQuery; lastExecuteStartNano = -1L; lastExecuteTimeNano = -1L; return createChain().preparedStatement_executeQuery(this); } public FilterChainImpl createChain() {FilterChainImpl chain = this.filterChain;if (chain == null) { chain = new FilterChainImpl(this.getConnectionProxy().getDirectDataSource()); } else { this.filterChain = null; } return chain; } @Overridepublic ResultSetProxy preparedStatement_executeQuery(PreparedStatementProxy statement) throws SQLException {if (this.pos < filterSize) { return nextFilter().preparedStatement_executeQuery(this, statement); } ResultSet resultSet = statement.getRawObject().executeQuery(); if (resultSet == null) { return null; } return new ResultSetProxyImpl(statement, resultSet, dataSource.createResultSetId(), statement.getLastExecuteSql()); }

? ? ? ??看了如上源碼我們會(huì)發(fā)現(xiàn)FilterChainImpl類的preparedStatement_executeQuery方法執(zhí)行的時(shí)候會(huì)先執(zhí)行過濾器類的此方法,所以我們看看過濾器類做了什么,這里我們拿SQL監(jiān)控的過濾器類(FilterEventAdapter)來分析,如下源碼是此類的方法實(shí)現(xiàn)。我看可以看到此方法先調(diào)用了statementExecuteQueryBefore(statement, statement.getSql())方法,然后調(diào)用了下一個(gè)過濾器類的查詢方法,在方法正常執(zhí)行以后又調(diào)用了statementExecuteQueryAfter(statement, statement.getSql(), resultSet)方法,在方法執(zhí)行異常的時(shí)候調(diào)用了statement_executeErrorAfter(statement, statement.getSql(), error),這些方法的作用就是保存SQL執(zhí)行中的監(jiān)控?cái)?shù)據(jù)。說到這里從流程上就說明了druid監(jiān)控?cái)?shù)據(jù)的來源。

public ResultSetProxy preparedStatement_executeQuery(FilterChain chain, PreparedStatementProxy statement)throws SQLException {try { statementExecuteQueryBefore(statement, statement.getSql()); ResultSetProxy resultSet = chain.preparedStatement_executeQuery(statement); if (resultSet != null) { statementExecuteQueryAfter(statement, statement.getSql(), resultSet); resultSetOpenAfter(resultSet); } return resultSet; } catch (SQLException error) { statement_executeErrorAfter(statement, statement.getSql(), error); throw error; } catch (RuntimeException error) { statement_executeErrorAfter(statement, statement.getSql(), error); throw error; } catch (Error error) { statement_executeErrorAfter(statement, statement.getSql(), error); throw error; } }

? ? ? 2)、監(jiān)控的數(shù)據(jù)保存到哪里

? ? ?這里我們簡(jiǎn)單說明,數(shù)據(jù)是保存到DruidDataSource類的dataSourceStat對(duì)象中。

? ? ? 3)、監(jiān)控的請(qǐng)求如何處理的

? ? ? ? ? ? ? 要使用druid的監(jiān)控功能需要配置com.alibaba.druid.support.http.StatViewServlet,這是一個(gè)繼承自HttpServlet的servlet,用來處理訪問druid監(jiān)控的請(qǐng)求,具體處理流程如下:

? ? ? ? ?

5、如何去除監(jiān)控頁面的廣告

? ? ? ?1)?使用過druid的同仁應(yīng)該都了解,druid的監(jiān)控頁面加載以后,footer頁是有阿里的廣告的如下圖所示,如果是一個(gè)商業(yè)項(xiàng)目這個(gè)是很不雅也是不允許的,那么我們來看看如何去除廣告。

?

? ? ? ?

? ? ? ?2)要去除這個(gè)廣告需要修改druid.jar的源碼文件,具體方法是,用winRAR打開jar包,在druid-1.1.6.jar\support\http\resources\js\common.js路徑下找到文件,修改common.js中如下圖所示的代碼,刪除buildFooter函數(shù)中的代碼即可:

buildFooter : function() {var html ='<footer class="footer">'+' <div class="container">'+'<a href="https://render.alipay.com/p/s/taobaonpm_click/druid_banner_click" target="new"><img src="https://render.alipay.com/p/s/taobaonpm_click/druid_banner"></a><br/>' +' powered by <a href="https://github.com/alibaba/" target="_blank">AlibabaTech</a> & <a href="http://www.sandzhang.com/" target="_blank">sandzhang</a> & <a href="http://melin.iteye.com/" target="_blank">melin</a> & <a href="https://github.com/shrekwang" target="_blank">shrek.wang</a>'+' </div>'+' </footer>';$(document.body).append(html);},

轉(zhuǎn)載于:https://www.cnblogs.com/gu-bin/p/11188917.html

創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)

總結(jié)

以上是生活随笔為你收集整理的阿里云sql监控配置-druid的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。