-
Notifications
You must be signed in to change notification settings - Fork 26.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
RpcContext获取参数问题 #11876
Comments
不知道你的和我的问题对不对,我的问题是消费者setAttachment但是提供者get不到,看源码发现它走的是已废弃的代码getAttachment()方法。其中会if (value instanceof String),判断成立强转为string,不成立直接return null。 |
如果是 set 的 string 类型的这里不应该有问题。 |
@a4363220 AdminRpcContext 这个你们是怎么封装的,已经是在什么时机填充的 |
我也遇到了类似的问题,在dubbo-samples中有一个上下文参数传递的demo https://github.com/apache/dubbo-samples/blob/4b98c856b8c084fa51d9f0d4bbd6d45fe64cdeea/10-task/dubbo-samples-develop/dubbo-samples-develop-consumer/src/main/java/org/apache/dubbo/samples/develop/ContextTask.java#L37 public void contextServiceCall(){
//往服务端传递参数
RpcContext.getClientAttachment().setAttachment("clientKey1","This is client");
String res = contextService.invoke("context1");
//接收传递回来的参数
Map<String, Object> serverAttachments = RpcContext.getServerContext().getObjectAttachments();
System.out.println("ContextTask clientAttachment: " + JSON.toJSONString(serverAttachments));
System.out.println("ContextService Return: " + res);
} 这是provider @DubboService
public class ContextServiceImpl implements ContextService{
@Override
public String invoke(String param) {
//ServerAttachment接收传递过来的参数
Map<String, Object> serverAttachments =
RpcContext.getServerContext().getObjectAttachments();
System.out.println("ContextService server Receives server Attachments:"+ JSON.toJSONString(serverAttachments));
//往客户端传递参数
RpcContext.getServerContext().setAttachment("serverKey","这是server");
StringBuilder s = new StringBuilder();
s.append("ContextService param:").append(param);
return s.toString();
}
} 运行后在consumer这端是可以拿到provider传的attachments的 |
本质原因是为了防止上下文污染 比如:
|
【如果是在 Filter 内使用的话需要直接基于 invocation 对象操作】大佬这句话是什么意思没有理解?Filter里面不应该使用RpcContext或者attachment去传递业务标识吗? @AlbumenJ 比如我想在dubbo服务间透传tag标识,是不是直接在filter里面使用 invocation.setAttachment("dubbo.tag", "green");就可以了 |
但如果你是想要通过设置"dubbo.tag"来完成流量的打标,则需要扩展ClusterFiter(不能是filter),在invoke方法中直接使用 invocation.setAttachment("dubbo.tag", "green")。不能使用attachments的形式,因为我们拓展的ClusterFilter默认是会在内置的ClusterFilter链的最后,也就是会在ConsumerContexFilter之后,所以这些attachments不会被自动加到invocation中。ClusterFilter是Dubbo3.0中新加入,可以参考#7382 而TagStateRouter.doRoute是拿的invocation.getAttachment("dubbo.tag")来做标签路由的: 不能通过扩展Filter的方式来进行流量的打标的原因是因为Dubbo的调用链中到Filter这里就已经完成了路由选址和负载均衡,Filter只是对已确定的provider实例做一些其他操作 |
跪谢大佬,这两天一直被这个问题困扰。原因就是扩展了filter,传递了dubbo.tag 但是没办法做tag路由。非常感谢大佬的耐心解答!我去试试 @robocanic |
现在发现个问题,在本地机器上我启动了A服务和B服务,都打上了tag="green",发现是符合预期的,可以调通。 @Activate(group = {CommonConstants.PROVIDER, CommonConstants.CONSUMER})
public class DubboTagFilter implements ClusterFilter {
@Override
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
try {
String tagValue = EnvContext.getDubboTag();
// 设置到上下文中,在后续调用链路中传递
if (StringUtils.isNotBlank(tagValue)) {
invocation.setAttachment(TagKeyConstants.TAG_KEY, tagValue);
}
// 继续执行
return invoker.invoke(invocation);
} finally {
// 清理上下文
EnvContext.remove();
}
}
} 注意:所有服务都注册成功了,然后Nacos也能看到B1实例打上了tag为green |
从你的截图上来看,invocation.attachments里并没有这个tag,而B1是有tag的,所以不会路由到B1 |
确实 invocation里面没有dubbo.tag这个key。 |
我新加了一个作用于provider的过滤器,为什么在调用链路中不会生效?这个Filter是往EnvContext里面设置dubbo.tag的值的。目前来看配置没有问题。但是在请求过程中一直没有进来 @Activate(group = CommonConstants.PROVIDER)
public class DubboProviderTagFilter implements ClusterFilter {
@Override
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
try {
String tagValue = invocation.getAttachment(TagKeyConstants.TAG_KEY);
if (StringUtils.isNotBlank(tagValue)) {
EnvContext.setDubboTag(tagValue);
}
// 继续执行
return invoker.invoke(invocation);
} finally {
// 清理上下文
EnvContext.remove();
}
}
}
``` @AlbumenJ |
Dubbo3里面对这个链路透传上下文参数重新设计了一下,@AlbumenJ大佬上面也提到是为了防止上下文污染,具体可以参考文档: |
今天认真debug了一下整个链路,发现确实是dubbo.tag参数在调用某个服务的时候丢失了。举个例子: |
代码如下,定义两个filter分别来处理consumer和provider,EnvContext是ThreadLocal的用来暂存dubbo.tag标记。 @Activate(group = CommonConstants.CONSUMER)
public class DubboConsumerTagFilter implements ClusterFilter {
@Override
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
try {
String tagValue = EnvContext.getDubboTag();
// 设置到上下文中,在后续调用链路中传递
if (StringUtils.isNotBlank(tagValue)) {
invocation.setAttachment(TagKeyConstants.TAG_KEY, tagValue);
}
// 继续执行
return invoker.invoke(invocation);
} finally {
// 清理上下文
EnvContext.remove();
}
}
} @Activate(group = CommonConstants.PROVIDER)
public class DubboProviderTagFilter implements Filter {
@Override
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
try {
String tagValue = invocation.getAttachment(TagKeyConstants.TAG_KEY);
if (StringUtils.isNotBlank(tagValue)) {
EnvContext.setDubboTag(tagValue);
}
// 继续执行
return invoker.invoke(invocation);
} finally {
// 清理上下文
EnvContext.remove();
}
}
} |
除了不清理threadLocal 感觉无解了啊。dubbo支持某个参数一直沿着调用链路传递么? @robocanic |
对于非内部 key(如 tag),其他 key 都是默认透传的 |
请问,dubbo3.2.7中可以上下文可以一直透传吗?增加过滤器设置参数,A是一个服务,B、C、D在同一个服务上,例如A->B->C,B->D,在A->B前设置RpcContext.getServiceContext().setAttachment("app_name","A"),B可以拿到app_name为A,B调C前,设置RpcContext.getServiceContext().setAttachment("app_name","B"),在B->C后,参数本应该是app_name为B,但结果app_name变为了A了,怎么回事呢? |
A->B,在 A 侧使用 RpcContext.getClientAttachment().setAttachment("app_name","A"),在 B 侧使用 RpcContext.getServerAttachment().getAttachment("app_name") |
建议优化下命名,client和server的命名远比不上consumer和provider语义更清晰,理论上来说consumer和provider其实都是client,server的语义更偏向于统一管理的服务端,还有ServiceContext、ServerContext这俩肉眼几乎没区别,太容易用错了。 |
system:centos7.9
jdk:11
dubbo:3.1.4
序列化:kryo1.0.1
问题:在消费者透传信息给提供者时,在提供者的方法第一行是可以获取到透传信息,但是在方法执行期间和执行末尾获取透传信息则为空,但是相同的案例 我把dubbo版本切回到3.1.0版本则一切正常,不太理解是因为什么原因造成的,还是官方已经得知该问题并修复了。
提供者代码如下:
3.1.4版本获取rpc透传信息大致打印如下:
3.1.0版本获取rpc透传信息大致打印如下:
可以看到在3.1.0版本上从方法执行到末尾都可以正常拿到RpcContext参数
The text was updated successfully, but these errors were encountered: