Dubbo源码(4)-Zookeeper注册中心源码解析

精尽 Dubbo 源码分析 —— Zookeeper 客户端 1.概述 在 dubbo-remoting-zookeeper 模块,实现了 Dubbo 对 Zookeeper 客户端的封装。在该模块中,抽象了通用的 Zookeeper Client API 接口,实现了两种 Zookeeper Client 库的接入: 基于 Apache Curator 实现: <dubbo:registry address=“zookeeper://127.0.0.... 阅读详情

本文主要参考自Dubbo官方文档、Dubbo项目源码以及网络文章和相关书籍,并附上自身的一些理解,如有遗漏或错误,还望海涵并指出。谢谢!

------本文基于Dubbo-2.6.1版本

一、Zookeeper在Dubbo中的作用

Dubbo源码(3)-基础抽象注册中心源码解析已经讲了注册中心抽象API的实现。

可以看到FailbackRegistry基于AbstractRegistry已经实现了失败重试的逻辑,最后和注册中心交互、写入、删除、查询的逻辑都使用模板方法模式将指定的方法下放给具体注册中心实现类来完成,这也是本章要说的重点。本章是对Zookeeper注册中心的解析,当然了,整个Dubbo注册中心体系下共有4个注册中心:

在这里插入图片描述

1.1、什么是Zookeeper

首先简单介绍一下,什么是Zookeeper?

我认为Zookeeper可以理解为一个分布式的数据管理系统,每个zk都采用类似于Linux的树状结构来管理文件,基于此可以构建出类似于服务注册、状态管理、集群管理等相关的应用来。

为什么选择zk作为注册中心呢,我认为有以下好处:

  • 集群化配置方便,具备良好高可用性
  • 根据ZAB算法做Leader选举,实时性高
  • 整个zk集群能保证对外数据一致性
  • 整个zk集群能保证数据的集群原子性

当然了,也可以使用Redis作为注册中心,并且Redis能够做到更快、读写效率更高;以CAP模型来看,Redis保证的是AP模型,也就是先保证可用性,但不保证数据的强一致性(只保证最终一致性),更加适合于作高速读写缓存;而zk保证的是CP模型,也就是先保证一致性,网络分区发生时有可能不对外提供服务。

具体选择Redis还是zk作为注册中心,还是要看具体情境,不过大部分情况下选择zk都是合适的。

1.2、Dubbo的Zookeeper注册中心

在这里插入图片描述

  • 若Provider提供了com.foo.BarService这个接口的服务,那么在Provider启动时,会向 zk的/dubbo/com.foo.BarService/providers 目录下写入接口暴露出的URL地址10.20.153.10:20880

  • 当Consumer启动时,会订阅zk的 /dubbo/com.foo.BarService/providers 目录下的Provider暴露的URL地址。并向 /dubbo/com.foo.BarService/consumers 目录下写入自己的URL地址

  • 当Monitor启动时,会订阅zk /dubbo/com.foo.BarService
    目录下的所有Provider和Consumer的URL地址。

以上就是以zk作为注册中心的使用,具体的使用细节以及配置参考官方文档:

https://dubbo.apache.org/zh-cn/docs/user/references/registry/zookeeper.html

二、Zookeeper注册中心源码解析

现在就是Zookeeper注册中心的源码解析环节了,先来看看大致的情况:

Zookeeper注册中心的实现位于dubbo-registry模块下的dubbo-registry-zookeeper子模块:

在这里插入图片描述

查看SPI文件,可知zookeeper是RegistryFactory的默认拓展实现:

zookeeper=com.alibaba.dubbo.registry.zookeeper.ZookeeperRegistryFactory

代码量统计:

在这里插入图片描述

2.1、FailbackRegistry

这里就不贴具体代码了,主要是想提一下这里的模板方法模式:

public void register(URL url) {
        // ...
        try {
            // !!doXxxx方法交由子类实现!!
            doRegister(url);
        } catch (Exception e) {
            // ...
        }
    }
