Dubbo Filter 過濾器(攔截器)的使用——dubbo.rpc.Filter

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>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章