(十三)异常分析

来源:互联网 发布:淘宝最诚信的邮票商家 编辑:程序博客网 时间:2024/05/18 16:19

调用dubbo服务,有时出现异常信息

Forbid consumer xxx.xxx.xxx.xxx(ip) access service xx.xx(service全包的名称) from registry xxx.xxx.xxx.xxx(提供者的ip) use dubbo version xxx(dubbo的版本号), Please check registry access list (whitelist/blacklist).

查看dubbo的源码:
com.alibaba.dubbo.registry.integration.RegistryDirectory类的doList方法:

public List<Invoker<T>> doList(Invocation invocation) {    if (forbidden) { //1处        throw new RpcException(RpcException.FORBIDDEN_EXCEPTION, "Forbid consumer " +  NetUtils.getLocalHost() + " access service " + getInterface().getName() + " from registry " + getUrl().getAddress() + " use dubbo version " + Version.getVersion() + ", Please check registry access list (whitelist/blacklist).");    }    List<Invoker<T>> invokers = null;    Map<String, List<Invoker<T>>> localMethodInvokerMap = this.methodInvokerMap; // local reference    if (localMethodInvokerMap != null && localMethodInvokerMap.size() > 0) {        String methodName = RpcUtils.getMethodName(invocation);        Object[] args = RpcUtils.getArguments(invocation);        if(args != null && args.length > 0 && args[0] != null                && (args[0] instanceof String || args[0].getClass().isEnum())) {            invokers = localMethodInvokerMap.get(methodName + "." + args[0]); // 可根据第一个参数枚举路由        }        if(invokers == null) {            invokers = localMethodInvokerMap.get(methodName);        }        if(invokers == null) {            invokers = localMethodInvokerMap.get(Constants.ANY_VALUE);        }        if(invokers == null) {            Iterator<List<Invoker<T>>> iterator = localMethodInvokerMap.values().iterator();            if (iterator.hasNext()) {                invokers = iterator.next();            }        }    }    return invokers == null ? new ArrayList<Invoker<T>>(0) : invokers;}
看源码的"1处",当forbidden被设为true,即提供者被认为是禁止访问,而在调用doList来获取提供者的Invoker列表时,会抛出这个异常。
接着看看forbidden在什么地方被设为true?
/** * 根据invokerURL列表转换为invoker列表。转换规则如下: * 1.如果url已经被转换为invoker,则不在重新引用,直接从缓存中获取,注意如果url中任何一个参数变更也会重新引用 * 2.如果传入的invoker列表不为空,则表示最新的invoker列表 * 3.如果传入的invokerUrl列表是空,则表示只是下发的override规则或route规则,需要重新交叉对比,决定是否需要重新引用。 * @param invokerUrls 传入的参数不能为null */private void refreshInvoker(List<URL> invokerUrls){    if (invokerUrls != null && invokerUrls.size() == 1 && invokerUrls.get(0) != null            && Constants.EMPTY_PROTOCOL.equals(invokerUrls.get(0).getProtocol())) { //2处        this.forbidden = true; // 禁止访问        this.methodInvokerMap = null; // 置空列表        destroyAllInvokers(); // 关闭所有Invoker    } else {        this.forbidden = false; // 允许访问        Map<String, Invoker<T>> oldUrlInvokerMap = this.urlInvokerMap; // local reference        if (invokerUrls.size() == 0 && this.cachedInvokerUrls != null){            invokerUrls.addAll(this.cachedInvokerUrls);        } else {            this.cachedInvokerUrls = new HashSet<URL>();            this.cachedInvokerUrls.addAll(invokerUrls);//缓存invokerUrls列表,便于交叉对比        }        if (invokerUrls.size() ==0 ){            return;        }        Map<String, Invoker<T>> newUrlInvokerMap = toInvokers(invokerUrls) ;// 将URL列表转成Invoker列表        Map<String, List<Invoker<T>>> newMethodInvokerMap = toMethodInvokers(newUrlInvokerMap); // 换方法名映射Invoker列表        // state change        //如果计算错误,则不进行处理.        if (newUrlInvokerMap == null || newUrlInvokerMap.size() == 0 ){            logger.error(new IllegalStateException("urls to invokers error .invokerUrls.size :"+invokerUrls.size() + ", invoker.size :0. urls :"+invokerUrls.toString()));            return ;        }        this.methodInvokerMap = multiGroup ? toMergeMethodInvokerMap(newMethodInvokerMap) : newMethodInvokerMap;        this.urlInvokerMap = newUrlInvokerMap;        try{            destroyUnusedInvokers(oldUrlInvokerMap,newUrlInvokerMap); // 关闭未使用的Invoker        }catch (Exception e) {            logger.warn("destroyUnusedInvokers error. ", e);        }    }}
看到上面源码的"2处",服务的提供者列表为空时,则会将调用提供者设为禁止forbidden。
而提供者列表为空,可能提供者还没启用成功,或者已经被禁用状态,或者列为调用黑名单等等。
原创粉丝点击