`
LoveLZY
  • 浏览: 57484 次
  • 性别: Icon_minigender_1
博客专栏
Group-logo
从零编写RPC框架
浏览量:0
社区版块
存档分类
最新评论

dubbo源码研究之dubbo-registry模块

阅读更多
    dubbo-registry注册中心模块,基于注册中心下发地址的集群方式,以及对各种注册中心的抽象。
   registry模块顶层接口为RegistryService和NotifyListener以及一个工厂接口RegistryFactory。
   RegistryService接口包含4个方法。
   void register(URL url); 注册服务
   void unregister(URL url); 取消注册
   void subscribe(URL url, NotifyListener listener); 订阅服务(推)
   void unsubscribe(URL url, NotifyListener listener);取消订阅
   List<URL> lookup(URL url); 订阅服务(拉)
  
  Registry模块使用经典的消费者生成者模式,dubbo消费者订阅服务,dubbo服务者注册服务。
  AbstractRegistry为RegistryService接口实现的一个抽象类,提供一些默认实现。
 
    public AbstractRegistry(URL url) {
        setUrl(url);
        // 启动文件保存定时器
        syncSaveFile = url.getParameter(Constants.REGISTRY_FILESAVE_SYNC_KEY, false);
        String filename = url.getParameter(Constants.FILE_KEY, System.getProperty("user.home") + "/.dubbo/dubbo-registry-" + url.getHost() + ".cache");
        File file = null;
        if (ConfigUtils.isNotEmpty(filename)) {
            file = new File(filename);
            if(! file.exists() && file.getParentFile() != null && ! file.getParentFile().exists()){
                if(! file.getParentFile().mkdirs()){
                    throw new IllegalArgumentException("Invalid registry store file " + file + ", cause: Failed to create directory " + file.getParentFile() + "!");
                }
            }
        }
        this.file = file;
        loadProperties();
        notify(url.getBackupUrls());
    }


   可以看出AbstractRegistry类在构建的时候,会去本地磁盘文件读取文件,转成properties对象。文件默认路径是user.home/.dubbo/dubbo-registry-host.cache
   读取完之后会把这个url存到本地缓存文件里面去,但是该方法并非递增修改,而且是全部重写文件。
 
   public void doSaveProperties(long version) {
        if(version < lastCacheChanged.get()){
            return;
        }
        if (file == null) {
            return;
        }
        Properties newProperties = new Properties();
        // 保存之前先读取一遍,防止多个注册中心之间冲突
        InputStream in = null;
        try {
            if (file.exists()) {
                in = new FileInputStream(file);
                newProperties.load(in);
            }
        } catch (Throwable e) {
            logger.warn("Failed to load registry store file, cause: " + e.getMessage(), e);
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    logger.warn(e.getMessage(), e);
                }
            }
        }     
     // 保存
        try {
			newProperties.putAll(properties);
            File lockfile = new File(file.getAbsolutePath() + ".lock");
            if (!lockfile.exists()) {
            	lockfile.createNewFile();
            }
            RandomAccessFile raf = new RandomAccessFile(lockfile, "rw");
            try {
                FileChannel channel = raf.getChannel();
                try {
                    FileLock lock = channel.tryLock();
                	if (lock == null) {
                        throw new IOException("Can not lock the registry cache file " + file.getAbsolutePath() + ", ignore and retry later, maybe multi java process use the file, please config: dubbo.registry.file=xxx.properties");
                    }
                	// 保存
                    try {
                    	if (! file.exists()) {
                            file.createNewFile();
                        }
                        FileOutputStream outputFile = new FileOutputStream(file);  
                        try {
                            newProperties.store(outputFile, "Dubbo Registry Cache");
                        } finally {
                        	outputFile.close();
                        }
                    } finally {
                    	lock.release();
                    }
                } finally {
                    channel.close();
                }
            } finally {
                raf.close();
            }
        } catch (Throwable e) {
            if (version < lastCacheChanged.get()) {
                return;
            } else {
                registryCacheExecutor.execute(new SaveProperties(lastCacheChanged.incrementAndGet()));
            }
            logger.warn("Failed to save registry store file, cause: " + e.getMessage(), e);
        }
    }




  如果是两个不同的注册中心,不能使用一个缓存文件。
  值得注意一点的是,多个dubbo服务公用一个cache文件的时候,如果一起启动,可能会出现Failed to load registry store File 这类异常信息,这是因为当时该文件其他服务占用了。这种情况开发环境比较多,可以无视掉。因为会重复去注册的,下面会说明,但是尽量还是手动指定注册缓存文件比较好。尽量不使用同一个缓存文件。
 
<dubbo:registry address="${zookeeper.address}" file=".cache/dubbo-registry-car.cache" />

这样指定的话,缓存文件会在当前工程目录下。
RegistryService接口的所有方法参数都有URL对象,说明dubbo服务最终是转成URL来注册的。通过URL来表示服务的全部信息。
FailbackRegistry是AbstractRegistry类的子类,通过模式设计模式扩展,重写了AbstractRegistry类一些实现,并新增模板方法,交个子类去实现。
  public FailbackRegistry(URL url) {
        super(url);
        int retryPeriod = url.getParameter(Constants.REGISTRY_RETRY_PERIOD_KEY, Constants.DEFAULT_REGISTRY_RETRY_PERIOD);
        this.retryFuture = retryExecutor.scheduleWithFixedDelay(new Runnable() {
            public void run() {
                // 检测并连接注册中心
                try {
                    retry();
                } catch (Throwable t) { // 防御性容错
                    logger.error("Unexpected error occur at failed retry, cause: " + t.getMessage(), t);
                }
            }
        }, retryPeriod, retryPeriod, TimeUnit.MILLISECONDS);
    }


  FailbackRegistry构建的时候通过ScheduledExecutorService来延迟执行连接注册中心,默认延迟周期为5秒。
  其中retry()方法从set集合里面取出注册失败的url,然后不断去重新注册。如果注册中心当机了,但是只要注册中心重新启动之后,dubbo还是会去重新注册的。
 
   @Override
    public void register(URL url) {
        super.register(url);
        failedRegistered.remove(url);
        failedUnregistered.remove(url);
        try {
            // 向服务器端发送注册请求
            doRegister(url);
        } catch (Exception e) {
            Throwable t = e;

            // 如果开启了启动时检测,则直接抛出异常
            boolean check = getUrl().getParameter(Constants.CHECK_KEY, true)
                    && url.getParameter(Constants.CHECK_KEY, true)
                    && ! Constants.CONSUMER_PROTOCOL.equals(url.getProtocol());
            boolean skipFailback = t instanceof SkipFailbackWrapperException;
            if (check || skipFailback) {
                if(skipFailback) {
                    t = t.getCause();
                }
                throw new IllegalStateException("Failed to register " + url + " to registry " + getUrl().getAddress() + ", cause: " + t.getMessage(), t);
            } else {
                logger.error("Failed to register " + url + ", waiting for retry, cause: " + t.getMessage(), t);
            }

            // 将失败的注册请求记录到失败列表,定时重试
            failedRegistered.add(url);
        }
    }

  register方法把具体的注册实现交给子类的doRegister实现。注册失败的都会记录到失败的set集合里面去,值得注意一个check 配置,当设置<dubbo:registry check="false" />时,记录失败注册和订阅请求,后台定时重试。
  zookeeper注册中心是dubbo推荐使用的注册中心,本身zookeeper的基于是Paxos,一个分布式一致性算法。
 

  流程:
1.服务提供者启动时向/dubbo/com.foo.BarService/providers目录下写入URL
2.服务消费者启动时订阅/dubbo/com.foo.BarService/providers目录下的URL向/dubbo/com.foo.BarService/consumers目录下写入自己的URL
3.监控中心启动时订阅/dubbo/com.foo.BarService目录下的所有提供者和消费者URL
  dubbo如何通过注册中心来实现服务治理,则下篇文章博文单独讲解。


 

  • 大小: 109.5 KB
0
0
分享到:
评论

相关推荐

    dubbo源码包

    包含dubbo源码 dubbo-admin-2.4.3-sources.jar dubbo-demo-consumer-2.4.3-sources.jar dubbo-demo-provider-2.4.3-sources.jar dubbo-monitor-simple-2.4.3-sources.jar dubbo-registry-simple-2.4.3-sources....

    Dubbo源码以及所需jar文件

    Dubbo是中国阿里巴巴公司开源的一款高性能、轻量级的Java服务治理框架,它主要为企业级分布式应用提供服务调用、负载均衡、服务注册与发现、流量控制、熔断等核心功能。在深入理解Dubbo之前,我们需要先了解一些基础...

    dubbo源码解析2

    ### Dubbo源码解析2 #### 一、源码阅读路径 在开始深入解析Dubbo源码之前,首先需要明确的是,Dubbo虽然代码量不算庞大,但是它涉及的技术领域非常广泛,对于初学者来说,可能需要具备一定的前置知识才能更好地...

    alibaba-dubbo-dubbo-2.5.7-0-ge2d63ad.tar.gz

    《阿里巴巴Dubbo 2.5.7源码分析与应用》 阿里巴巴的Dubbo是一款高性能、轻量级的开源Java RPC框架,它提供了服务发现、服务治理、流量控制等一系列完整的服务解决方案。本压缩包"alibaba-dubbo-dubbo-2.5.7-0-ge2d...

    dubbo-monitor-simple-2.5.8

    在服务提供者和消费者端,需要在`dubbo.properties`或XML配置中设置`registry.monitor`属性,指向`dubbo-monitor-simple`的地址。用户可以通过浏览器访问监控页面,查看服务调用的统计图表,以及详细的服务信息。 ...

    一.dubbox(dangdang V2.8.4)+springBoot(1.4.2.RELEASE)+dubbo-monitor-web 监控项目源码

    7. **源码解析**:深入研究dubbox和springBoot的源码,理解它们的工作原理,这对于优化服务性能和解决故障至关重要。 8. **实战演练**:通过实际操作,如搭建环境、编写服务提供者和消费者、配置监控中心,将理论...

    dubbo-spring-boot-autoconfigure-2.7.8.zip

    `dubbo-spring-boot-autoconfigure`模块中的`DubboAutoConfiguration`类就是实现这一功能的关键,它会根据项目中的依赖和配置自动创建并注册Dubbo相关的Bean,如Service、Reference、Registry等。 3. **服务提供者...

    dubbo源码解析2.0.7z

    《Dubbo源码解析2.0》是一份深入剖析阿里巴巴开源框架Dubbo核心机制的资料,专注于2.0版本的源代码分析。Dubbo作为Java领域最知名的分布式服务框架之一,其设计理念、实现原理以及在实际应用中的优化策略都是开发者...

    dubbo2.0源码解读

    了解Dubbo源码通常从其主要模块入手,如服务提供者(Provider)、服务消费者(Consumer)、注册中心(Registry)、协议层(Protocol)等。通过跟踪调用流程,理解服务发布、订阅、调用过程。 2. **Dubbo诞生的背景*...

    dubbo2.5.7 源码包

    《Dubbo 2.5.7 源码解析与技术探索》 Dubbo,作为阿里巴巴开源的一款高性能、轻量级的服务治理框架,为分布式应用提供了丰富的服务调用、负载均衡、容错处理等能力。这里我们将深入探讨Dubbo 2.5.7版本的源码,了解...

    dubbo源码解析 1 pdf2.0

    在阅读Dubbo源码时,作者建议从简单的例子和模块入手,逐步深入到更复杂的机制和原理中去。在分析过程中,应不断地回顾和联系前面提到的预备知识点,这样才能在理解源码的同时,也能够学习到更广泛的知识和技能。 ...

    dubbo2.5.5源码

    这部分源码主要位于`dubbo-registry-zookeeper`模块,涉及到`RegistryFactory`、`Registry`、`RegistryService`等接口和实现类。 2. **服务调用**:Dubbo支持多种协议,如RPC(Remote Procedure Call)、HTTP等。...

    dubbo源码解析

    13. Refer&export过程分析:研究了Dubbo中服务的暴露(export)和引用(refer)的流程,包括调用顺序、生成Invoker的过程、Registry的使用等。 14. 集群和容错处理:描述了Dubbo中的集群机制,包括路由服务、负载...

    github上下载dubbo2.5.4源码下载后将dubbo-admin按jdk1.6,1.7,1.8编译后的war包

    在本案例中,你下载的是Dubbo 2.5.4版本的源代码,并且已经根据Java的不同版本(JDK 1.6,1.7,1.8)编译了dubbo-admin模块,生成了对应的WAR包。dubbo-admin是Dubbo的管理控制台,用于提供服务监控和管理功能。 ...

    dubbo源码分享,可打包创建可视页面

    dubbo源码,打成war包后,将此war放入本地tomcat&gt;webapps目录下,启动tomcat(/bin/startup.bat) 为了防止端口占用,可以再/conf/server.xml 修改tomcat端口,我的是8088 tomcat自解压 如图这里写图片描述 打开...

    dubbo源码解析2.01.pdf

    ### Dubbo源码解析知识点概览 #### 一、Dubbo简介与背景 - **背景**:Apache Dubbo是一款高性能、轻量级的开源服务框架,致力于提供高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案。Dubbo版本2.01在...

    dubbo-monitor-simple-2.5.10-assembly.tar.gz

    dubbo-monitor-simple的源码分析有助于深入理解其实现原理。其主要由以下几个部分组成: 1. **Controller层**:处理HTTP请求,提供RESTful API,如`/services`用于获取所有服务信息,`/statistics`用于获取调用统计...

    dubbo2.5.3GA 全套源码和jar

    深入研究Dubbo 2.5.3的源码,可以帮助我们了解分布式服务治理的底层实现,包括服务发现、负载均衡算法、故障转移策略等。这对于提升个人的分布式系统设计和优化能力具有重要意义。 总结,Dubbo 2.5.3 GA版本是理解...

Global site tag (gtag.js) - Google Analytics