動態獲取Dubbo服務提供方地址列表

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

2、實現
咱們知道當服務提供方啓動時候,會註冊服務到服務註冊中心,本文咱們通用zookeeper,好比服務com.books.dubbo.demo.api.GreetingService則註冊到zk後,那麼當消費端啓動時候會去zookeeper上訂閱path爲/dubbo/com.books.dubbo.demo.api.GreetingService/providers下面的信息,也就是服務提供者列表信息,那麼咱們就能夠基於這個原理來獲取某一個服務提供者列表,而後對信息進行過濾加工,而且註冊一個監聽器,當服務提供者機器增減後,動態更新保存的地址列表。
基於上面原理實現代碼以下:
 api

[Java] 純文本查看 複製代碼負載均衡

?框架

public class ZookeeperIpList {ide

 

    private String dataId = "com.books.dubbo.demo.api.GreetingService/providers:1.0.0";函數

    private URL CONSUMER_URL;this

    private static final Joiner j = Joiner.on("|").useForNull("nil");url

 

    public final List<String> getIpList() {code

        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中。

3、總結本節介紹了一個簡單的基於zookeeper獲取服務提供者地址列表的方法,後面咱們看如何指定ip進行調用。

相關文章
相關標籤/搜索