1. 程式人生 > >16、生鮮電商平臺-監控模塊的設計與架構

16、生鮮電商平臺-監控模塊的設計與架構

stack 方法 tool param nature () contex new ima

說明:Java開源生鮮電商平臺-監控模塊的設計與架構,我們談到監控,一般設計到兩個方面的內容:

1. 服務器本身的監控。(比如:linux服務器的CPU,內存,磁盤IO等監控)

2. 業務系統的監控. (比如:業務系統性能的監控,SQL語句的監控,請求超時的監控,用戶輸入的監控,整個請求過程時間的監控,優化等等)

1. 服務器本身的監控

說明:由於Java開源生鮮電商平臺采用的是阿裏雲的linux CentOS服務器,由於阿裏雲本身是有監控預警的,但是我們不可能時刻去看,最好有集成自己的系統監控,

最終在各種系統對比的過程中,選擇了netdata這個工具,當然有一些軟件比如:zabbix,negios等等都是可以的,但是我們服務器壓力不算大,最終采用了更加輕量級的解決方案。

相關的安裝與使用,大家自行百度處理,我這邊就不列舉出來了。

以下是相關的實際運營截圖:

技術分享圖片

技術分享圖片

技術分享圖片

2. 業務監控

說明:任何一個業務系統都需要采用業務監控,拋異常,有error日誌,短信預警,推送等等

  1. Java內存
  2. JavaCPU使用情況
  3. 用戶Session數量
  4. JDBC連接數
  5. http請求、sql請求、jsp頁面與業務接口方法(EJB3、Spring、 Guice)的執行數量,平均執行時間,錯誤百分比等

最終,業務代碼中采用了Spring AOP進行日誌攔截,把請求方法超過了1500秒的方法進行了error日誌的輸出:

業務代碼如下:

技術分享圖片
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的執行時間
 */
@Aspect
@Component
public class LogAspect {
    
    private static final Logger logger=LoggerFactory.getLogger(LogAspect.class);
    
    /**
     * 切入點:表示在哪個類的哪個方法進行切入。配置有切入點表達式
     */
    @Pointcut("execution(* com.netcai.admin.controller.*.*.*(..))")
    public void pointcutExpression() {
        logger.debug("配置切入點");
    }
    
    /**
     * 1 前置通知
     * @param joinPoint
     */
    @Before("pointcutExpression()")
    public void beforeMethod(JoinPoint joinPoint) {
        logger.debug("前置通知執行了");
    }
    
    /**
     * 2 後置通知
     * 在方法執行之後執行的代碼. 無論該方法是否出現異常
     */
    @After("pointcutExpression()") 
    public void afterMethod(JoinPoint joinPoint) {
        logger.debug("後置通知執行了,有異常也會執行");
    }
    
    /**
     * 3 返回通知
     * 在方法法正常結束受執行的代碼
     * 返回通知是可以訪問到方法的返回值的!
     * @param joinPoint
     * @param returnValue
     */
    @AfterReturning(value = "pointcutExpression()", returning = "returnValue")
    public void afterRunningMethod(JoinPoint joinPoint, Object returnValue) {
        logger.debug("返回通知執行,執行結果:" + returnValue);
    }
    /**
     * 4 異常通知
     * 在目標方法出現異常時會執行的代碼.
     * 可以訪問到異常對象; 且可以指定在出現特定異常時在執行通知代碼
     * @param joinPoint
     * @param e
     */
    @AfterThrowing(value = "pointcutExpression()", throwing = "e")
    public void afterThrowingMethod(JoinPoint joinPoint, Exception e)
    {
        logger.debug("異常通知, 出現異常 " + e);
    }
    
    /**
     * 環繞通知需要攜帶 ProceedingJoinPoint 類型的參數. 
     * 環繞通知類似於動態代理的全過程: ProceedingJoinPoint 類型的參數可以決定是否執行目標方法.
     * 且環繞通知必須有返回值, 返回值即為目標方法的返回值
     */
    @Around("pointcutExpression()")
    public Object aroundMethod(ProceedingJoinPoint pjd)
    {
        StopWatch clock = new StopWatch();
        //返回的結果
        Object result = null;
        //方法名稱
        String className=pjd.getTarget().getClass().getName();
        
        String methodName = pjd.getSignature().getName();
        
        try 
        {
            // 計時開始
            clock.start(); 
            //前置通知
            //執行目標方法
            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;
    }
}
技術分享圖片

補充說明:這個方法記錄那個類,那個方法執行的時間多少,超過設置的閥值,那麽就打印error日誌,需要我們每天進行查看與針對性的優化。

3. 對於整個業務線的監控,我們采用了另外一種開源的監控:javamelody

相關的配置與處理如下:

POM文件中設置:

技術分享圖片
<!-- 系統監控 -->
        <dependency>
            <groupId>net.bull.javamelody</groupId>
            <artifactId>javamelody-core</artifactId>
            <version>1.68.1</version>
        </dependency>

        <dependency>
            <groupId>org.jrobin</groupId>
            <artifactId>jrobin</artifactId>
            <version>1.5.9</version>
        </dependency>
技術分享圖片

web.xml文件中處理

技術分享圖片
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            classpath*:config/applicationContext.xml
            classpath*:net/bull/javamelody/monitoring-spring.xml
            classpath*:net/bull/javamelody/monitoring-spring-datasource.xml
            classpath*:net/bull/javamelody/monitoring-spring-aspectj.xml
        </param-value>
    </context-param>
技術分享圖片

技術分享圖片
    <!--javamelody -->
    <filter>
        <filter-name>monitoring</filter-name>
        <filter-class>net.bull.javamelody.MonitoringFilter</filter-class>
        <async-supported>true</async-supported>
        <init-param>
            <param-name>logEnabled</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>

    <filter-mapping>
        <filter-name>monitoring</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <listener>
        <listener-class>net.bull.javamelody.SessionListener</listener-class>
    </listener>
技術分享圖片

最終運營效果如下:

技術分享圖片

技術分享圖片

技術分享圖片

技術分享圖片

總結:最終可以形成一套基於自己的監控系統,當然還有類似的更加強大的監控系統,比如:連接池方面druid,系統方面zabbix,業務方面可以用cat等等,甚至開發采用自己的監控系統也是可以的。也是支持二次開發的。

轉載自-- https://www.cnblogs.com/jurendage/p/9070442.html

16、生鮮電商平臺-監控模塊的設計與架構