阿里云sql监控配置-druid

  今天我们说说数据源和数据库连接池,熟悉java开发的同仁应该都了解C3PO,在这里不做过多的赘述了,今天我们说的是阿里DRUID,druid是后起之秀,因为它的优秀很快占领了使用市场,下边我们一起来看看druid数据源的配置以及druid监控的配置和监控的实现逻辑。

1、druid数据源配置

       下面是druid的数据源配置项,这些配置项都是com.alibaba.druid.pool.DruidDataSource类和其基类com.alibaba.druid.pool.DruidAbstractDataSource的public final属性,这些配置型和C3P0的数据源配置项基本一样,有个别的是明白发生了变化但是参数所表示的意思不变,还有一些参数是druid自己扩展的,其中filters属性就是杰出代表,次属性是DruidAbstractDataSource类的,是一个List<Filter>的集合,此属性提供了三个可选值:监控统计用的stat、日志用的log4j、 防御sql注入的wall,这三个值可以单独使用也可以两两组合或者一起使用,组合使用的时候不同值之间用逗号隔开。有人可能会有疑问了,不是一个List集合吗,为什么这里却是用逗号分隔的,那是因为druid在赋值的时候有特殊处理,至于是如何处理的在下边我们会说到。

配置缺省值说明
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。详细看这里:
https://github.com/alibaba/druid/wiki/%E4%BD%BF%E7%94%A8ConfigFilter
driverClassName根据url自动识别这一项可配可不配,如果不配置druid会根据url自动识别dbType,
然后选择相应的driverClassName
initialSize0初始化时建立物理连接的个数。初始化发生在显示调用init方法,
或者第一次getConnection时
maxActive8最大连接池数量
maxIdle8已经不再使用,配置了也没效果
minIdle 最小连接池数量
maxWait 获取连接时最大等待时间,单位毫秒。配置了maxWait之后,
缺省启用公平锁,并发效率会有所下降,
如果需要可以通过配置useUnfairLock属性为true使用非公平锁。
poolPreparedStatementsfalse是否缓存preparedStatement,也就是PSCache。
PSCache对支持游标的数据库性能提升巨大,比如说oracle。
在mysql5.5以下的版本中没有PSCache功能,建议关闭掉。
5.5及以上版本有PSCache,建议开启。
maxOpenPreparedStatements-1要启用PSCache,必须配置大于0,当大于0时,
poolPreparedStatements自动触发修改为true。
在Druid中,不会存在Oracle下PSCache占用内存过多的问题,
可以把这个数值配置大一些,比如说100
validationQuery 用来检测连接是否有效的sql,要求是一个查询语句。
如果validationQuery为null,testOnBorrow、testOnReturn、
testWhileIdle都不会其作用。
testOnBorrowtrue申请连接时执行validationQuery检测连接是否有效,
做了这个配置会降低性能。
testOnReturnfalse归还连接时执行validationQuery检测连接是否有效,
做了这个配置会降低性能
testWhileIdlefalse建议配置为true,不影响性能,并且保证安全性。
申请连接的时候检测,如果空闲时间大于
timeBetweenEvictionRunsMillis,
执行validationQuery检测连接是否有效。
timeBetweenEvictionRunsMillis 有两个含义:
1) Destroy线程会检测连接的间隔时间
 2) testWhileIdle的判断依据,详细看testWhileIdle属性的说明
numTestsPerEvictionRun 不再使用,一个DruidDataSource只支持一个EvictionRun
minEvictableIdleTimeMillis Destory线程中如果检测到当前连接的最后活跃时间和当前时间的差值大于
minEvictableIdleTimeMillis,则关闭当前连接。
connectionInitSqls 物理连接初始化的时候执行的sql
exceptionSorter根据dbType自动识别当数据库抛出一些不可恢复的异常时,抛弃连接
filters 属性类型是字符串,通过别名的方式配置扩展插件,
常用的插件有:
监控统计用的filter:stat 
日志用的filter:log4j
 防御sql注入的filter:wall
