(EnableDiscoveryClient与EnableEurekaClient的区别(Edgware版本))

蹉跎莫遣韶光老,人生唯有读书好。这篇文章主要讲述:EnableDiscoveryClient与EnableEurekaClient的区别(Edgware版本)相关的知识,希望能为你提供帮助。
欢迎访问我的GitHub
本篇概览

  • 在基于SpringCloud做开发的时候,EnableDiscoveryClient和EnableEurekaClient这两个注解我们并不陌生,今天就来聊聊它们的区别,和网上更早期的类似文章不同的是:==本文会聊到Dalston之后的版本中,这两个注解的区别;==
Spring Cloud版本说明
  • 大致发展情况如下:
  • Angle -> Brixton -> Camden -> Dalston -> Edgware -> Finchley
文章概览
  • 全文由以下几部分组成,注意Dalston版本是个很重要的时间点,这之后的版本中EnableDiscoveryClient、EnableEurekaClient的作用发生了很大的变化,因此我们接下来的讨论都要先分清楚是Dalston版本之前还是之后:
    1. 问题的起源;
    2. 来自作者的权威答案(Dalston或更早期的版本);
    3. 官方文档(Dalston或更早期的版本);
    4. 看源码(Dalston或更早期的版本);
    5. Edgware版本中EnableEurekaClient的变化;
    6. Edgware版本官方文档对EnableDiscoveryClient的解释;
    7. 源码揭示EnableDiscoveryClient的变化;
    8. 一点遗留问题待确定;
    9. 小结;
问题的起源
  • 在使用Spring Cloud的Dalston版本或更早期的版本中,为了将应用发布到Eureka注册中心,我们会在配置类中增加@EnableDiscoveryClient或者@EnableEurekaClient注解,例如以下代码:
    package com.bolingcavalry.springclouddeepprovider;

【(EnableDiscoveryClient与EnableEurekaClient的区别(Edgware版本))】import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication@EnableDiscoveryClient
br/>@EnableDiscoveryClient
public static void main(String[] args) SpringApplication.run(SpringclouddeepproviderApplication.class, args);


- 于是就有了疑问:==EnableDiscoveryClient和EnableEurekaClient的区别和关系。==### 来自作者的权威答案(Dalston或更早期的版本) ==请注意,下面这段内容的背景是Spring Cloud的Dalston版本,或更早期的版本,这一点很重要!==- EnableDiscoveryClient和EnableEurekaClient的区别在网上有不少文章分析,但最权威的答案应该来自这两个类的作者==Spencer Gibb==,他在StackOverflow上有回复,地址是:https://stackoverflow.com/questions/31976236/whats-the-difference-between-enableeurekaclient-and-enablediscoveryclient ,内容如下图: ![这里写图片描述](https://s4.51cto.com/images/blog/202203/05191345_622345e9dc09863311.png?x-oss-process=image/watermark,size_14,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=)- 我的理解:注册发现服务有三种实现方式:eureka、consul、zookeeper,EnableDiscoveryClient注解在common包中,通过项目的classpath来决定使用哪种实现,而EnableEurekaClient注解在netflix包中,只会使用eureka这种实现方式;- 有两个时间点需要注意: 1. Spencer Gibb的这段话发表于2015年8月13日; 2. Spencer Gibb于2017年10月25日,在Spring官方博客宣布[Edgware.RC1版本发布](https://spring.io/blog/2017/10/25/spring-cloud-edgware-rc1-released),如下图,此时距离他在StackOverflow上那个回答已经过去了两年: ![这里写图片描述](https://s4.51cto.com/images/blog/202203/05191346_622345ea108b747682.jpg?x-oss-process=image/watermark,size_14,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=)- 因此,如果您使用的Spring Cloud版本是Edgware或者更新的版本,您在考虑EnableDiscoveryClient和EnableEurekaClient的区别时,Spencer Gibb在StackOverflow上的那个解释就未必准确了,因为您的版本距离他当时的版本已经有了两年以上的间隔;### 官方文档(Dalston或更早期的版本) - 在Spring官方博客,于2014年12月9日宣布Spring Cloud 1.0.0.RC1发布,地址是:https://spring.io/blog/2014/12/19/spring-cloud-1-0-0-rc1-available-now ,里面有段描述如下图红框所示: ![这里写图片描述](https://s4.51cto.com/images/blog/202203/05191345_622345e9ecf6928668.jpg?x-oss-process=image/watermark,size_14,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=)- 我对以上描述的理解: 1. 服务注册发现功能被抽象后放入spring-cloud-commons库,该库的EnableDiscoveryClient可以取代旧的EnableEurekaClient,使用注解EnableDiscoveryClient就能启用服务注册发现功能; 2. 同理,EnableHystrix也被EnableCircuitBreaker取代了;- 可见,从Spring Cloud 1.0.0.RC1版本开始,就已经不推荐使用EnableEurekaClient和EnableHystrix了;### 看源码(Dalston或更早期的版本) - 看一下Dalston版本的EnableEurekaClient源码: ```java @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @EnableDiscoveryClient public @interface EnableEurekaClient

  • 上述代码显示,EnableEurekaClient 中使用了EnableDiscoveryClient,因此,从使用者角度来看两者确实已经没有什么区别了,按照官方的建议使用EnableDiscoveryClient其实是个不错的选择;
