想在Dubbo应用之间进行参数传递,其实非常简单。通过Dubbo提供的隐式传递功能即可实现。使用方式如下所示。
// A服务设置参数
RpcContext.getContext().setAttachment("name", "小明");
// A服务通过RPC调用B服务
// B服务可以获取到A服务设置的参数
RpcContext.getContext().getAttachment("name");
所以我们可以把全局事务id放在RpcContext(rpc)中,然后在下游取出来。但是seata是从RootContext取出事务id的,我们如何先把事务id从RpcContext取出来然后再放到RootContext中呢?其实可以用到Dubbo Fillter
我们先看一下Dubbo Filter在哪个环节起作用,当我们调用远程方法的时候,实际上是通过代理对象调用的,将调用信息通过网络发送到服务端,服务端也是通过代理对象来接收请求的,然后根据请求调用服务端的方法,并返回结果。
而Dubbo Filter的作用则可以让用户在发送请求之前或者执行本地方法之前执行用户自定义的逻辑,增加可扩展性
所以我们可以在Consumer端通过Filter将事务id放在RpcContext中,在Provider端将事务id从RpcContext中取出来然后放入到RootContext中
@Activate(group = {DubboConstants.PROVIDER, DubboConstants.CONSUMER}, order = 100)
public class ApacheDubboTransactionPropagationFilter implements Filter {
private static final Logger LOGGER = LoggerFactory.getLogger(ApacheDubboTransactionPropagationFilter.class);
@Override
public Result invoke(Invoker> invoker, Invocation invocation) throws RpcException {
String xid = RootContext.getXID();
BranchType branchType = RootContext.getBranchType();
String rpcXid = getRpcXid();
String rpcBranchType = RpcContext.getContext().getAttachment(RootContext.KEY_BRANCH_TYPE);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("xid in RootContext[{}] xid in RpcContext[{}]", xid, rpcXid);
}
boolean bind = false;
// 事务id为空,说明是在客户端调用,将事务id设置进去
if (xid != null) {
RpcContext.getContext().setAttachment(RootContext.KEY_XID, xid);
RpcContext.getContext().setAttachment(RootContext.KEY_BRANCH_TYPE, branchType.name());
} else {
// rpcXid不为空,说明这是一个事务方法
if (rpcXid != null) {
// 将事务id绑定到上下文中
RootContext.bind(rpcXid);
if (StringUtils.equals(BranchType.TCC.name(), rpcBranchType)) {
RootContext.bindBranchType(BranchType.TCC);
}
bind = true;
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("bind xid [{}] branchType [{}] to RootContext", rpcXid, rpcBranchType);
}
}
}
try {
return invoker.invoke(invocation);
} finally {
if (bind) {
BranchType previousBranchType = RootContext.getBranchType();
String unbindXid = RootContext.unbind();
if (BranchType.TCC == previousBranchType) {
RootContext.unbindBranchType();
}
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("unbind xid [{}] branchType [{}] from RootContext", unbindXid, previousBranchType);
}
if (!rpcXid.equalsIgnoreCase(unbindXid)) {
LOGGER.warn("xid in change during RPC from {} to {},branchType from {} to {}", rpcXid, unbindXid,
rpcBranchType != null ? rpcBranchType : "AT", previousBranchType);
if (unbindXid != null) {
RootContext.bind(unbindXid);
LOGGER.warn("bind xid [{}] back to RootContext", unbindXid);
if (BranchType.TCC == previousBranchType) {
RootContext.bindBranchType(BranchType.TCC);
LOGGER.warn("bind branchType [{}] back to RootContext", previousBranchType);
}
}
}
}
}
}
private String getRpcXid() {
String rpcXid = RpcContext.getContext().getAttachment(RootContext.KEY_XID);
if (rpcXid == null) {
rpcXid = RpcContext.getContext().getAttachment(RootContext.KEY_XID.toLowerCase());
}
return rpcXid;
}
}
Http
参考博客
[1]