proxyFilters 类型是List<com.alibaba.druid.filter.Filter>,
如果同时配置了filters和proxyFilters,
是组合关系,并非替换关系
removeAbandoned 对于建立时间超过removeAbandonedTimeout的连接强制关闭
removeAbandonedTimeout 指定连接建立多长时间就需要被强制关闭
logAbandoned 指定发生removeabandoned的时候,是否记录当前线程的堆栈信息到日志中

2、druid监控的配置与监控访问

 要使用druid监控需要做好两个配置:

1)、在配置数据源时需要配置filters并且赋值你需要使用的监控项(stat、log4j、wall);

2)、需要在项目的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)、监控系统的访问:http://IP:PORT/projectName/druid/(http://localhost:8088/cd_management/druid/sql.html),监控效果如下图所示:

3、filters属性的赋值逻辑

        上面有提到filters的配置项有三个,可以随机组合也可以一起使用,也有提到filters是一个List集合,那我们来看看druid是如何赋值的,如下源码所示,赋值时调用的setFilters(String filters)方法,最终是通过逗号分隔为数组然后遍历调用FilterManager.loadFilter(this.filters, item.trim()),然后用反射机制生成相应的对象并添加到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监控实现逻辑

     要说明druid监控逻辑从如下三个方面切入分析:

      1)、监控的数据什么时候生成

       在这里我们拿Spring和druid整合案例来分析说明druid监控数据的生成,上面我们有提到要使用druid的监控空能需要配置filters,并且filters可以配置多个,这里druid关于这些filter的处理其实借鉴了过滤器链的原理,druid关于监控数据的收集处理逻辑是这样的,我们从Spring的JdbcTemplate类开始看,如下源码一,是一个查询的处理,rs = ps.executeQuery()是PreparedStatement开始执行sql从数据库查询数据的开始,这里我们给ps对象赋予的是DruidPooledPreparedStatement类对象,所以进入DruidPooledPreparedStatement类我们来看它的具体实现。

        源码二是DruidPooledPreparedStatement类对executeQuery方法的实现,这个方法里面最关键的是ResultSet rs = stmt.executeQuery()这句,stmt是PreparedStatementProxyImpl类的类对象。

        源码三是PreparedStatementProxyImpl类对executeQuery方法的实现,这个方法实现中调用了父类的createChain()方法,源码四为父类方法实现,这个方法的返回值是一个过滤器链类FilterChainImpl类对象,FilterChainImpl类的

preparedStatement_executeQuery(PreparedStatementProxy statement)方法实现如源码五。

复制代码
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()); }
复制代码

        看了如上源码我们会发现FilterChainImpl类的preparedStatement_executeQuery方法执行的时候会先执行过滤器类的此方法,所以我们看看过滤器类做了什么,这里我们拿SQL监控的过滤器类(FilterEventAdapter)来分析,如下源码是此类的方法实现。我看可以看到此方法先调用了statementExecuteQueryBefore(statement, statement.getSql())方法,然后调用了下一个过滤器类的查询方法,在方法正常执行以后又调用了statementExecuteQueryAfter(statement, statement.getSql(), resultSet)方法,在方法执行异常的时候调用了statement_executeErrorAfter(statement, statement.getSql(), error),这些方法的作用就是保存SQL执行中的监控数据。说到这里从流程上就说明了druid监控数据的来源。

复制代码
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)、监控的数据保存到哪里

     这里我们简单说明,数据是保存到DruidDataSource类的dataSourceStat对象中。

      3)、监控的请求如何处理的

              要使用druid的监控功能需要配置com.alibaba.druid.support.http.StatViewServlet,这是一个继承自HttpServlet的servlet,用来处理访问druid监控的请求,具体处理流程如下:

         

5、如何去除监控页面的广告

       1) 使用过druid的同仁应该都了解,druid的监控页面加载以后,footer页是有阿里的广告的如下图所示,如果是一个商业项目这个是很不雅也是不允许的,那么我们来看看如何去除广告。

 

       

       2)要去除这个广告需要修改druid.jar的源码文件,具体方法是,用winRAR打开jar包,在druid-1.1.6.jar\support\http\resources\js\common.js路径下找到文件,修改common.js中如下图所示的代码,删除buildFooter函数中的代码即可:

复制代码
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);},
复制代码

