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

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

 

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

           1. 服務器自己的監控。(好比:linux服務器的CPU,內存,磁盤IO等監控)ios

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

 

1. 服務器自己的監控spring

    說明:因爲Java開源生鮮電商平臺採用的是阿里雲的linux CentOS服務器,因爲阿里雲自己是有監控預警的,可是咱們不可能時刻去看,最好有集成本身的系統監控,sql

最終在各類系統對比的過程當中,選擇了netdata這個工具,固然有一些軟件好比:zabbix,negios等等都是能夠的,可是咱們服務器壓力不算大,最終採用了更加輕量級的解決方案。apache

相關的安裝與使用,你們自行百度處理,我這邊就不列舉出來了。服務器

如下是相關的實際運營截圖:架構

 

 

 

 

 

 

 2. 業務監控app

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

  1. Java內存
  2. JavaCPU使用狀況
  3.  用戶Session數量
  4. JDBC鏈接數
  5. http請求、sql請求、jsp頁面與業務接口方法(EJB三、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等等,甚至開發採用本身的監控系統也是能夠的。也是支持二次開發的。

相關文章
相關標籤/搜索