2.2、ZookeeperRegistryFactory

com.alibaba.dubbo.registry.zookeeper.ZookeeperRegistryFactory实现了AbstractRegistryFactory抽象类,是ZookeeperRegistry的工厂。

  • ZookeeperTransporter
// 默认以curator作为zk客户端
@SPI("curator")
public interface ZookeeperTransporter {

    @Adaptive({Constants.CLIENT_KEY, Constants.TRANSPORTER_KEY})
    ZookeeperClient connect(URL url);

}
  • ZookeeperRegistryFactory
public class ZookeeperRegistryFactory extends AbstractRegistryFactory {
    // zk客户端
    private ZookeeperTransporter zookeeperTransporter;
    // 设置zk客户端
    public void setZookeeperTransporter(ZookeeperTransporter zookeeperTransporter) {
        this.zookeeperTransporter = zookeeperTransporter;
    }
    // 创建ZookeeperRegistry
    public Registry createRegistry(URL url) {
        return new ZookeeperRegistry(url, zookeeperTransporter);
    }
}
2.3、ZookeeperRegistry

接下来就是本章的重点解析对象了,com.alibaba.dubbo.registry.zookeeper.ZookeeperRegistry 也就是真正的zk注册中心实现类,继承于FailbackRegistry。从属性及构造方法、重点方法这两个维度来看源码:

2.3.1、属性及构造方法
    // logger
    private final static Logger logger = LoggerFactory.getLogger(ZookeeperRegistry.class);
    // 默认zk端口号
    private final static int DEFAULT_ZOOKEEPER_PORT = 2181;
    // 默认zk根节点
    private final static String DEFAULT_ROOT = "dubbo";
    // zk根节点
    private final String root;
    // Service接口全名集合
    private final Set<String> anyServices = new ConcurrentHashSet<String>();
    //监听器集合
    private final ConcurrentMap<URL, ConcurrentMap<NotifyListener, ChildListener>> zkListeners = new ConcurrentHashMap<URL, ConcurrentMap<NotifyListener, ChildListener>>();
    // zk客户端
    private final ZookeeperClient zkClient;

    /*
    *   URL:当前Registry的URL
    *   ZookeeperTransporter:指定zk客户端(默认为curator)
     */
    public ZookeeperRegistry(URL url, ZookeeperTransporter zookeeperTransporter) {
        super(url);
        if (url.isAnyHost()) {
            throw new IllegalStateException("registry address == null");
        }
        // 获取到zk根结点
        String group = url.getParameter(Constants.GROUP_KEY, DEFAULT_ROOT);
        if (!group.startsWith(Constants.PATH_SEPARATOR)) {
            // 设置为自定义zk根结点
            group = Constants.PATH_SEPARATOR + group;
        }
        // 设置为自定义zk根结点
        this.root = group;
        // 连接到指定的zk
        zkClient = zookeeperTransporter.connect(url);
        zkClient.addStateListener(new StateListener() {
            public void stateChanged(int state) {
                if (state == RECONNECTED) {
                    try {
                        // 断线重连zk时恢复自身数据
                        recover();
                    } catch (Exception e) {
                        logger.error(e.getMessage(), e);
                    }
                }
            }
        });
    }