转载于:https://www.cnblogs.com/gu-bin/p/11188917.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/386395.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

最全面试考点与面试技巧,真香!

写在前面 身边有不少去大厂面试的朋友&#xff0c;其中小金面试字节跳动的经历很有意义&#xff0c;在这里分享给大家。小金是末流211计算机专业大三本科生&#xff0c;前几天面试了字节跳动的广州Android开发实习生。下面是他的面试经历&#xff0c;还有一些他自己的经验。 …

最强Android教程!2021年Android面经分享,大厂面经合集

前言 找工作还是需要大家不要紧张&#xff0c;有我们干这一行的接触人本来就不多 难免看到面试官会紧张&#xff0c;主要是因为怕面试官问的问题到不上来&#xff0c;那时候不要着急 &#xff0c;答不上了的千万不然胡扯一些&#xff0c;直接就给面试官说这块我还没接触到&…

最强整理!字节跳动历年Android中高级面试题全收录!附超全教程文档

开头 让我们一起来看看&#xff0c;字节跳动的第三面&#xff0c;面试官都问了什么&#xff1f;&#xff08;第一二面的题目及答案已整理&#xff0c;需要的可以在文末领取&#xff09; 从七月中旬开始&#xff0c;我前前后后差不多一共投递了八十份简历&#xff0c;到目前为…

最新BAT大厂面试者整理的Android面试题目模板,分享PDF高清版

前言 从毕业到现在面试也就那么几家公司&#xff0c;单前几次都比较顺利&#xff0c;在面到第三家时都给到了我offer&#xff01;前面两次找工作&#xff0c;没考虑到以后需要什么&#xff0c;自己的对未来的规划是什么&#xff0c;只要有份工作&#xff0c;工资符合自己的要求…

最新BAT大厂面试者整理的Android面试题目模板,成功入职字节跳动

前言 **一年中第一段跳槽高潮就要来了&#xff0c;**看到同事一个个离职&#xff0c;又有一部分同事已经找到满意的工作&#xff0c;于是自己也盲目的开始面试起来&#xff08;期间也没有准备充分&#xff09;&#xff0c;日夜奔走&#xff0c;简历投了很多家公司&#xff0c;…

算法题+JVM+自定义View,终局之战

关于面试题 打个比方&#xff0c;如果把找工作理解成考大学&#xff0c;面试就是高考&#xff0c;市面上的“真题”就是模拟试卷。我们会很容易倾向于在面试前寻找对应公司的面试“真题”&#xff0c;重点准备&#xff0c;期待“押题”成功。但实际上&#xff0c;即使面试同一…

系统学Android从零开始,搞懂这些直接来阿里入职

开头 很多人说Android开发前景越来越差了 我觉得这个回答是片面的 首先Android应用开发前景差是在最近两年出现的&#xff0c;也就是从2018开始&#xff0c;从那时起移动端的程序员已经慢慢出现供大于求的局面&#xff0c;本人作为移动端开发&#xff0c;深知这一点。 然而也…

Bginfo软件在域的部署和应用

在企业的IT管理中&#xff0c;很多用户都不知道怎么去查看自己计算机的IP地址、登陆帐户。而对于网络管理人员来说&#xff0c;他们可能需要知道用户在域中登录的一些信息&#xff0c;如那些用户登录过&#xff0c;在什么时间登录&#xff0c;IP和MAC地址是多少&#xff1b;需要…

系统学Android从零开始,详细的Android学习指南

Android面试相关整理 最近有一点找工作的打算&#xff0c;想补下面试题。但是发现网上面试相关的文章特别多&#xff0c;不知道从何看起&#xff0c;所以简单的总结了一下我有印象的一些&#xff0c;方便自己随时查看&#xff0c;本想带下个人评价&#xff0c;但有些没有仔细看…

WPF中解决内存泄露的几点提示与解决方法

一直以来用WPF做一个项目&#xff0c;但是开发中途发现内存开销太大&#xff0c;用ANTS Memory Profiler分析时&#xff0c;发现在来回点几次载入页面的操作中&#xff0c;使得非托管内存部分开销从起始的43.59M一直到150M&#xff0c;而托管部分的开销也一直持高不下&#xff…

