博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Dobbo问题及解决方案:forbid-consumer
阅读量:7100 次
发布时间:2019-06-28

本文共 2465 字,大约阅读时间需要 8 分钟。

本地运行Dubbo经常出现以下情况:

com.alibaba.dubbo.rpc.RpcException: Forbid consumer 10.0.53.69 access service com.kuaidadi.op.api.pay.service.PayChannelConfigRemoteService from registry 10.0.50.150:2181 use dubbo version 2.5.3, Please check registry access list (whitelist/blacklist).

一、问题分析:

其实线下环境根本没有对服务做白名单和黑名单机制。通过阅读源码,分析如下:

根据异常栈,抛出这个异常的代码在RegistryDirectory的第579行,如下:

public List
> doList(Invocation invocation) { if (forbidden ) { 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).”);}

如果forbidden变量为true,则抛出该异常。forbidden变量默认为false,那么什么时候变成true了呢?看RegistryDirectory的这段代码:

private void refreshInvoker(List
invokerUrls){ if (invokerUrls != null && invokerUrls.size() == 1 && invokerUrls.get(0) != null && Constants.EMPTY_PROTOCOL .equals(invokerUrls.get(0).getProtocol())) { this.forbidden = true; // 禁止访问 this.methodInvokerMap = null; // 置空列表 destroyAllInvokers(); // 关闭所有Invoker }

意思是如果invokerUrls的size为1,并且url的协议头是Constants.EMPTY_PROTOCOL时,则设置forbidden为false,Constants.EMPTY_PROTOCOL的值是empty。

refreshInvoker方法什么时候被调用呢?当某个服务的provider有变化时就会被调用,例如zookeeper上某个服务的provider目录里的内容发生变化,则zk监听器会被触发,由于provider的数量会发生变化,所以必须刷新本地的对provider的连接,具体逻辑就在refreshInvoker方法里。

可以确定的是,zookeeper推送的URL的protocol部分不可能无缘无故变成了empty,肯定是由某个地方更改了,于是看一下Constants.EMPTY_PROTOCOL到底有哪些地方调用了。当zookeeper初次订阅或者订阅的信息有变更时,都会触发toUrlsChanged方法,看看这个方法内部都做了什么,完整代码如下:

private List
toUrlsWithEmpty(URL consumer, String path, List
providers) { List
urls = toUrlsWithoutEmpty(consumer, providers); if (urls == null || urls.isEmpty()) { int i = path.lastIndexOf(‘/’ ); String category = i < 0 ? path : path.substring(i + 1); URL empty = consumer.setProtocol(Constants.EMPTY_PROTOCOL ).addParameter(Constants. CATEGORY_KEY, category); urls.add(empty); } return urls; }

二、总结

可见如果toUrlsWithoutEmpty的结果是空或者size为0,则强制返回一个protocol为empty的url,看来源头就在这里了。传入的List<String> providers实际上就是最新的服务提供者信息,当某个服务没有任何provider时,providers就变为一个size为0的List了,导致返回一个协议头为empty的url,进而导致forbidden为true,屏蔽了consumer调用。

转载于:https://www.cnblogs.com/eyesmoon/p/10064486.html

你可能感兴趣的文章
5-4-3原则
查看>>
html图像入门
查看>>
C# Mongo Client 2.4.2创建索引
查看>>
我的第四个网页制作:列表标签
查看>>
【python进阶】详解元类及其应用2
查看>>
简单实用的菜单栏
查看>>
AMap行政区查询服务
查看>>
SpringBoot2.0源码分析(一):SpringBoot简单分析
查看>>
LeetCode-96-Unique Binary Search Trees
查看>>
Mac iOS 模拟器录制屏幕生成Gif
查看>>
python练习题
查看>>
oracle log_archive_dest_1 未指定导致flash_recovery_area引发数据库挂起
查看>>
性能测试培训笔记-安装loadrunner出现vc2005_sp1_with_atl_fix_redist
查看>>
Puppet函数介绍(十八)
查看>>
数据中心开发者定义
查看>>
iOS网络编程-ASIHTTPRequest框架同步请求
查看>>
马哥Linux大型免费公开课即将开始(马哥多年经验首次对外公开)
查看>>
可穿戴操作系统,期待吗?(二)
查看>>
阿里巴巴赴美上市,市值将超千亿
查看>>
14.Azure流量管理器(下)
查看>>