一種通用的業務監控觸發方案設計

2023-05-16 12:00:46

一、背景

業務監控是指通過技術手段監控業務程式碼執行的最終結果或者狀態是否符合預期,實現業務監控主要分成兩步:一、在業務系統中選擇節點傳送訊息觸發業務監控;二、系統在接收到mq訊息或者定時任務排程時,根據訊息中或者任務中的業務資料查詢業務執行的結果或狀態並與業務預期的結果相對比。目前供銷系統的方案如下:

由業務系統傳送訊息觸發規則中心的校驗任務,校驗邏輯和報警規則通過規則中心的groovy指令碼程式碼實現,該方案的缺點如下:
1.業務監控程式碼摻雜在正常的業務程式碼中,業務監控的程式碼侵入性高;
2.業務監控訊息觸發程式碼可複用性極低,各個應用都要維護一套程式碼,後期若要增加或維護某個功能時成本大;
3.增加業務監控的開發工作量,開發人員需要開發和維護與業務監控功能無關的程式碼,如:訊息觸發降級功能、效能監控、非同步觸發等功能;
為解決上述問題,本文提出了一種通用的業務監控觸發方案。

二、方案介紹

  1. 通用mq訊息體:
public class BusinessCheckMessage {
    /**
     * 監控型別
     */
    private String businessType;
    /**
     * 業務監控需要的引數
     */
    private Object data;
    /**
     * 業務方
     */
    private String businessSource;
    /**
     * 當前所屬的topic
     */
    private String topic;
}

其中,
businessType用於區分業務監控的型別,如:終止合作、提單等;
data用於儲存和業務相關的關鍵資料,如訂單id、商家id等;
businessSource用於區分不同業務方的業務,如:萬商的提單、供銷的提單等;
topic用於隔離訊息,如:業務監控任務執行快的可以用主題A、執行慢的的可以用主題B等;

2.自定義註解 + 切面
以供銷系統業務監控為例,接近50%的場景是將方法體中的引數作為業務資料來觸發業務監控,針對此場景,本文采用註解+切面解耦業務監控程式碼和正常業務程式碼,降低業務監控程式碼對正常的業務程式碼的侵入,其中自定義註解負責獲取業務監控需要用到的方法入參中的相關資料,切面負責組裝通用mq資料模型並完成訊息的傳送。自定義註解定義如下:

public @interface BusinessCheckPoint {
    /**     
     * 業務監控型別     
     */    
   String businessType();    
   /**     
    * 業務方     
    */    
   String businessSource();    
   /**     
    * 要傳送的訊息的topic     
    */    
   String businessTopic();    
   /**     
    * 方法引數的第幾個引數作為訊息內容,從0開始     
   */    
   int dataIndex();    
   /**     
    * 在執行業務流程前傳送訊息     
    * 預設在業務流程執行後傳送訊息     
    */    
   boolean beforeOperate() default false;
}

其中,
businesstype用於獲取業務監控型別;
businessSource用於獲取業務方;
businessTopic用於獲取當前要傳送的訊息主體;
dataIndex用於獲取方法體引數中的資料,從0開始;
beforeOperate用於獲取訊息傳送的時間,在業務流程執行後傳送訊息還是業務流程執行前發訊息;

3.侵入式觸發業務監控
考慮到業務系統可能會在複雜場景下觸發業務監控,本文也提供了通用的解決方案,具體如何使用見下一章節的實戰介紹。

三、實戰介紹

1.引入依賴

<dependency>    
    <groupId>com.jd</groupId>    
    <artifactId>business.check</artifactId>   
    <version>1.0.0</version>
</dependency>

2.初始化切面

<bean id="businessCheckAspect" class="com.jd.gmall.monitor.aspect.BusinessCheckAspect"/>

3.Producer及執行緒池賦值

<bean id="businessCheckHandler" class="com.jd.gmall.monitor.service.impl.BusinessCheckHandlerImpl">    
    <property name="messageProducerMap">        
        <map>            
            <entry key="gx_bussiness_check" value-ref="businessCheckProducer" />        
        </map>    
    </property>    
    <property name="commonExecutor" ref="asyncTaskThreadPoolTaskExecutor"/>
</bean>

其中,
messageProducerMap型別為Map<String, Producer>,用於指定topic對應的Producer;
commonExecutor用於指定非同步傳送訊息時用到的執行緒池(建議自行建立執行緒池);

4.業務監控訊息傳送
場景一:
簡單場景下可使用自定義註解來傳送訊息,如下所示

業務監控型別 = "100"
訊息主題 = "gx_bussiness_check"
業務方 = "ws"
訊息體中的業務資料data = req

場景二:
複雜場景下,可在服務中注入sdk中的訊息傳送服務,如下所示

場景二與場景一傳送的訊息內容一致。

5.業務監控降級不傳送訊息
sdk中的類BusinessCheckHandlerImpl中定義了控制降級的方法:

public static void setBusinessCheckSwitch(boolean businessCheckSwitch) {            
    BusinessCheckHandlerImpl.businessCheckSwitch = businessCheckSwitch;
}

此處給出了通過ducc控制降級的方法:

@LafValue("business.check.switch")
public void setBusinessCheckSwitch(boolean switch) {   
  BusinessCheckHandlerImpl.setBusinessCheckSwitch(b);
}

switch:true,開啟訊息傳送;false,降級

作者:京東零售 胡飛

內容來源:京東雲開發者社群