组件化与插件化的差别在哪里?内含福利

前言 今年上半年其实就已经有了换工作的想法,奈何疫情原因和岗位缩减&#xff0c;加之信心不足&#xff0c;到六月底投递了百度的Android岗位,本以为像我这种非211、985没工作经验的渣渣只能被直接pass,结果却意外的收到了电话,真是受宠若惊.经过电面,技术三面,然后就是等通知…

MapXtreme2004 vs2005的官方回答

自从ms公开vs belta测试版后&#xff0c;很多人员一直在试用。而正式版已发布&#xff0c;很多大型项目已经迁移到vs2005下来了&#xff0c;我象很多人一样&#xff0c;关心MapXtreme2004与vs2005的兼容性。我也做了一些试验&#xff0c;基本上&#xff0c;所有的大型的.net组件…

经典Android开发教程!这些新技术你们都知道吗?年薪超过80万!

概述 想了很久怎么样可以让文章的标题不那么悲观&#xff0c;但是各种文案都在我脑海里面不断的被否定&#xff0c;要么是不那么抓眼球&#xff0c;要么是立意不匹配。最后想了想&#xff0c;这个标题是真的符合我最近的感悟。 希望看过文章&#xff0c;能有同感的朋友也能多…

给Android程序员的一些面试建议,帮你突破瓶颈

开头 这里是一些个人开发者接私活和自己做软件加广告的一些科普知识。可是做软件&#xff0c;需要服务器&#xff0c;需要后台&#xff0c;对于一些小的开发者&#xff0c;想赚点广告费而又不想做后台使用服务器的人来说&#xff0c;网上提供了一些免费的接口&#xff0c;可以…

给Android程序员的一些面试建议,附带学习经验

我&#xff0c;来自大山。 我&#xff0c;不甘平凡。 笔者80后&#xff0c;出生在江西一个偏远的山村。虽然出生时已经不是那个温饱都是问题的年代&#xff0c;但是也谈不上有个幸福的童年。家里很穷。幼儿园并没有读&#xff0c;因为家里觉得花那个钱没有必要&#xff0c;小学…

HBase查询速度慢原因排查

问题&#xff1a;通过HBase访问服务在HBase中查询 ASSET_NORMAL 表速度很慢 如下&#xff0c;查询一条数据需要2.970s时间&#xff1a; 如下&#xff0c;统计总条数需要14.675s时间&#xff1a; HBase访问服务部署了3个节点&#xff1a; HBase部署了3个节点&#xff1a; 表 ASS…

网易云的朋友给我这份339页的Android面经,持续更新中

程序员职业生涯真的很短吗? 不短&#xff0c;我就是明证&#xff01;我今年44岁&#xff0c;世界500强公司&#xff0c;编程20年&#xff0c;软件技术专家&#xff0c;一直都在编程一线&#xff0c;从来离开过。技术上&#xff0c;我深入的使用过Java、.net、Js等等。也许吧&…

PIE SDK主成分变换

1.算法功能简介 主成分变换(Principal Component Analysis&#xff0c;PCA)又称K-L&#xff08;Karhunen-Loeve&#xff09;变换或霍特林&#xff08;Hotelling&#xff09;变换&#xff0c;是基于变量之间的相关关系&#xff0c;在尽量不丢失信息前提下的一种线性变换的方法&a…

网络优化软件apk,金九银十怎么从中小企业挤进一线大厂?我先收藏为敬

前言 从毕业到现在面试也就那么几家公司&#xff0c;单前几次都比较顺利&#xff0c;在面到第三家时都给到了我offer&#xff01;前面两次找工作&#xff0c;没考虑到以后需要什么&#xff0c;自己的对未来的规划是什么&#xff0c;只要有份工作&#xff0c;工资符合自己的要求…

渣本毕业两年经验,大厂面试题汇总

开头 最近有个老铁&#xff0c;告诉我说&#xff0c;上班一个月&#xff0c;后悔当初着急入职现在公司了。他之前在美图做手机研发&#xff0c;今年美图那边今年也有一波组织优化调整&#xff0c;他是其中一个&#xff0c;在协商离职后&#xff0c;当时捉急找工作上班&#xf…