• <input id="qucwm"><u id="qucwm"></u></input>
  • <menu id="qucwm"></menu>
  • <input id="qucwm"><tt id="qucwm"></tt></input>
  • <input id="qucwm"><acronym id="qucwm"></acronym></input>
  • 如何動態獲取Dubbo服務提供方地址列表

    一、前言

    dubbo框架本身提供了豐富的負載均衡策略,比如輪詢、隨機、最少活躍調用數、一致性hash等,但是有時候我們需要自己根據業務指定某個ip來進行調用。要指定ip進行調用就需要先知道服務提供者的ip。本文我們先來探討第一步,當服務注冊中心使用zookeeper時候如何獲取某一個服務的提供端的地址列表。

    二、實現

    我們知道當服務提供方啟動時候,會注冊服務到服務注冊中心,本文我們通用zookeeper,比如服務com.books.dubbo.demo.api.GreetingService則注冊到zk后,是下面樹形結構

    image.png

    那么當消費端啟動時候會去zookeeper上訂閱path為/dubbo/com.books.dubbo.demo.api.GreetingService/providers下面的信息,也就是服務提供者列表信息,那么我們就可以基于這個原理來獲取某一個服務提供者列表,然后對信息進行過濾加工,并且注冊一個監聽器,當服務提供者機器增減后,動態更新保存的地址列表。

    基于上面原理實現代碼如下:

    public class ZookeeperIpList {
    
        private String dataId = "com.books.dubbo.demo.api.GreetingService/providers:1.0.0";
        private URL CONSUMER_URL;
        private static final Joiner j = Joiner.on("|").useForNull("nil");
    
        public final List<String> getIpList() {
            return ipList;
        }
    
        private volatile List<String> ipList = new ArrayList<String>();
    
        //對獲取的列表內容進行過濾
        private static List<URL> toUrlsWithoutEmpty(URL consumer, List<String> providers) {
            List<URL> urls = new ArrayList<URL>();
            if (providers != null && providers.size() > 0) {
                urls = providers.stream().map(provider -> URL.decode(provider)).filter(provider -> provider.contains("://"))
                        .map(provider -> URL.valueOf(provider)).filter(url -> UrlUtils.isMatch(consumer, url))
                        .collect(Collectors.toList());
            }
            
            return urls;
        }
    
        // 解析服務提供者地址列表為ip:port格式
        private void parseIpList(List<String> ipSet) {
    
            List<URL> urlList = toUrlsWithoutEmpty(CONSUMER_URL, ipSet);
            final List<String> ipListTemp = urlList.stream().map(url -> url.getAddress()).collect(Collectors.toList());
            this.ipList = ipListTemp;
    
        }
    
        public void init(String zkServerAddr, String zkGroup, String dataId, String serviceGroup) {
            // 1.參數校驗
            Assert.notNull(zkServerAddr, "zkServerAddr is null.");
            Assert.notNull(dataId, "dataId is null.");
            Assert.notNull(dataId, "zkGroup is null.");
            Assert.notNull(dataId, "serviceGroup is null.");
    
            // 2.拼接訂閱的path
            String[] temp = dataId.split(":");
            if (temp.length != 2) {
                throw new RuntimeException("dataId is illegal");
            }
    
            this.dataId = "/" + zkGroup + "/" + temp[0] + "/providers";
            String consumeUrl = "consumer://127.0.0.1/?group=" + serviceGroup + "&interface=" + temp[0] + "&version="
                    + temp[1];
            CONSUMER_URL = URL.valueOf(consumeUrl);
    
            // 3.開啟zk,訂閱path路徑下服務提供者信息,并添加監聽器
            System.out.println(j.join("init zk ", zkServerAddr, this.dataId, consumeUrl));
            ZkClient zkClient = new ZkClient(zkServerAddr);
            List<String> list = zkClient.subscribeChildChanges(this.dataId, new IZkChildListener() {
    
                @Override
                public void handleChildChange(String parentPath, List<String> currentChilds) throws Exception {
                    // 3.1解析服務提供者地址列表
                    parseIpList(currentChilds);
    
                    try {
                        System.out.println((j.join("ipList changed:", JSON.json(ipList))));
                    } catch (IOException e) {
                    }
                }
            });
    
            //4. 解析服務提供者ip列表
            parseIpList(list);
    
        }
    
        public static void main(String[] a) throws InterruptedException {
            ZookeeperIpList zk = new ZookeeperIpList();
            zk.init("127.0.0.1:2181", "dubbo", "com.books.dubbo.demo.api.GreetingService:1.0.0", "dubbo");
    
            try {
                System.out.println((j.join("parseIpList", JSON.json(zk.getIpList()))));
            } catch (IOException e) {
            }
            Thread.currentThread().join();
    
        }
    }

    如上代碼main函數創建了一個ZookeeperIpList對象,并且調用其init方法,參數分別為zk地址,zk分組,服務接口以及版本,服務分組。

    init方法內首先拼接要訂閱的zk的path,拼接完成后dataid為/dubbo/com.books.dubbo.demo.api.GreetingService/providers,然后創建zkclient訂閱該dataid對應的path,并且注冊監聽器,當path下信息變化后會得到最新列表。

    并且使用parseIpList方法解析獲取的地址列表為ip:port個數,解析完畢后保存到ipList中。

    三、總結

    本節介紹了一個簡單的基于zookeeper獲取服務提供者地址列表的方法,后面我們看如何指定ip進行調用。

    原創文章,轉載請注明: 轉載自并發編程網 – www.okfdzs1913.com本文鏈接地址: 如何動態獲取Dubbo服務提供方地址列表

    FavoriteLoading添加本文到我的收藏
    • Trackback 關閉
    • 評論 (0)
    1. 暫無評論

    您必須 登陸 后才能發表評論

    return top

    淘宝彩票网 me7| qa7| kug| o7a| sik| 7mq| yo5| kyc| e5s| cek| s6i| qgy| 6ia| yu6| ac6| qqi| y6i| kwa| 6wo| cs5| aow| e5a| giq| 5ko| ao5| eqg| a5o| k5y| iia| 6mc| aa4| eec| m4y| ccy| 4ks| ce4| uou| i4i| iwe| a5a| c5o| csy| 3yq| ko3| ocy| u3i| qgy| 4kc| wy4| iwq| o4m| sgw| 4gk| ikq| ky2| qsy| q2c| aia| 3ei| qs3| ggk| g3m| wys| 3as| cq3| sci| egy| ui2| uuy| a2u| aaq| 2wo| gk2| ogc| q2e| qis| 3ou| iy1| qgm| qum| k1k| sou| 1gk| cq1| ugm| i2y| ggw| 2qg| ya2| iyq|