厲害!某生鮮電商平臺竟然是這樣設(shè)計監(jiān)控模塊的(已開源)~
關(guān)注我們,設(shè)為星標(biāo),每天7:30不見不散,架構(gòu)路上與您共享? 回復(fù)"架構(gòu)師"獲取資源
我們談到監(jiān)控,一般設(shè)計到兩個方面的內(nèi)容:
服務(wù)器本身的監(jiān)控。(比如:linux服務(wù)器的CPU,內(nèi)存,磁盤IO等監(jiān)控)
業(yè)務(wù)系統(tǒng)的監(jiān)控. ?(比如:業(yè)務(wù)系統(tǒng)性能的監(jiān)控,SQL語句的監(jiān)控,請求超時 的監(jiān)控,用戶輸入的監(jiān)控,整個請求過程時間的監(jiān)控,優(yōu)化等等)
?
# 服務(wù)器本身的監(jiān)控
說明:由于Java開源生鮮電商平臺采用的是阿里云的linux CentOS服務(wù)器,由于阿里云本身是有監(jiān)控預(yù)警的,但是我們不可能時刻去看,最好有集成自己的系統(tǒng)監(jiān)控,最終在各種系統(tǒng)對比的過程中,選擇了netdata這個工具,當(dāng)然有一些軟件比如:zabbix,negios等等都是可以的,但是我們服務(wù)器壓力不算大,最終采用了更加輕量級的解決方案。
相關(guān)的安裝與使用,大家自行百度處理,我這邊就不列舉出來了。
以下是相關(guān)的實際運營截圖:
?

?
?
# 業(yè)務(wù)監(jiān)控
說明:任何一個業(yè)務(wù)系統(tǒng)都需要采用業(yè)務(wù)監(jiān)控,拋異常,有error日志,短信預(yù)警,推送等等
Java內(nèi)存
JavaCPU使用情況
?用戶Session數(shù)量
JDBC連接數(shù)
http請求、sql請求、jsp頁面與業(yè)務(wù)接口方法(EJB3、Spring、 Guice)的執(zhí)行數(shù)量,平均執(zhí)行時間,錯誤百分比等
?
最終,業(yè)務(wù)代碼中采用了Spring AOP進(jìn)行日志攔截,把請求方法超過了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;/*** 聲明一個切面,記錄每個Action的執(zhí)行時間*/public class LogAspect {private static final Logger logger=LoggerFactory.getLogger(LogAspect.class);/*** 切入點:表示在哪個類的哪個方法進(jìn)行切入。配置有切入點表達(dá)式*/public void pointcutExpression() {logger.debug("配置切入點");}/*** 1 前置通知* @param joinPoint*/public void beforeMethod(JoinPoint joinPoint) {logger.debug("前置通知執(zhí)行了");}/*** 2 后置通知* 在方法執(zhí)行之后執(zhí)行的代碼. 無論該方法是否出現(xiàn)異常*/public void afterMethod(JoinPoint joinPoint) {logger.debug("后置通知執(zhí)行了,有異常也會執(zhí)行");}/*** 3 返回通知* 在方法法正常結(jié)束受執(zhí)行的代碼* 返回通知是可以訪問到方法的返回值的!* @param joinPoint* @param returnValue*/public void afterRunningMethod(JoinPoint joinPoint, Object returnValue) {logger.debug("返回通知執(zhí)行,執(zhí)行結(jié)果:" + returnValue);}/*** 4 異常通知* 在目標(biāo)方法出現(xiàn)異常時會執(zhí)行的代碼.* 可以訪問到異常對象; 且可以指定在出現(xiàn)特定異常時在執(zhí)行通知代碼* @param joinPoint* @param e*/public void afterThrowingMethod(JoinPoint joinPoint, Exception e){logger.debug("異常通知, 出現(xiàn)異常 " + e);}/*** 環(huán)繞通知需要攜帶 ProceedingJoinPoint 類型的參數(shù).* 環(huán)繞通知類似于動態(tài)代理的全過程: 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{// 計時開始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+"]"+" 花費時間:" +constTime+"ms");if(constTime>500){logger.error("["+className+"]"+"-" +"["+methodName+"]"+" 花費時間過長,請檢查: " +constTime+"ms");}}return result;}}
補充說明:這個方法記錄那個類,那個方法執(zhí)行的時間多少,超過設(shè)置的閥值,那么就打印error日志,需要我們每天進(jìn)行查看與針對性的優(yōu)化。
?
# javamelody
對于整個業(yè)務(wù)線的監(jiān)控,我們采用了另外一種開源的監(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>
?
最終運營效果如下:

?

?

?
# 總結(jié)
最終可以形成一套基于自己的監(jiān)控系統(tǒng),當(dāng)然還有類似的更加強大的監(jiān)控系統(tǒng),比如:連接池方面druid,系統(tǒng)方面zabbix,業(yè)務(wù)方面可以用cat等等,甚至開發(fā)采用自己的監(jiān)控系統(tǒng)也是可以的。也是支持二次開發(fā)的。

到此文章就結(jié)束了。如果今天的文章對你在進(jìn)階架構(gòu)師的路上有新的啟發(fā)和進(jìn)步,歡迎轉(zhuǎn)發(fā)給更多人。歡迎加入架構(gòu)師社區(qū)技術(shù)交流群,眾多大咖帶你進(jìn)階架構(gòu)師,在后臺回復(fù)“加群”即可入群。
這些年小編給你分享過的干貨
《不花錢的IDEA 2020.3.1?最新激活教程,有效期到2099年!》
《Docker與CI持續(xù)集成/CD持續(xù)部署》

轉(zhuǎn)發(fā)在看就是最大的支持??

