Dubbo自定义日志拦截器
生活随笔
收集整理的這篇文章主要介紹了
Dubbo自定义日志拦截器
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
前言
上一篇文章 Spring aop+自定義注解統一記錄用戶行為日志 記錄了 web層中通過自定義注解配合Spring aop自動記錄用戶行為日志的過程。那么按照分布式架構中Dubbo服務層的調用過程是否也可以實現統一記錄日志?自定義日志攔截器可以實現這個需求。
需求場景
在使用Dubbo搭建的分布式項目中,服務層代碼調用是這樣的:
@GetMapping(value = "/info") 2 public BaseResult userInfo() { 3 //rpc遠程調用用戶服務 4 BaseResult result = mUserService.userInfo(); 6 return result; 7 }這里的用戶服務位于另外一個服務進程,由服務提供者暴露出來,讓web層遠程調用,需要記錄服務結果的調用過程,便于跟蹤定位bug.
自定義日志攔截器
翻看下Dubbo官方文檔,可以看到如下內容:
簡要說明:
- Dubbo 中所有的攔截器全部繼承自org.apache.dubbo.rpc.Filter接口,我們自己也可以自行擴展,只要繼承該接口即可.
- 用戶自定義 filter 默認在內置 filter 之后執行
新增 DubboServiceFilter 攔截器如下:
public class DubboServiceFilter implements Filter {private static final Logger LOGGER = LoggerFactory.getLogger(DubboServiceFilter.class);@Overridepublic Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {//外部日志開關默認關閉String logSwitch = StringUtils.equals(RedisUtil.get(BaseConstants.CACHE_SERVICE_LOG_SWITCH), BaseConstants.YES) ? BaseConstants.YES : BaseConstants.NO;if (StringUtils.equals(BaseConstants.YES, logSwitch)) {//打印入參日志DubboServiceRequest serviceRequest = new DubboServiceRequest();serviceRequest.setInterfaceName(invocation.getInvoker().getInterface().getName());serviceRequest.setMethodName(invocation.getMethodName());serviceRequest.setArgs(invocation.getArguments());LOGGER.info("dubbo服務接口入參: " + JSON.toJSONString(serviceRequest));}//開始時間long startTime = System.currentTimeMillis();//執行接口調用邏輯Result result = invoker.invoke(invocation);//調用耗時long elapsed = System.currentTimeMillis() - startTime;//如果發生異常 則打印異常日志if (result.hasException() && invoker.getInterface() != GenericService.class) {LOGGER.error("dubbo執行異常: ", result.getException());} else {if (StringUtils.equals(BaseConstants.YES, logSwitch)) {//打印響應日志DubboServiceResponse serviceResponse = new DubboServiceResponse();serviceResponse.setMethodName(invocation.getMethodName());serviceResponse.setInterfaceName(invocation.getInvoker().getInterface().getName());serviceResponse.setArgs(invocation.getArguments());serviceResponse.setResult(new Object[]{result.getValue()});serviceResponse.setSpendTime(elapsed);LOGGER.info("dubbo服務響應成功,返回數據: " + JSON.toJSONString(serviceResponse));}}//返回結果響應結果return result;} }代碼中對應的實體bean如下:
入參實體:
/*** @program: easywits* @description:Dubbo服務請求入參實體* @author: zhangshaolin* @create: 2019-01-08 20:35**/ @Data public class DubboServiceRequest implements Serializable{private static final long serialVersionUID = 7127824956842786618L;/*** 接口名*/private String interfaceName;/*** 方法名*/private String methodName;/*** 參數*/private Object[] args; }響應實體:
/*** @program: easywits* @description: Dubbo服務響應結果實體* @author: zhangshaolin* @create: 2019-01-08 20:36**/ @Data public class DubboServiceResponse implements Serializable{private static final long serialVersionUID = -2531169660859647737L;/*** 接口名*/private String interfaceName;/*** 方法名*/private String methodName;/*** 參數*/private Object[] args;/*** 返回結果*/private Object result;/*** 調用耗時(毫秒)*/private long spendTime; }在/src/main/resources/META-INF/dubbo目錄下新增純文本文件org.apache.dubbo.rpc.Filter 內容為:
dubboServiceFilter=com.easywits.common.filter.DubboServiceFilter- 鍵值對形式,鍵隨便起個名字
- 值為DubboServiceFilter攔截器的完整包名.
最后在服務提供者配置文件中添加配置使攔截器生效:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"...省略部分代碼"><!--服務提供方應用信息,用于計算依賴關系--><dubbo:application name="easywits-upms-rpc-service"/><!--用dubbo協議在20881端口暴露服務--><dubbo:protocol name="dubbo" port="20881" payload="52428800"/><!--自定義服務層過濾器,值為上述步驟文本文件中的鍵--><dubbo:provider filter="dubboServiceFilter"/>....省略部分服務配置 </beans>驗證結果
抓一下我們業務中的部分日志信息看下效果,如下圖:
可以清楚地看到Dubbo服務接口調用的請求參數信息,以及最終的響應結果信息,便于定位線上問題。
參考文檔:http://dubbo.apache.org/zh-cn/docs/dev/impls/filter.html
最后
記錄一個比較簡單的具體實用場景,后續會不定期更新更多的實用場景,歡迎關注公眾號【張少林同學】!
總結
以上是生活随笔為你收集整理的Dubbo自定义日志拦截器的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 控制反转(ioc)和 面向切面(AOP)
- 下一篇: js 克隆数组