Edgware版本中EnableEurekaClient的变化
  • 来看看Edgware版本中,EnableEurekaClient.java的内容:
    @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited public @interface EnableEurekaClient


- 如上所示,之前版本中的@EnableDiscoveryClient注解已经不存在了,而且也没有用到任何@Import注解,因此,==EnableEurekaClient这个注解已经没什么用处了==,在代码中用不用它,是没什么差别的;### Edgware版本官方文档对EnableDiscoveryClient的解释 - Dalston之后的第一个版本为Edgware,Spring官方博客在2017年10月25日宣布发布,一起来看看此版本的EnableEurekaClient和EnableDiscoveryClient的区别;- 首先还是看[官方博客](https://spring.io/blog/2017/10/25/spring-cloud-edgware-rc1-released),关键信息如下图: ![这里写图片描述](https://s4.51cto.com/images/blog/202203/05191345_622345e9d70e067618.png?x-oss-process=image/watermark,size_14,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=)- 我对以上内容的理解: 1. EnableDiscoveryClient注解现在是可选项了(你用不用这个注解,是不会影响服务注册发现功能的); 2. 只要依赖了以==spring-cloud-starter-netflix==为前缀的库(例如spring-cloud-starter-netflix-eureka-client),就启用了服务注册发现功能; 3. 使用配置项==spring.cloud.service-registry.auto-registration.enabled=false即可禁止服务注册发现功能==;- 从官方博客上看来EnableDiscoveryClient注解已经不会影响服务注册发现功能了;### 如何理解“@EnableDiscoveryClient is now optional”? - 既然注解@EnableDiscoveryClient用或者不用都不影响服务注册发现功能,那为什么官方文档将其描述为"is now optional"(可选项),为什么不直接废弃这个注解呢? - 从官方文档对EnableDiscoveryClient的描述,我们可以看个明白,如下图: ![这里写图片描述](https://s4.51cto.com/images/blog/202203/05191346_622345ea3688627825.jpg?x-oss-process=image/watermark,size_14,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=)- 上图是Edgware版本的开发文档,地址:http://cloud.spring.io/spring-cloud-static/Edgware.SR4/multi/multi__spring_cloud_commons_common_abstractions.html#__enablediscoveryclient- 从上图描述可以看出,spring容器在查询spring.factories的过程中,如果找到了EnableDiscoveryClient的配置,就会实例化该配置对应的服务注册发现:例如eureka、consul、zookeeper等;- 红框中提到,EnableDiscoveryClient不是必须的,只要classpath中存在DiscoveryClient的实现就可以保证将应用注册到注册中心了,这个功能是如何实现的,后面我们会分析到(和spring.factories有关);### 源码揭示EnableDiscoveryClient的变化 - 通过源码来确认官方文档的信息,这种方式可以加深对Spring Cloud的理解;- 寻找突破点: - 面对浩瀚的源码,如何下手呢?前面官方文档的那句话给了我们一个线索,如下图红框所示: ![这里写图片描述](https://s4.51cto.com/images/blog/202203/05191346_622345ea132e943045.png?x-oss-process=image/watermark,size_14,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=)- 只依赖以==spring-cloud-starter-netflix==为前缀的库(例如spring-cloud-starter-netflix-eureka-client),就启用了服务注册发现功能,这个特性让我想起了spring容器通过META-INF/spring.factories文件加载配置的能力;- 于是打开工程==spring-cloud-netflix-eureka-client==(Edgware版对应的该工程版本号为1.4.0.RELEASE),去看src\\main\\resources\\META-INF目录下的spring.factories文件,发现在springboot的自动配置项中,出现了一个关键配置==EurekaDiscoveryClientConfiguration==,如下图: ![这里写图片描述](https://s4.51cto.com/images/blog/202203/05191346_622345ea3263588628.png?x-oss-process=image/watermark,size_14,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=)- EurekaDiscoveryClientConfiguration负责启动实现服务注册发现功能,实现机制相对复杂,在此不展开细说了,看看部分源码如下: ![这里写图片描述](https://s4.51cto.com/images/blog/202203/05191346_622345ea3e07c41962.png?x-oss-process=image/watermark,size_14,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=)- 真相大白:服务注册发现功能是否启动,是由配置类EurekaDiscoveryClientConfiguration控制的,在Edgware版本中,如果开启了springboot的自动配置,那么EurekaDiscoveryClientConfiguration就会生效,因此不是靠EnableDiscoveryClient注解来控制了;- 现在我们对Edgware版本的服务注册发现已经有所了解,再去看看Dalston版本下的spring.factories,应该能有不少收获;- Dalston版的Spring Cloud,其spring-cloud-netflix-eureka-client工程的版本号为1.3.6.RELEASE,打开该工程下面的spring.factories文件,内容如下: ![这里写图片描述](https://s4.51cto.com/images/blog/202203/05191346_622345ea526ba81328.png?x-oss-process=image/watermark,size_14,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=)- 真相大白:在Dalston版本下,使用注解EnableDiscoveryClient才会使配置类EurekaDiscoveryClientConfiguration生效;### 一点遗留问题待确定 - 前面我们在Edgware和Dalston版本下分别打开spring-cloud-netflix-eureka-client工程的spring.factories,通过对比spring.factories,弄清楚了服务注册发现功能是如何启动的;- 但是似乎有个问题: 1. 在Edgware版本中,官方建议使用spring-cloud-netflix-eureka-client作为starter; 2. 在Dalston版本中,官方建议使用spring-cloud-starter-eureka作为start,也就是所我们的pom.xml中并没有出现spring-cloud-netflix-eureka-client;- 那么问题来了,如果Dalston版本中没有用到spring-cloud-netflix-eureka-client库,那么它的spring.factories自然也就不会生效,那我们刚才的分析岂不是无用了?- 除非是被pom.xml中的其他库间接依赖了,还是创建一个工程来验证一下吧;- 基于maven创建一个springboot工程,里面依赖了Spring Cloud的Dalston版本,pom.xml内容如下: ```xml < ?xml version="1.0" encoding="UTF-8"?> < project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> < modelVersion> 4.0.0< /modelVersion> < groupId> com.bolingcavalry< /groupId> < artifactId> springclouddeepprovider< /artifactId> < version> 0.0.1-SNAPSHOT< /version> < packaging> jar< /packaging> < name> springclouddeepprovider< /name> < description> Demo project for Spring Cloud service provider< /description> < parent> < groupId> org.springframework.boot< /groupId> < artifactId> spring-boot-starter-parent< /artifactId> < version> 1.5.9.RELEASE< /version> < /parent> < properties> < project.build.sourceEncoding> UTF-8< /project.build.sourceEncoding> < project.reporting.outputEncoding> UTF-8< /project.reporting.outputEncoding> < java.version> 1.8< /java.version> < /properties> < dependencies> < dependency> < groupId> org.springframework.boot< /groupId> < artifactId> spring-boot-starter-web< /artifactId> < /dependency> < dependency> < groupId> org.springframework.cloud< /groupId> < artifactId> spring-cloud-starter-eureka< /artifactId> < /dependency> < dependency> < groupId> org.springframework.boot< /groupId> < artifactId> spring-boot-starter-test< /artifactId> < scope> test< /scope> < /dependency> < /dependencies> < dependencyManagement> < dependencies> < dependency> < groupId> org.springframework.cloud< /groupId> < artifactId> spring-cloud-dependencies< /artifactId> < version> Dalston.SR5< /version> < type> pom< /type> < scope> import< /scope> < /dependency> < /dependencies> < /dependencyManagement> < build> < plugins> < plugin> < groupId> org.springframework.boot< /groupId> < artifactId> spring-boot-maven-plugin< /artifactId> < /plugin> < /plugins> < /build> < /project>

  • 注意starter用的是spring官方推荐的==spring-cloud-starter-eureka==,现在工程目录下执行命令==mvn dependency:tree==看依赖关系,如下图红框所示,spring-cloud-netflix-eureka-client被spring-cloud-starter-eureka间接依赖了:
    (EnableDiscoveryClient与EnableEurekaClient的区别(Edgware版本))

    文章图片

  • 之前的疑惑已解开,分析如下:
    1. 由于spring-cloud-starter-eureka的间接依赖,spring-cloud-netflix-eureka-client会出现在classpath中;
    2. 因此spring启动时会扫描到spring-cloud-netflix-eureka-client.jar包中的spring.factories文件;
    3. 如果当前工程使用了EnableDiscoveryClient注解,按照spring.factories中的配置,配置类EurekaDiscoveryClientConfiguration会生效,进而开启服务注册发现功能;
小结
  • 至此,EnableDiscoveryClient与EnableEurekaClient的区别我们已经全部弄明白了,在这里小结一下吧:
  • 在Spring Cloud的Dalston及其之前的版本中:
    1. 从2014年的Spring Cloud 1.0.0.RC1版本开始,官方就推荐使用EnableDiscoveryClient来取代EnableEurekaClient;
    2. EnableEurekaClient源码中使用了注解EnableDiscoveryClient,因此如果要使用eureka的注册发现服务,两者功能是一样的;
    3. EnableDiscoveryClient注解在spring.factories配置中通过配置项EurekaDiscoveryClientConfiguration来开启服务注册发现功能;
  • 在Dalston之后的版本中(不含Dalston):
    1. 在spring.factories配置中,配置类EurekaDiscoveryClientConfiguration被配置到springboot的自动配置注解中,与EnableDiscoveryClient注解没有关系了,也就是说只要开启了springboot的自动配置,服务注册发现功能就会启用;
    2. EnableEurekaClient源码中没有使用注解EnableDiscoveryClient,此时EnableEurekaClient已经没用了;
欢迎关注51CTO博客:程序员欣宸

    推荐阅读