Dubbo秘密傳遞:讓你的代碼行云流水
哈嘍,大家好,我是了不起。
在Dubbo使用過程中,有一些通用參數(shù)如果顯式的在接口參數(shù)中傳遞,使用起來會有一些不方便。
比如:經(jīng)常使用的用戶信息、token等上下文信息,如果都放入?yún)?shù)中傳遞,這樣會耦合到業(yè)務(wù)邏輯中了,這時隱式傳參就是一種比較好的處理方式了。
隱式傳參
Dubbo提供了RpcContext隱式傳參的方式:
//消費(fèi)側(cè)傳入?yún)?shù)
RpcContext.getContext().setAttachment(String key, String value);
//服務(wù)提供側(cè)接收參數(shù)
RpcContext.getContext().getAttachment(String key);
通過上面兩個方法,我們可以在消費(fèi)端傳入?yún)?shù),然后在提供側(cè)就可以接收到參數(shù)了,類似于線程變量ThreadLocal
為了更好的兼顧Dubbo多重調(diào)用導(dǎo)致隱式傳參丟失的問題,我們可以在每個Dubbo服務(wù)程序中加入兩個filter可解決問題
創(chuàng)建Filter
消費(fèi)側(cè):
import java.util.HashMap;
import java.util.Map;
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.alibaba.fastjson.JSONObject;
@Activate(group = {Constants.CONSUMER})
public class DubboConsumerContextFilter implements Filter {
@Override
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
RpcContext.getContext().setAttachment("token", "tokenvalue");
return invoker.invoke(invocation);
}
}
服務(wù)提供側(cè):
import java.util.Map;
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.alibaba.fastjson.JSONObject;
@Activate(group = {Constants.PROVIDER})
public class DubboProviderContextFilter implements Filter {
@Override
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
// 處理token
String token = RpcContext.getContext().getAttachment("token");
//TODO 處理代碼
return invoker.invoke(invocation);
}
}
其中@Activate注解指定了這個Filter是在消費(fèi)端生效還是服務(wù)端生效。
配置filter到META-INF中
在/src/main/resources/META-INF/dubbo/下新建文件,文件名為com.alibaba.dubbo.rpc.Filter,沒錯,這就是文件的名稱,而不是包路徑。
文件內(nèi)容:
dubboProviderContextFilter=com.xxx.DubboProviderContextFilter
dubboConsumerContextFilter=com.xxx.DubboConsumerContextFilter
總結(jié)
經(jīng)過以上簡單的幾步,我們在對業(yè)務(wù)代碼無侵入的情況下,通過Filter實現(xiàn)了Dubbo遠(yuǎn)程調(diào)用中的隱式傳參。這可以方便地在服務(wù)調(diào)用鏈中傳遞一些公共的上下文信息,如登錄信息、請求ID等。