解決dubbo問題

今日在做maven項目訪問url:http://localhost:9101/admin/type_template.html時,一直出不來效果,控制檯報如下錯誤:

com.alibaba.dubbo.rpc.RpcException:Forbid consumer 192.168.80.6 access service com.xxx.xxx.xxx(此處是你的TypeTemplateService的包名).TypeTemplateService from registry 192.168.25.130:2181 use dubbo version 2.8.4, Please check registry access list (whitelist/blacklist).

1.原因分析:

以上異常意思是當前調用者被禁止訪問某個服務,請檢查下注冊中心訪問列表,還有黑名單和白名單。
其實線下環境根本沒有對服務做白名單和黑名單機制,因爲線下環境給開發人員的賬號是guest,沒有權限做黑白名單。看源碼發現根源所在,根據異常棧,拋出這個異常的代碼在RegistryDirectory的第579行,如下:
public List<Invoker<T>> 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<URL> 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啓動了,有一個provider下線了,所以必須刷新本地的對provider的連接,具體邏輯就在refreshInvoker方法裏,這個方法的調用棧如下:

可以確定的是,zookeeper推送的URL的protocol部分不可能無緣無故變成了empty,肯定是由某個地方更改了,於是看一下Constants.EMPTY_PROTOCOL到底有哪些地方調用了,如下:

見圖中紅色圈圈部分,當zookeeper初次訂閱或者訂閱的信息有變更時,都會觸發toUrlsChanged方法,看看這個方法內部都做了什麼,完整代碼如下:
     private List<URL> toUrlsWithEmpty(URL consumer, String path, List<String> providers) {
        List<URL> 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;
    }
2.結論:
UrlsWithoutEmpty的結果是空或者size爲0,則強制返回一個protocol爲empty的url,看來源頭就在這裏了。傳入的List<String> providers實際上就是最新的服務提供者信息,當某個服務沒有任何provider時,providers就變爲一個size爲o的List了,導致返回一個協議頭爲empty的url,進而導致forbidden爲true,屏蔽了consumer調用。
3.解決辦法:

重啓服務器,重新運行,訪問你的url





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章