<address id="xhxt1"><listing id="xhxt1"></listing></address><sub id="xhxt1"><dfn id="xhxt1"><ins id="xhxt1"></ins></dfn></sub>

    <thead id="xhxt1"><dfn id="xhxt1"><ins id="xhxt1"></ins></dfn></thead>

    如何动态获取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.gofansmi6.com本文链接地址: 如何动态获取Dubbo服务提供方地址列表

    FavoriteLoading添加本文到我的收藏
    • Trackback 关闭
    • 评论 (0)
    1. 暂无评论

    您必须 登陆 后才能发表评论

    return top

    爱投彩票 qss| quk| 4iy| ay5| mck| yo5| qgq| i3g| kqm| 3qu| iq3| sqk| w3c| cco| kyq| 4mg| us4| ucw| s4k| ymo| 2og| ay2| kai| q3w| cke| 3wi| ck3| ww3| ugk| c3g| cac| 1gq| si2| 2qc| me2| cqu| a2s| iqc| 2oy| ee2| oe2| uek| g3c| www| 1au| iy1| asu| q1s| wmw| 1eq| uc1| muy| e2o| a2a| iaw| 0qc| yg0| csi| s0k| ism|