Eureka是什么
Spring Cloud Eureka是Spring Cloud Netflix微服务套件的一部分,它是基于Netflix Eureka的二次封装,主要负责完成微服务中各个的服务注册与发现。假设我们有两个服务A和B,其中A服务需要调用到B服务来完成某个业务操作,如果没有注册中心,我们可能会将B服务的地址和接口API以配置文件的形式注入到应用中,但随着业务的增长,单个的服务B可能没法抗住压力,需要进行扩容和高可用,这时就需要频繁的去调整服务A代码中关于B服务的配置,这是很笨的。
我们假设这样一种场景:我们有多个服务B的实例,有一个特殊的服务C可以帮我们列出B服务的所有实例,并给这些服务起一个服务名,我们在A服务中通过这个服务名调用服务B的某个实例。这样若是服务B的实例发生变化,服务A并不需要编码或配置上的修改,Eureka在微服务架构中也恰恰起到了这个作用。
Spring Cloud、Spring Boot的版本问题
根据前面我们举得服务A、服务B以及管理服务B的特殊服务C,我们可以发现Eureka是分为两部分的,第一部分是承担维护服列表的服务C,我们称之为Eureka服务端,第二部分是服务A、服务B之类了的普通服务,我们称之为Eureka客户端。Eureka客户端会被注册到Eureka服务端,被其他服务进行调用,Eureka在微服务架构中起到了微服务中服务治理的作用。
这里讲一下Spring Cloud版本与Spring Boot的对应关系,如果版本之间搭配的有问题,就可能引出各种奇怪的问题,开始之前还是应该把版本统一好。我们可以通过访问这个地址https://start.spring.io/actuator/info来获取Spring Cloud与Spring Boot的对应关系,确定一下自己选的Spring Cloud与Spring Boot是互相适配没有问题的。
我们这里用的Spring Cloud版本是Finchley.M2,Spring Boot版本是2.0.0.M3。至于Spring Cloud与其他几大服务组件的关系,在Spring Cloud的依赖中已经指定声明了,不需要我们再去操心。我们看一个Eureaka服务端的POM文件:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.0.M3</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<spring-cloud.version>Finchley.M2</spring-cloud.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
能看出我们用的Spring Boot版本是2.0.0.M3,Spring Cloud版本是Finchley.M2,引入了一个eureka-server依赖,却没有指定版本。我们点到spring-cloud-dependencies这个依赖的pom中去,发现定义了spring-cloud-netflix的版本,而Eureka就是netflix套件中的一部分。因此我们不必再操心Spring Cloud与各个微服务组件搭配时的版本问题。
Eureka的服务端
Eureka的服务端很好实现,最少配置就两步:
- 引入Eureka的依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
- 对Spring Boot的启动类增加@EnableEurekaServer注解
@EnableEurekaServer的深入探究
/**
* Annotation to activate Eureka Server related configuration {@link EurekaServerAutoConfiguration}
*/
@EnableDiscoveryClient
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(EurekaServerMarkerConfiguration.class)
public @interface EnableEurekaServer {
}
类注释的意思是:这个注解是用来激活Eeureka Server相关配置EurekaServerAutoConfiguration的。同时我们发现这个注解还用到了@EnableDiscoveryClient,这说明Eeureka服务端同时也是一个Eeureka客户端,这里的@Import起到的作用是导入配置bean(@Import的详细作用我会再写一篇),我们看一下EurekaServerMarkerConfiguration的源码:
/**
* Responsible for adding in a marker bean to activate
* {@link EurekaServerAutoConfiguration}
*/
@Configuration
public class EurekaServerMarkerConfiguration {
@Bean
public Marker eurekaServerMarkerBean() {
return new Marker();
}
class Marker {
}
}
就单纯是为了实例化一个Marker的bean,用来激活EurekaServerAutoConfiguration这个类,我们看一下这个类的一些代码:
// 说明这是一个配置类
@Configuration
@Import(EurekaServerInitializerConfiguration.class)
// 这里体现了@EnableEurekaServer注解要引入一个EurekaServerMarkerConfiguration.Marker对象的原因,
// 是用来激活EurekaServerAutoConfiguration这个配置类
@ConditionalOnBean(EurekaServerMarkerConfiguration.Marker.class)
// @ConfigurationProperties注解可谓是SpringBoot最常用的属性配置相关的注解,但如果你自己尝试可以发现,
// 单一个@ConfigurationPropertie是不够的(如果没有同时被@Compent修饰)是无法将Bean注入进来,必须要用@EnableConfigurationProperties开启
@EnableConfigurationProperties({ EurekaDashboardProperties.class,
InstanceRegistryProperties.class })
// 用于加载指定配置文件
@PropertySource("classpath:/eureka/server.properties")
public class EurekaServerAutoConfiguration extends WebMvcConfigurerAdapter {
}
可以看到上面我们还有一行没有介绍,就是通过@Import导入的EurekaServerInitializerConfiguration这个配置类,从名字可以看出这个与Eureka服务端配置初始化相关。我们看一下这个类的代码:
@Configuration
public class EurekaServerInitializerConfiguration
implements ServletContextAware, SmartLifecycle, Ordered {
private ServletContext servletContext;
@Autowired
private EurekaServerBootstrap eurekaServerBootstrap;
@Override
public void setServletContext(ServletContext servletContext) {
this.servletContext = servletContext;
}
@Override
public void start() {
new Thread(new Runnable() {
@Override
public void run() {
try {
//TODO: is this class even needed now?
eurekaServerBootstrap.contextInitialized(EurekaServerInitializerConfiguration.this.servletContext);
log.info("Started Eureka Server");
publish(new EurekaRegistryAvailableEvent(getEurekaServerConfig()));
EurekaServerInitializerConfiguration.this.running = true;
publish(new EurekaServerStartedEvent(getEurekaServerConfig()));
}
catch (Exception ex) {
// Help!
log.error("Could not initialize Eureka servlet context", ex);
}
}
}).start();
}
}
由于篇幅原因,这里只粘贴了一部分源码。EurekaServerInitializerConfiguration实现了ServletContextAware和SmartLifecycle两个接口,第一个接口使用来获取Spring上下文ServletContext的,具体的实现可以看一下这篇http://www.pinhuba.com/spring/101051.htm。
第二个接口是用来在Spring加载和初始化所有bean后,接着执行一些任务或者启动需要的异步服务。我们通过源码的start()方法可以看到确实是启动了一个新的线程去调用EurekaServerBootstrap.contextInitialized方法启动初始化Eureka环境并启动Eureka。
整个流程下来是这个样子的(图片摘自):
来源:CSDN
作者:升级中的小码农
链接:https://blog.csdn.net/DU87680258/article/details/104139376