閏四洋 胡昌平 卞德志 左剛
摘要:微服務(wù)的出現(xiàn)大大降低了Web系統(tǒng)的耦合度,但隨著微服務(wù)的規(guī)模不斷增大,其運(yùn)行日志的數(shù)量不斷增多、內(nèi)容也更加雜亂,給用戶查看日志數(shù)據(jù)帶來困難,因此對微服務(wù)的運(yùn)行日志進(jìn)行處理具有重要意義。文章介紹的微服務(wù)日志系統(tǒng),采用SpringBoot開發(fā),利用非關(guān)系性數(shù)據(jù)庫MongoDB作為日志系統(tǒng)的存儲庫,提供日志管理的相關(guān)接口,從而極大地提高了對日志數(shù)據(jù)管理和應(yīng)用的效率。
關(guān)鍵詞:微服務(wù);日志數(shù)據(jù);查詢;SpringBoot;處理;MongoDB
中圖分類號:TP311 文獻(xiàn)標(biāo)識碼:A 文章編號:1006-8228(2020)08-69-04
0 引言
當(dāng)前微眼務(wù)的治理框架大多采用SpringCloud,如果把基于微服務(wù)架構(gòu)的系統(tǒng)比作是一棟大樓,鋼筋混凝土結(jié)構(gòu)可以說是SpringCloud,那么最基礎(chǔ)的磚頭瓦塊就是SpringBoot。所謂的獨(dú)立的微服務(wù)是用SpringBoot開發(fā)的,作為一套全新的框架,繼承了Spring所有的功能并青出于藍(lán);SpringBoot的約定大于配置的核心思想,默認(rèn)幫用戶做了許多基礎(chǔ)設(shè)置,很多SpringBoot應(yīng)用只需要很少的Spring配置就可以正常運(yùn)行。同時,SpringBoot也提供了很多應(yīng)用集成包,支持絕大多數(shù)開源軟件,讓用戶可以以很低的成本去集成其他主流開源軟件[2]。
MongoDB是一個基于文檔模型的,支持索引、復(fù)制、事務(wù)的數(shù)據(jù)庫,是目前比較流行的非關(guān)系型數(shù)據(jù)庫[1]。微服務(wù)在運(yùn)行過程中,由于用戶訪問、計劃任務(wù)等操作會產(chǎn)生大量日志,而MongoDB數(shù)據(jù)庫系統(tǒng)就非常適合管理這些日志。首先,它易擴(kuò)展,靈活的文檔數(shù)據(jù)模型可以快捷直觀地處理數(shù)據(jù);第二,它和關(guān)系型數(shù)據(jù)庫有共同點(diǎn),具有豐富的數(shù)據(jù)查詢語言,其主要的聚合函數(shù)操作如表l所示;第三,它以文件形式把數(shù)據(jù)加載在內(nèi)存中,假如服務(wù)器的內(nèi)存資源足夠豐富,其插入和查詢效率要高于關(guān)系型數(shù)據(jù)庫[1]。
由于SpringBoot本身就封裝了MongoDB的套件,因此使用SpringBoot整合MongoDB做日志系統(tǒng)的開發(fā),是相得益彰的。
1 實(shí)現(xiàn)原理
本系統(tǒng)共分為兩個模塊。一個是日志記錄模塊,是一個單獨(dú)的依賴組件,需要被微服務(wù)所引用,使用Spring的AOP及SpringBoot等技術(shù)開發(fā),用于在微服務(wù)運(yùn)行過程中,對Http請求的內(nèi)容以及產(chǎn)生的異常等信息進(jìn)行捕獲處理,并按照微服務(wù)名稱以及日期進(jìn)行分類記錄到MongoDB數(shù)據(jù)庫。另一個模塊是日志管理模塊,是用SpringBoot開發(fā)的獨(dú)立的微服務(wù),利用了MongoDB的相關(guān)特性,可提供日志數(shù)據(jù)的靈活查詢、統(tǒng)計分析、批量刪除、批量導(dǎo)出等功能接口供其他微服務(wù)調(diào)用[4]。
2 具體實(shí)現(xiàn)
2.1 功能模塊
2.1.1 日志記錄
日志記錄模塊在微服務(wù)內(nèi)運(yùn)行,主要負(fù)責(zé)在微服務(wù)運(yùn)行過程中,將其產(chǎn)生的運(yùn)行日志異步地記錄到MongoDB數(shù)據(jù)庫,其功能設(shè)計如圖l所示。
2.1.2 日志管理
日志管理模塊主要負(fù)責(zé)日志數(shù)據(jù)的管理,可對數(shù)據(jù)進(jìn)行查詢、統(tǒng)計分析、批量刪除和導(dǎo)出,其功能設(shè)計如圖2所示。
2.2 軟件接口
2.2.1 寫日志接口
異步接口,其功能是將微服務(wù)產(chǎn)生的運(yùn)行日志按照微服務(wù)名稱、產(chǎn)生日期進(jìn)行分類,并記錄到MongoDB數(shù)據(jù)庫。
/**
* @param info日志信息
* @param level日志級別1 inf0 2 warn 3 error
*/|
public void saveLog(String info, int level);
2.2.2 查詢?nèi)罩窘涌?/p>
提供日志數(shù)據(jù)的查詢功能,根據(jù)微服務(wù)名稱、日志產(chǎn)生日期篩選到指定的日志數(shù)據(jù),并可根據(jù)具體的時間以及類型做進(jìn)一步篩選,同時也可以根據(jù)日志內(nèi)容做模糊查詢[3,5,6]。
/** @param appName微服務(wù)名稱* @param date檢索日期* @param time檢索時間* @param timeType檢索時間類型* @param searchStr檢索字符串*/ public ListgetAppLogs(String appName,
LocaIDate date, LocaITime time, int timeType,
String searchStr);
2.2.3 統(tǒng)計分析接口
可根據(jù)微服務(wù)名稱、分析類型、檢索字符串等條件,同時利用MongoDB的聚合函數(shù)等,對日志數(shù)據(jù)進(jìn)行統(tǒng)計分析,例如按小時、天、月統(tǒng)計某個微服務(wù)的日志數(shù)量。
/**
* @param appName微服務(wù)名稱
* @param type分析類型
* @param searchStr檢索字符串
*/
public Object analyseAppLogs(String appName,
int type, String searchStr);
2.2.4批量刪除日志接口
根據(jù)微服務(wù)名稱及指定的日期范圍對日志進(jìn)行批量刪除。
/**
* @param appName微服務(wù)名稱
* @param startDate刪除范圍的起始日期
* @param endDate刪除范圍的截止日期
*/
public void deleteAppLogs(String appName,
LocaIDate startDate, LocaIDate endDate);
2.2.5 批量導(dǎo)出日志接口
根據(jù)微服務(wù)名稱及指定的時間范圍對日志進(jìn)行批量導(dǎo)出。
/**
* @param appName微服務(wù)名稱
* @param startDate導(dǎo)出范圍的起始時間
* @param endDate導(dǎo)出范圍的截止時間
*/
public void exportAppLogs(String appName, LocaIDate
startDate, LocaIDate endDate, int type);
2.3 日志表設(shè)計
為了方便日志系統(tǒng)將來拓展,特增加幾個備用屬性,表定義見表2。
3 項(xiàng)目代碼
3.1 日志記錄接口
在業(yè)務(wù)系統(tǒng)的實(shí)際開發(fā)中,需要對日志進(jìn)行不同級別的記錄,這里提供四個級別的接口,來分別記錄不同級別的日志。
public interfaceLogger(
/★調(diào)試級別,不記錄/*,
void debug(String info);
/* info級別*/,
void info(String info);
/* warn級別 */,
void warn(String info);
/* error級別*/
void error(String info);
)
3.2 請求跟蹤
對于微服務(wù)接收的Http請求,可以利用AOP切面技術(shù)來處理。首先可以利用Pointcut注解來對所有的web接口進(jìn)行匹配,這樣就可以在每一個請求的流轉(zhuǎn)過程中進(jìn)行內(nèi)容的處理并記錄日志[4]。
/*切點(diǎn),匹配包路徑最后為controller的所有包下面類的所有方法+,
@Pointcut(”execution(++..controIIer*.*(..))”)
public void printPointCutController()O
/*切點(diǎn),匹配所有帶有RequestMapping注解的方法*/,
@Pointcut(”@annotation(org.springframework.web.bind
.annotation.RequestMapping)“)
public void printPointCutRequestMapping()O
/* AOP切點(diǎn)交集,針對所有的web接口 */,
@Pointcut(”printPointCutController0&&
printPointCutRequestMapping0”)
public void printPointCut()0
/*調(diào)用web接口之前調(diào)用此方法,可以對請求的路徑、地址、
內(nèi)容等進(jìn)行記錄*/,
@Before(”printPointCut()”)
public void doBefore(JoinPoint joinPoint){…)
/*調(diào)用web接口之后調(diào)用此方法,可以對請求的返回結(jié)果等進(jìn)行記錄*,
@AfterReturning(returning=”ret”, pointcut=”printPointCut0”)
public void doAfterReturning(Object ret){…}
/*調(diào)用web接口的過程中調(diào)用此方法,可以對請求的響應(yīng)時
間等進(jìn)行記錄+,
@Around(”printPointCut()”)
public Object doAround(ProceedingjoinPoint pjp){…}
3.3 異常捕獲
在工具類上使用RestControllerAdvice注解可捕獲運(yùn)行過程中產(chǎn)生的異常,而在方法上使用ExceptionHandler注解會匹配異常。一旦捕獲異常,此工具類會按照方法定義的前后順序去匹配異常執(zhí)行。
@RestControllerAdvice
public class ExceptionHandler{
r匹配空指針異常*,
@ Exception Handler(N uIIPointerException.class)
public Object handleRException(RException e){…}
/*匹配所有異常*/
@ExceptionHandler(Exception.class)
public Object handleRException(RException e){…}}
4 結(jié)束語
本文針對微服務(wù)日志規(guī)模龐大、難管理的問題,利用Spring的AOP切面技術(shù)、SpringBoot的配置管理及MongoDB數(shù)據(jù)庫實(shí)現(xiàn)了對分散的微服務(wù)運(yùn)行日志的統(tǒng)一收集處理。利用Spring的切面及SpringBoot的配置[6],可以獲取到微服務(wù)的運(yùn)行日志及異常信息。使用MongoDB數(shù)據(jù)庫做存儲,主要是MongoDB的易拓展、高性能等特性以及具備一定的統(tǒng)計分析查詢功能,可以快速地對日志進(jìn)行記錄并可以靈活地查詢、統(tǒng)計分析等。
目前,根據(jù)上面的設(shè)計開發(fā)的日志系統(tǒng)已成功應(yīng)用到多個微服務(wù)平臺,運(yùn)行狀況良好,用戶可直觀便捷地對日志進(jìn)行查詢統(tǒng)計,大大提高了后臺日志的利用率。
參考文獻(xiàn)(References):
[1]宋瑜輝.基于MongoDB存儲和分析輔助決裳系統(tǒng)中的海量日志[J].科技創(chuàng)新與應(yīng)用,2019:2095-2945
[2]張驍,應(yīng)時,張韜.應(yīng)用軟件運(yùn)行日志的收集與服務(wù)處理框架[J].計算機(jī)工程與應(yīng)用,2018.10:1002-8331
[3]楊旭東,陳婷,梁瀟聆.基于web的本科畢業(yè)師生雙選系統(tǒng)開發(fā)設(shè)計[J].軟件,2018.39(5):182-188
[4]李天賜,余海情.基于SSH框架試題系統(tǒng)的設(shè)計與實(shí)現(xiàn)[J].軟件,2018.39(6):74-77
[5]周芷儀,陳婷,袁瑩靜,陳龍.基于JavaScript的電子時鐘效果實(shí)現(xiàn)[J].軟件,2019.40(3):60-64
[6]陳申平.敏捷軟件開發(fā)中的配置管理探討[J].軟件,2018.39(5):134-138
*基金項(xiàng)目:中國船舶集團(tuán)有限公司科技創(chuàng)新項(xiàng)目(201823K)
作者簡介:閆四洋(1993-),男,江蘇連云港人,本科,工程師,主要研究方向:企業(yè)應(yīng)用開發(fā)。