com.alibaba.dubbo.rpc.Filter簡介
咱們先說說 “Filter”,顧名思義 過濾器,在我們平時的工作中也是一員猛將。
在之前的文章中我也介紹了在Spring中類似的HandlerInterceptor的使用方法。
com.alibaba.dubbo.rpc.Filter它換了個馬甲,乾的依然是守門(過濾器)的活兒,不過是跑去阿里上班了,在dubbo幹起了守門保安,做事低調所以認識他的猿並不多,遠不如javax.servlet.Filter和HandlerInterceptor 名聲在外,兒孫遍地,打麻將都還多幾個在旁邊買馬。
廢話扯完,進入正題,我就拿我這邊的誇系統打印業務流水號來介紹。業務背景是找問題查日誌經常涉及到誇系統查詢 可是到了另一個系統我如何迅速找到對應的日誌 在日誌量龐大的情況下靠時間來篩選是十分低效且愚蠢的。所以咱們每個HTTP請求分配一個唯一的UUID,在Dubbo接口調用的過程中將UUID攜帶過去保證UUID不變實現日誌迅速定位。
1、定義Filter
- 實現com.alibaba.dubbo.rpc.Filter接口。
- 添加Activate,其註解含義如下:
- group :所屬組 例如消費者、服務提供者 啥的
- order :多個Filter的執行順序 (越小越早)
package com.test.trace.remote.filter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import com.alibaba.dubbo.common.Constants;
import com.alibaba.dubbo.common.extension.Activate;
import com.alibaba.dubbo.rpc.Filter;
import com.alibaba.dubbo.rpc.Invocation;
import com.alibaba.dubbo.rpc.Invoker;
import com.alibaba.dubbo.rpc.Result;
import com.alibaba.dubbo.rpc.RpcContext;
import com.alibaba.dubbo.rpc.RpcException;
import com.test.trace.support.AbstractMyThreadContext;
import com.test.trace.support.AbstractUUIDShort;
@Activate(group = {Constants.CONSUMER, Constants.PROVIDER}, order = -30000)
public class RemoteTraceIdFilter implements Filter {
protected final Logger log = LoggerFactory.getLogger(this.getClass());
@Override
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
//判斷是消費者 還是 服務提供者
if (RpcContext.getContext().isConsumerSide()) {
//消費者 將trace_id(業務流水號) set至上下文中
RpcContext.getContext().setAttachment(AbstractMyThreadContext.TRACE_ID,
AbstractMyThreadContext.getTraceId());
} else {
//取出業務流水號
String traceId =
RpcContext.getContext().getAttachment(AbstractMyThreadContext.TRACE_ID);
if (traceId == null) {
traceId = AbstractUUIDShort.generate();
}
//流水號set至線程局部變量
AbstractMyThreadContext.setTraceId(traceId);
//slf4j 中設置了日誌打印格式用作日誌鏈路追蹤
MDC.put(AbstractMyThreadContext.MDC_TRACE_ID, traceId);
}
try {
return invoker.invoke(invocation);
} finally {
if (RpcContext.getContext().isProviderSide()) {
MDC.remove(AbstractMyThreadContext.MDC_TRACE_ID);
AbstractMyThreadContext.removeTraceId();
}
}
}
}
2、取個名
- 在resources目錄下新建META-INF文件夾,然後建立子文件夾dubbo,最後新建文件com.alibaba.dubbo.rpc.Filter。(敲黑板劃重點拉!這裏不要弄錯了)
- 爲你的過濾器起個名並附上對應的過濾器實現類的路徑,如下圖就取名爲traceId(這裏的名大家根據業務自己起名字)
3、去守門
- 去具體的項目中 找到 你們的dubbo配置文件加上如下配置
- filter 也就是咱們第二步在文件中取的別名
<dubbo:provider filter="traceId" />
<dubbo:consumer filter="traceId" />
到這個dubbo中Filter的簡單適用方法大家應該有所瞭解可以上手使用了。
如果有需要整套日誌鏈路追蹤的 可以等我下一篇文章中貼出剩下的代碼 。
4、番外篇
大家現在都用的maven 這裏有個小坑需要注意 還是提前說下。如果不注意可能會報:No such extension xxxFilter for filter/com.alibaba.dubbo.rpc.Filter錯誤
錯誤內容是找不到xxxFilter,有可能是你的pom中指定了resources下需要打包的文件類型,修改成.*結尾就好了。代碼如下
<resource>
<directory>${basedir}/src/main/resources</directory>
<filtering>true</filtering>
<includes>
<include>**/*.*</include>
</includes>
</resource>