[apache/dubbo]dubbo3.1.5添加自定义Filter调用异常

2023-12-25 434 views
5
Environment
  • Dubbo version: 3.1.5
  • Java version: 1.8
Steps to reproduce this issue

1.成功调用到提供端,但是返回异常,返回报: [DUBBO] Decode rpc invocation failed: null, dubbo version: 3.1.5, current host: 192.168.0.190, error code: 4-20. This may be caused by , go to https://dubbo.apache.org/faq/4/20 to find instructions.

java.lang.NullPointerException: null at java.util.concurrent.ConcurrentHashMap.get(ConcurrentHashMap.java:936) at org.apache.dubbo.rpc.support.GroupServiceKeyCache.getServiceKey(GroupServiceKeyCache.java:37) at org.apache.dubbo.rpc.support.ProtocolUtils.serviceKey(ProtocolUtils.java:51) at org.apache.dubbo.rpc.protocol.AbstractProtocol.serviceKey(AbstractProtocol.java:83) at org.apache.dubbo.rpc.protocol.dubbo.DubboProtocol.getInvoker(DubboProtocol.java:282)

2.使用的是dubbo 3.1.5 3.通过日志发现消费端会3次进入invoke方法,这个过滤器主要用来设置额外请求参数

过滤器代码如下: `@Activate(group = {Constants.CONSUMER, Constants.PROVIDER}, order = -1) public class DubboTenantFilter implements Filter { protected final Logger log = LoggerFactory.getLogger(this.getClass());

@Override
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
    //判断是消费者 还是 服务提供者
    System.out.println("invoke:"+RpcContext.getContext().isConsumerSide());
    if (RpcContext.getContext().isConsumerSide()) {
        //消费者 将tenant_id set至上下文中
        RpcContext.getContext().setAttachment(DefConstants.TENANT_HEADER_KEY, TenantContextHolder.getTenantId());
    } else {
        String tenantId = RpcContext.getContext().getAttachment(DefConstants.TENANT_HEADER_KEY);
        if(tenantId!=null){
            TenantContextHolder.setTenantId(tenantId);
        }
    }
    try {
        return invoker.invoke(invocation);
    }finally {
        if (RpcContext.getContext().isProviderSide()) {
            TenantContextHolder.clear();
        }
    }
}

}`

回答

7

1.通过日志发现消费端会3次进入invoke方法,这个过滤器主要用来设置额外请求参数 答:如果Filter是全局的则有些内部的调用,建议通过invocation获取接口名和方法名过滤掉不需要的

2 请问下面异常必现吗 java.lang.NullPointerException: null at java.util.concurrent.ConcurrentHashMap.get(ConcurrentHashMap.java:936) at org.apache.dubbo.rpc.support.GroupServiceKeyCache.getServiceKey(GroupServiceKeyCache.java:37) at org.apache.dubbo.rpc.support.ProtocolUtils.serviceKey(ProtocolUtils.java:51) at org.apache.dubbo.rpc.protocol.AbstractProtocol.serviceKey(AbstractProtocol.java:83) at org.apache.dubbo.rpc.protocol.dubbo.DubboProtocol.getInvoker(DubboProtocol.java:282)

4

建议提供完整的invocation信息,两边dubbo 版本是否一致

4

1.3次调用的是同一个接口方法名 2.异常是必现的 3.我的service写法如下:

提供者:
@DubboService(version = CommonConstants.DUBBO_VERSION_1_0_0,group = CommonConstants.DUBBO_GROUP,interfaceClass = RemoteConfigsService.class)
public class RemoteConfigsServiceProvider implements RemoteConfigsService {

    @Resource
    private IConfigsService configsService;

    @Override
    public String getContent(String configCode){
        Configs configs = configsService.getOne(new QueryWrapper<Configs>().lambda()
                .eq(Configs::getConfigCode,configCode)
        );
        if(configs ==null || StringUtils.isBlank(configs.getContent())){
            return null;
        }

        String content = configs.getContent();
        return content;
    }

}

调用:
    @DubboReference(version = CommonConstants.DUBBO_VERSION_1_0_0,group = CommonConstants.DUBBO_GROUP)
    private RemoteConfigsService configsService;

    @Override
    public Channel getChannel(ChannelEnum.Code code) {
        ConfigsEnum configCode = ConfigsEnum.getByCode(code.getConfigCode());
        String content = configsService.getContent(configCode.name());
        if(StringUtils.isBlank(content)){
            throw new ServiceException("通道参数未配置: "+code.getTitle());
        }
...
0

我发现如果设置以下代码就会出现这个异常:


TenantContextHolder.setTenantId(tenantId);
    public static void setTenantId(String tenantId) {
        TENANT_ID.set(tenantId);
    }
private static final ThreadLocal<String> TENANT_ID = new TransmittableThreadLocal<>();

改成通过RpcContext上下文的方式获取参数调用就正常了,但是invoke也会调用3次,不知道会不会有影响

    @Override
    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
        //判断是消费者 还是 服务提供者
        if (RpcContext.getContext().isConsumerSide()) {
            //消费者 将tenant_id set至上下文中
            RpcContext.getContext().setAttachment(DefConstants.TENANT_HEADER_KEY, TenantContextHolder.getTenantId());
        }

        return invoker.invoke(invocation);
    }

    public static String getTenantId() {
        String tenantId = TENANT_ID.get();
        if(tenantId==null){
            tenantId = RpcContext.getContext().getAttachment(DefConstants.TENANT_HEADER_KEY);
        }
        return tenantId;
    }
2

这个应该是重试了,请求远端失败

3

dubbo3.1.5 未复现此问题 没有出现重试和失败

filter 代码

@Activate(group = {Constants.CONSUMER, Constants.PROVIDER}, order = -1)
public class MyFilter implements Filter {
    private static final Logger logger = LoggerFactory.getLogger(MyFilter.class);

    @Override
    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
        logger.info("{}", invocation.getMethodName());
        if (!"org.apache.dubbo.springboot.demo.DemoService:0.0.0".equals(invocation.getTargetServiceUniqueName())) {
            return invoker.invoke(invocation);
        }

        if (RpcContext.getContext().isConsumerSide()) {
            RpcContext.getContext().setAttachment("tenantId", "aaaaa");
        } else {
            String tenantId = RpcContext.getContext().getAttachment("tenantId");
            TenantContextHolder.setTenantId(tenantId);
        }
        return invoker.invoke(invocation);
    }
}
public class TenantContextHolder {
    public static void setTenantId(String tenantId) {
        TENANT_ID.set(tenantId);
    }
    private static final ThreadLocal<String> TENANT_ID = new TransmittableThreadLocal<>();

}
4

@weixuehu 好兄弟,问题解决了吗?我也遇到了