厲害!某生鮮電商平臺(tái)竟然是這樣設(shè)計(jì)監(jiān)控模塊的(已開(kāi)源)~
我們談到監(jiān)控,一般設(shè)計(jì)到兩個(gè)方面的內(nèi)容:
服務(wù)器本身的監(jiān)控。(比如:linux服務(wù)器的CPU,內(nèi)存,磁盤(pán)IO等監(jiān)控) 業(yè)務(wù)系統(tǒng)的監(jiān)控. ?(比如:業(yè)務(wù)系統(tǒng)性能的監(jiān)控,SQL語(yǔ)句的監(jiān)控,請(qǐng)求超時(shí) 的監(jiān)控,用戶輸入的監(jiān)控,整個(gè)請(qǐng)求過(guò)程時(shí)間的監(jiān)控,優(yōu)化等等) ?
服務(wù)器本身的監(jiān)控
說(shuō)明:由于Java開(kāi)源生鮮電商平臺(tái)采用的是阿里云的linux CentOS服務(wù)器,由于阿里云本身是有監(jiān)控預(yù)警的,但是我們不可能時(shí)刻去看,最好有集成自己的系統(tǒng)監(jiān)控,最終在各種系統(tǒng)對(duì)比的過(guò)程中,選擇了netdata這個(gè)工具,當(dāng)然有一些軟件比如:zabbix,negios等等都是可以的,但是我們服務(wù)器壓力不算大,最終采用了更加輕量級(jí)的解決方案。 相關(guān)的安裝與使用,大家自行百度處理,我這邊就不列舉出來(lái)了。 以下是相關(guān)的實(shí)際運(yùn)營(yíng)截圖: ?
?
?
業(yè)務(wù)監(jiān)控
說(shuō)明:任何一個(gè)業(yè)務(wù)系統(tǒng)都需要采用業(yè)務(wù)監(jiān)控,拋異常,有error日志,短信預(yù)警,推送等等
Java內(nèi)存
JavaCPU使用情況
?用戶Session數(shù)量
JDBC連接數(shù)
http請(qǐng)求、sql請(qǐng)求、jsp頁(yè)面與業(yè)務(wù)接口方法(EJB3、Spring、 Guice)的執(zhí)行數(shù)量,平均執(zhí)行時(shí)間,錯(cuò)誤百分比等
?
最終,業(yè)務(wù)代碼中采用了Spring AOP進(jìn)行日志攔截,把請(qǐng)求方法超過(guò)了1500秒的方法進(jìn)行了error日志的輸出:
?
業(yè)務(wù)代碼如下:
import org.apache.commons.lang.time.StopWatch;import org.aspectj.lang.JoinPoint;import org.aspectj.lang.ProceedingJoinPoint;import org.aspectj.lang.annotation.After;import org.aspectj.lang.annotation.AfterReturning;import org.aspectj.lang.annotation.AfterThrowing;import org.aspectj.lang.annotation.Around;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Before;import org.aspectj.lang.annotation.Pointcut;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.stereotype.Component;/*** 聲明一個(gè)切面,記錄每個(gè)Action的執(zhí)行時(shí)間*/public class LogAspect {private static final Logger logger=LoggerFactory.getLogger(LogAspect.class);/*** 切入點(diǎn):表示在哪個(gè)類的哪個(gè)方法進(jìn)行切入。配置有切入點(diǎn)表達(dá)式*/public void pointcutExpression() {logger.debug("配置切入點(diǎn)");}/*** 1 前置通知* @param joinPoint*/public void beforeMethod(JoinPoint joinPoint) {logger.debug("前置通知執(zhí)行了");}/*** 2 后置通知* 在方法執(zhí)行之后執(zhí)行的代碼. 無(wú)論該方法是否出現(xiàn)異常*/public void afterMethod(JoinPoint joinPoint) {logger.debug("后置通知執(zhí)行了,有異常也會(huì)執(zhí)行");}/*** 3 返回通知* 在方法法正常結(jié)束受執(zhí)行的代碼* 返回通知是可以訪問(wèn)到方法的返回值的!* @param joinPoint* @param returnValue*/public void afterRunningMethod(JoinPoint joinPoint, Object returnValue) {logger.debug("返回通知執(zhí)行,執(zhí)行結(jié)果:" + returnValue);}/*** 4 異常通知* 在目標(biāo)方法出現(xiàn)異常時(shí)會(huì)執(zhí)行的代碼.* 可以訪問(wèn)到異常對(duì)象; 且可以指定在出現(xiàn)特定異常時(shí)在執(zhí)行通知代碼* @param joinPoint* @param e*/public void afterThrowingMethod(JoinPoint joinPoint, Exception e){logger.debug("異常通知, 出現(xiàn)異常 " + e);}/*** 環(huán)繞通知需要攜帶 ProceedingJoinPoint 類型的參數(shù).* 環(huán)繞通知類似于動(dòng)態(tài)代理的全過(guò)程: ProceedingJoinPoint 類型的參數(shù)可以決定是否執(zhí)行目標(biāo)方法.* 且環(huán)繞通知必須有返回值, 返回值即為目標(biāo)方法的返回值*/public Object aroundMethod(ProceedingJoinPoint pjd){StopWatch clock = new StopWatch();//返回的結(jié)果Object result = null;//方法名稱String className=pjd.getTarget().getClass().getName();String methodName = pjd.getSignature().getName();try{// 計(jì)時(shí)開(kāi)始clock.start();//前置通知//執(zhí)行目標(biāo)方法result = pjd.proceed();//返回通知clock.stop();} catch (Throwable e){//異常通知e.printStackTrace();}//后置通知if(!methodName.equalsIgnoreCase("initBinder")){long constTime=clock.getTime();logger.info("["+className+"]"+"-" +"["+methodName+"]"+" 花費(fèi)時(shí)間:" +constTime+"ms");if(constTime>500){logger.error("["+className+"]"+"-" +"["+methodName+"]"+" 花費(fèi)時(shí)間過(guò)長(zhǎng),請(qǐng)檢查: " +constTime+"ms");}}return result;}}
?
javamelody
對(duì)于整個(gè)業(yè)務(wù)線的監(jiān)控,我們采用了另外一種開(kāi)源的監(jiān)控:javamelody。
相關(guān)的配置與處理如下:
POM文件中設(shè)置:
<dependency><groupId>net.bull.javamelodygroupId><artifactId>javamelody-coreartifactId><version>1.68.1version>dependency><dependency><groupId>org.jrobingroupId><artifactId>jrobinartifactId><version>1.5.9version>dependency>
?
web.xml文件中處理
<context-param><param-name>contextConfigLocationparam-name><param-value>classpath*:config/applicationContext.xmlclasspath*:net/bull/javamelody/monitoring-spring.xmlclasspath*:net/bull/javamelody/monitoring-spring-datasource.xmlclasspath*:net/bull/javamelody/monitoring-spring-aspectj.xmlparam-value>context-param>
<filter><filter-name>monitoringfilter-name><filter-class>net.bull.javamelody.MonitoringFilterfilter-class><async-supported>trueasync-supported><init-param><param-name>logEnabledparam-name><param-value>trueparam-value>init-param>filter><filter-mapping><filter-name>monitoringfilter-name><url-pattern>/*url-pattern>filter-mapping><listener><listener-class>net.bull.javamelody.SessionListenerlistener-class>listener>
?
最終運(yùn)營(yíng)效果如下:

?

?

?
總結(jié)
最終可以形成一套基于自己的監(jiān)控系統(tǒng),當(dāng)然還有類似的更加強(qiáng)大的監(jiān)控系統(tǒng),比如:連接池方面druid,系統(tǒng)方面zabbix,業(yè)務(wù)方面可以用cat等等,甚至開(kāi)發(fā)采用自己的監(jiān)控系統(tǒng)也是可以的。也是支持二次開(kāi)發(fā)的。
來(lái)源:https://www.cnblogs.com/jurendage/p/9070442.html
大家一起在評(píng)論區(qū)聊聊唄~