2.3.2、重点方法
2.3.2.1、doRegister
  • doRegister
    /*
    *   注册url到zk中
     */
    protected void doRegister(URL url) {
        try {
            // 创建Root+Service+Type+Url的zk节点
            // toUrlPath:获取到Root + Service + Type + URL
            zkClient.create(toUrlPath(url), url.getParameter(Constants.DYNAMIC_KEY, true));
        } catch (Throwable e) {
            throw new RpcException("Failed to register " + url + " to zookeeper " + getUrl() + ", cause: " + e.getMessage(), e);
        }
    }
  • toUrlPath
    /*
    *   获取到Root + Service + Type + URL
     */
    private String toUrlPath(URL url) {
        return toCategoryPath(url) + Constants.PATH_SEPARATOR + URL.encode(url.toFullString());
    }
  • toCategoryPath
    /*
    *   获取到Root + Service + Type
     */
    private String toCategoryPath(URL url) {
        return toServicePath(url) + Constants.PATH_SEPARATOR + url.getParameter(Constants.CATEGORY_KEY, Constants.DEFAULT_CATEGORY);
    }
  • toServicePath
    /*
    *   获取到Root + Service
     */
    private String toServicePath(URL url) {
        String name = url.getServiceInterface();
        if (Constants.ANY_VALUE.equals(name)) {
            return toRootPath();
        }
        return toRootDir() + URL.encode(name);
    }
  • toRootDir
    /*
    *   获取到Root
     */
    private String toRootDir() {
        if (root.equals(Constants.PATH_SEPARATOR)) {
            return root;
        }
        return root + Constants.PATH_SEPARATOR;
    }

   
    private String toRootPath() {
        return root;
    }
2.3.2.2、doUnregister
 /*
    *   取消注册,删除该Root+Service+Type+Url的zk节点
     */
    protected void doUnregister(URL url) {
        try {
            zkClient.delete(toUrlPath(url));
        } catch (Throwable e) {
            throw new RpcException("Failed to unregister " + url + " to zookeeper " + getUrl() + ", cause: " + e.getMessage(), e);
        }
    }
