首先需要再消费端的AbstractClusterInvoker类的inoke()方法类,把附加属性键值对放到RpcInvocation的attachments变量中,然后经过网络传递到服务端。
服务端则使用ContextFilter对请求进行拦截,并从RpcInvocation中获取attachments中的键值对,然后使用RpcContext.getContext().setAttachement设置到上下文对象中。
消费端:AbstractClusterInvoker方法
public Result invoke(final Invocation invocation) throws RpcException {
checkWhetherDestroyed();
// binding attachments into invocation.
Map<String, String> contextAttachments = RpcContext.getContext().getAttachments();
if (contextAttachments != null && contextAttachments.size() != 0) {
((RpcInvocation) invocation).addAttachments(contextAttachments);
}
List<Invoker<T>> invokers = list(invocation);
LoadBalance loadbalance = initLoadBalance(invokers, invocation);
RpcUtils.attachInvocationIdIfAsync(getUrl(), invocation);
return doInvoke(invocation, invokers, loadbalance);
}
添加的隐式参数最终是要清除的,当发送完成后,将会在ConsumerContextFilter的invoker中清除
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
RpcContext.getContext().setInvoker(invoker).setInvocation(invocation).setLocalAddress(NetUtils.getLocalHost(), 0).setRemoteAddress(invoker.getUrl().getHost(), invoker.getUrl().getPort());
if (invocation instanceof RpcInvocation) {
((RpcInvocation)invocation).setInvoker(invoker);
}
Result var3;
try {
RpcContext.removeServerContext();
var3 = invoker.invoke(invocation);
} finally {
RpcContext.getContext().clearAttachments();
}
return var3;
}
服务端:ContextFilter方法
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
Map<String, String> attachments = invocation.getAttachments();
if (attachments != null) {
attachments = new HashMap((Map)attachments);
((Map)attachments).remove("path");
((Map)attachments).remove("interface");
((Map)attachments).remove("group");
((Map)attachments).remove("version");
((Map)attachments).remove("dubbo");
((Map)attachments).remove("token");
((Map)attachments).remove("timeout");
((Map)attachments).remove("async");
((Map)attachments).remove("dubbo.tag");
((Map)attachments).remove("dubbo.force.tag");
}
RpcContext.getContext().setInvoker(invoker).setInvocation(invocation).setLocalAddress(invoker.getUrl().getHost(), invoker.getUrl().getPort());
if (attachments != null) {
if (RpcContext.getContext().getAttachments() != null) {
RpcContext.getContext().getAttachments().putAll((Map)attachments);
} else {
RpcContext.getContext().setAttachments((Map)attachments);
}
}
if (invocation instanceof RpcInvocation) {
((RpcInvocation)invocation).setInvoker(invoker);
}
Result var4;
try {
var4 = invoker.invoke(invocation);
} finally {
RpcContext.removeContext();
RpcContext.removeServerContext();
}
return var4;
}
服务端会在此时将接受到的隐式参数设置到上下文中。
消费端拦截器的添加时机
image.png
服务端拦截器添加时机
image.png
网友评论