2.3.2.3、doSubscribe
@Override
protected void doSubscribe(final URL url, final NotifyListener listener) {
    try {
        // 处理所有Service层的发起订阅,例如监控中心的订阅
        if (Constants.ANY_VALUE.equals(url.getServiceInterface())) {
            String root = toRootPath();
            // 获得url对应的监听器集合
            ConcurrentMap<NotifyListener, ChildListener> listeners = zkListeners.get(url);
            if (listeners == null) { // 不存在,进行创建
                 zkListeners.putIfAbsent(url, new ConcurrentHashMap<NotifyListener, ChildListener>());
                 listeners = zkListeners.get(url);// 获得 ChildListener ChildListener zkListener = listeners.get(listener)if (zkListener == null) { // 不存在ChildListener 对象,进行创建ChildListener对象
                 listeners.putIfAbsent(listener, new ChildListener() public void childChanged(String parentPath, List<String> currentChilds) { for (String child : currentChilds) {
                     child = URL.decode(child);
                     if (!anyServices.contains(child)) {
                                anyServices.add(child);
                                subscribe(url.setPath(child).addParameters(Constants.INTERFACE_KEY, child,
                                        Constants.CHECK_KEY, String.valueOf(false)), listener);
                            }
                 }
                    }
        });
                zkListener = listeners.get(listener);
            }
            // 创建 Service 节点。该节点为持久节点。
            zkClient.create(root, false);
            // 向 Zookeeper ,Service 节点,发起订阅
            List<String> services = zkClient.addChildListener(root, zkListener);
            // 首次全量数据获取完成时,循环 Service 接口全名数组,发起该 Service 层的订阅
            if (services != null && !services.isEmpty()) {
                for (String service : services) {
                 service = URL.decode(service);
                    anyServices.add(service);
                    subscribe(url.setPath(service).addParameters(Constants.INTERFACE_KEY, service,
                            Constants.CHECK_KEY, String.valueOf(false)), listener);
                }
            }
        // 处理指定 Service 层的发起订阅,例如服务消费者的订阅
        } else {
            // 子节点数据数组
            List<URL> urls = new ArrayList<URL>();
            // 循环分类数组
            for (String path : toCategoriesPath(url)) {
                // 获得 url 对应的监听器集合
                ConcurrentMap<NotifyListener, ChildListener> listeners = zkListeners.get(url);
                if (listeners == null) { // 不存在,进行创建
                    zkListeners.putIfAbsent(url, new ConcurrentHashMap<NotifyListener, ChildListener>());
                    listeners = zkListeners.get(url);
                }
                // 获得ChildListener对象
                ChildListener zkListener = listeners.get(listener);
                if (zkListener == null) { // 不存在 ChildListener 对象,进行创建ChildListener对象
                    listeners.putIfAbsent(listener, new ChildListener() {
                        public void childChanged(String parentPath, List<String> currentChilds) {
                            // 出现变更,回调NotifyListener
                            ZookeeperRegistry.this.notify(url, listener, toUrlsWithEmpty(url, parentPath, currentChilds));
                        }
                    });
                    zkListener = listeners.get(listener);
                }
                // 创建Type节点。该节点为持久节点。
                zkClient.create(path, false);
                // 向Zookeeper ,PATH节点,发起订阅
               List<String> children = zkClient.addChildListener(path, zkListener);
                // 添加到urls 中
                if (children != null) {
                    urls.addAll(toUrlsWithEmpty(url, path, children));
                }
            }
            // 首次全量数据获取完成时,调用notify方法,回调 NotifyListener
            notify(url, listener, urls);
        }
    } catch (Throwable e) {
        throw new RpcException("Failed to subscribe " + url + " to zookeeper " + getUrl() + ", cause: " + e.getMessage(), e);
    }
}
2.3.2.4、doUnsubscribe
@Override
protected void doUnsubscribe(URL url, NotifyListener listener) {
    ConcurrentMap<NotifyListener, ChildListener> listeners = zkListeners.get(url);
    if (listeners != null) {
        ChildListener zkListener = listeners.get(listener);
        if (zkListener != null) {
            // 通知zk ,移除订阅
            zkClient.removeChildListener(toUrlPath(url), zkListener);
        }
    }
}
Dubbo源码解析:注册中心 介绍 Dubbo可以用zookeeper,reids,nacos来实现注册中心 Registry继承了RegistryService接口,RegistryService接口定义了对注册中心的基本操作 public interface RegistryService { // 注册 void register(URL url); // 注销 void unregister(URL url); // 订阅 void subscribe(URL url, No 阅读详情

相关推荐

Dubbo:Unsubscribe consumer问题解决

系统更新升级的时候遇到 Dubbo:Unsubscribe consumer 的提示,导致系统无法正常启动,相信有部分朋友遇到过。本文介绍了一种解决这个问题的方法。

qq_46119575的博客 912

单点DToF激光测距传感器各家产品的比较

汇总DToF 单点测距传感器的相关信息

Linux 设备驱动概述及开发环境构建 (一) 1775

Zookeeper源码分析

一、算法基础 Zookeeper 是如何保证数据一致性的? 1.1 拜占庭将军问题 拜占庭将军问题是一个协议问题,拜占庭帝国军队的将军们必须全体一致的决定是否攻击某一支敌军。问题是这些将军在地理上是分隔开来的,并且将军中存在叛徒。 叛徒可以任意行动以达到以下目标:欺骗某些将军采取进攻行动;促成一个不是所有将军都同意的决定,如当将军们不希望进攻时促成进攻行动;或者迷惑某些将军,使他们无法做出决定。 如果叛徒达到了这些目的之一,则任何攻击行动的结果都是注定要失败的,只有完全达成一致的努力才能获得胜利。 1.2

cosuyo的博客 1439

Simplorer-Maxwell联合仿真速度太慢?我用这3个技巧把仿真时间砍半(附SVPWM周期与步长设置避坑)

本文详细介绍了Simplorer-Maxwell联合仿真性能优化的3个关键技巧,包括仿真步长与周期的科学配置、基于任务调度的加速技术以及模型简化与精度平衡。特别针对SVPWM参数设置提供了避坑指南,帮助工程师在不牺牲精度的情况下将仿真时间缩短50%以上,适用于电机驱动系统开发等场景。

weixin_29189381的博客 466

在昇腾910B上,用kubeadm快速拉起一个双节点K8s集群(保姆级避坑指南)

本文详细介绍了在昇腾910B服务器上使用kubeadm快速搭建双节点Kubernetes集群的完整流程,包括环境准备、容器运行时配置、kubeadm初始化、节点加入与网络插件部署等关键步骤,特别针对ARM架构和昇腾芯片提供了优化配置和避坑指南。

weixin_29204749的博客 247

Dubbo使用zookeeper原理

dubbo有服务提供者和消费者,二者都会向zookeeper注册,那么他们两个向zookeeper注册了什么,又起到什么作用呢? 服务提供者向zookeeper注册了什么? 在服务启动时,会调用到一个方法: org.apache.dubbo.registry.zookeeper.ZookeeperRegistry#doRegister @Override public void doRegister(URL url) { try { check

诗人不写诗 395

Deep Reinforcement Learning - 1. DDPG原理和算法

Deep Reinforcement Learning - 1. DDPG原理和算法 背景描述 DDPG的定义和应用场景 DDPG算法相关基本概念定义 DDPG实现框架和算法 DDPG对于DPG的关键改进 下一篇 以下用RL作为Reinforcement Learning 的简称。背景描述概括来说,RL要解决的问

kenneth_yu的博客 14万+

学习笔记---注册中心zookeeper客户端源码简单分析

11

u014461495的博客 242

别让运放自激振荡!手把手教你用波特图分析反相放大电路的稳定性(附LTspice仿真)

本文详细解析了运算放大器在反相放大电路中的稳定性问题,通过波特图分析和LTspice仿真,揭示了自激振荡的成因及解决方案。文章从故障现象识别到数学工具应用,再到实战仿真和工程优化,提供了一套完整的稳定性分析工具链,帮助工程师有效避免运放自激振荡问题。

weixin_31682031的博客 303

【异常】OpenClaw LLM请求超时故障全链路排查与解决方案 LLM request timed out. 网络连接超时了

摘要: OpenClaw LLM请求超时故障是高频网络交互问题,表现为客户端在预设时间内未收到服务端响应。根因分为四类:客户端配置缺陷(如超时阈值不合理)、网络链路异常(防火墙拦截等)、服务端问题(限流/宕机)及硬件瓶颈(算力不足)。解决方案分三步: 通用排查:检查网络连通性、关闭防火墙/代理校验,调整超时阈值至60-300秒; 分场景修复:云端API需核对密钥/限流规则,本地部署需验证服务状态与硬件资源; 兜底方案:重启程序、更新版本或更换服务端点,结合日志精准定位。修复后不影响OpenClaw数据完整性

奶爸的编程之路,也就一周冷个三天 2058

从源码全面解析 dubbo 服务订阅的来龙去脉

对于 Java 开发者而言,关于 dubbo ,我们一般当做黑盒来进行使用,不需要去打开这个黑盒。但随着目前程序员行业的发展,我们有必要打开这个黑盒,去探索其中的奥妙。本期 dubbo 源码解析系列文章,将带你领略 dubbo 源码的奥秘。本期源码文章吸收了之前 Spring、Kakfa、JUC源码文章的教训,将不再一行一行的带大家分析源码,我们将一些不重要的部分当做黑盒处理,以便我们更快、更有效的阅读源码。虽然现在是互联网寒冬,但乾坤未定,你我皆是黑马!

爱敲代码的小黄 2371

华为OD机试 - 小扇和小船的数字游戏 - 二进制(Python/JS/C/C++ 2024 C卷 200分)

二进制表示:任何数 n 的二进制表示中,要找到下一个有相同数量的1的数,我们需要在最低位的0后面的最低位的1进行操作。右侧交换法则:找到右侧的第一个0,位于第一个1的左边,将这个0变成1(提升这个位),并将这个1变成0(下移这个位)。调整尾部1:为了得到最小的数,将所有低于已交换的1的位重置,使得所有1尽可能靠右。

学Java,找哪吒 1162

深度解析dubbo注册中心zookeeper实现

本文基于dubbo 2.6.x 文章目录一、ZookeeperRegistryFactory二、ZookeeperRegistry2.1 class与成员变量2.2 构造2.3 doRegister2.4 doUnregister2.5 doSubscribe2.6 doUnsubscribe三、总结 一、ZookeeperRegistryFactory ZookeeperRegistryFactory是注册中心zookeeper工厂的实现,代码比较简单,我们直接来看下。 可以看到ZookeeperRe

猿上生活 1813

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

Dubbo——注册中心(zookeeper)原理

摘要 因为dubbo是一个分布式的RPC开源框架,各个服务之间单独部署,就会出现资源之间不一致的问题。而zookeeper就有保证分布式一致性的特性。ZooKeeper是一种为分布式应用所设计的高可用、高性能且一致的开源协调服务。zookeeper采用的是树形结构来组织数据节点,它类似于一个标准的文件系统。 该图是官方文档里面的一张图,展示了dubbo在zookeeper中存储的形式以及节点层级, dubbo的Root层是根目录,通过<dubbo:registry group="dubbo"

庄小焱 3080

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

Dubbo注册中心(ZooKeeper)

文章目录1. 注册中心概述2. 注册中心的工作流程3. 注册中心的原理3.1 ZooKeeper做注册中心的原理 1. 注册中心概述 在Dubbo微服务体系中,注册中心是其核心组件之一。Dubbo通过注册中心实现了分布式环境中各服务之间的注册与发现,是各个分布式节点之间的纽带。其主要作用如下: 动态加入(服务注册/暴露):一个服务提供者通过注册中心可以动态地把自己暴露给其他消费者,无须消费者逐个...

xingze的博客 1149

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

dubbo源码解析-zookeeper连接

Dubbo源码解析系列文章均来自肥朝简书 前言 上周的dubbo源码解析-远程暴露中讲解了远程暴露的大致过程,但是期间大家也发现了,这个过程涉及到了很多分支,比如netty,zookeeper.当然设计模式就不说了,这个贯穿在整个框架的始终. 但是我也认为,好的源码分析类文章,应该是先整体,后枝干的,就比如如果我们一开始学习HTML的时候先把各个标签过一遍,估计可能很多人还没入门就放弃了,比...

Franco的博客 469

Dubbo源码解析-Zookeeper注册中心解析

前言: 在多服务提供者的情况下,如果消费者需要获取一个特定的提供者来进行消费,则需要注册中心的帮助。 在Dubbo中,服务提供者启动时向注册中心注册当前provider_url,消费者在启动时也从注册中心中拉取当前接口的所有提供者信息,缓存到当前应用。 而当服务提供者发生变动时(新的提供者上线或者已有提供者下线),注册中心也会将变动消息推送到各个消费者,以实现注册信息的及时更新。 有关于注册中心,接口为Registry,Dubbo中提供的注册中心有如下: 本文就来看下Zookeepe.

恐龙弟旺仔的博客 1230

从源码全面解析 dubbo 注解配置的来龙去脉

对于 Java 开发者而言,关于 dubbo ,我们一般当做黑盒来进行使用,不需要去打开这个黑盒。但随着目前程序员行业的发展,我们有必要打开这个黑盒,去探索其中的奥妙。本期 dubbo 源码解析系列文章,将带你领略 dubbo 源码的奥秘。本期源码文章吸收了之前 Spring、Kakfa、JUC源码文章的教训,将不再一行一行的带大家分析源码,我们将一些不重要的部分当做黑盒处理,以便我们更快、更有效的阅读源码。虽然现在是互联网寒冬,但乾坤未定,你我皆是黑马!

爱敲代码的小黄 2472

Dubbo源码分析之zookeeper注册中心

1.ZookeeperRegistryFactory com.alibaba.dubbo.registry.zookeeper.ZookeeperRegistryFactory,实现 AbstractRegistryFactory 抽象类,Zookeeper Registry 工厂。代码如下: public class ZookeeperRegistryFactory extend...

ChinaCR07的博客 509

Dubbo注册中心 Zookeeper原理与实现

Dubbo注册中心 Zookeeper原理与实现 点关注不迷路,欢迎再访! 精简博客内容,尽量已行业术语来分享。 努力做到对每一位认可自己的读者负责。 帮助别人的同时更是丰富自己的良机。 目录Dubbo注册中心 Zookeeper原理与实现一.Zookeeper原理介绍二.Zookeeper 的实现2.1 发布的实现2.2 订阅的实现 一.Zookeeper原理介绍 Zookeeper 是树形结构的注册中心,Dubbo使用zookeeper作为注册中心时,只会创建持久节点和临时节点两种,对创建

最初的节奏 1586

【021】Dubbo3从0到1系列之注册中心源码解析

本文解析了Dubbo注册中心的核心机制与源码实现。注册中心(Registry)作为微服务架构的关键组件,通过本地客户端与Zookeeper/Nacos等集群同步信息,实现服务提供者(Provider)和消费者(Consumer)的相互感知。源码分析显示,注册模块在Dubbo中相对独立,采用Node接口抽象各类节点(Provider/Consumer/注册中心节点),该接口定义了获取URL、检查可用性和销毁节点三个基础方法。

编程技术圈 905

Dubbo使用nacos作为注册中心原理剖析

Nacos是阿里自研的,一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台 。作为微服务注册中心,它的目标是淘汰目前流行的eureka,zookeeper等组件。现在学习它真的很有必要。这里就还是从源码的角度出发,看一下Spring Boot是如何和它整合的。 详细教程官网已经写的非常明确,这里就不多说了。 Nacos中文官方文档 下载nacos 项目版本:(目前真对spring-cl...

zhaodongchao的博客 1万+

dubbo启动之注册中心(Registry)

今天来分享下dubbo注册中心的大致结构服务注册对于服务提供方,它需要发布服务,而且由于应用系统的复杂性,服务的数量、类型也不断膨胀;对于服务消费方,它最关心如何获取到它所需要的服务,而面对复杂的应用系统,需要管理大量的服务调用。而且,对于服务提供方和服务消费方来说,他们还有可能兼具这两种角色,即既需要提供服务,有需要消费服务。通过将服务统一管理起来,可以有效地优化内部应用对服务发布/使用的流程和管理。服务注册中心可以通过特定协议来完成服务对外的统一Registry: 服务注册与发现的注册中心。...

m0_67403013的博客 2033

Apache Dubbo系列:ZooKeeper注册中心

在Dubbo微服务体系中,注册中心是核心组件之一。Dubbo通过注册中心实现分布式环境中各个服务之间的注册和发现,是各个节点间的纽带。 在微服务体系中,注册中心的作用如下: 服务动态加入。一个服务提供者可以通过注册中心动态的将自己暴露给各个服务消费方。 服务动态订阅。服务消费方可以通过注册中心,实时的感知新旧服务的上线与下线。 动态调整。注册中心支持参数的动态调整,新参数将自动更新到所有相关的节点中。 统一配置。提供统一的配置服务。 在Dubb...

nuoWei_SenLin的博客 676

DUBBO源码学习(二)注册中心源码解析

这里写自定义目录标题欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式新的甘特图功能,丰富你的文章UML 图表FLowchart流程图导出与导入导出导入 欢迎使用Markdown编辑器 你好! 这是你第一次使用 Markdown编辑器 所展示的欢迎页。如果你想学习如何使用Mar

lisyee的博客 1109
上一篇: Dubbo源码(3)-基础抽象注册中心源码解析
下一篇: Dubbo源码(5)-领域模型及调用流程
BoringRong
BoringRong 领域专家: 后端开发技术领域 领域专家: 后端开发技术领域
博客等级 码龄9年 2万+粉丝 386原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

BoringRong

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值