Eureka是Netflix开源的一个服务注册与发现框架,广泛应用于微服务架构中。它通过提供服务的自动注册与发现机制,简化了服务间的依赖管理,提高了系统的灵活性和可扩展性。Eureka主要由Eureka Server(服务注册中心)和Eureka Client(服务实例)两个核心组件组成。下面将详细介绍Eureka的工作原理,深入到源码分析,并提供详细的实践实例。
Eureka工作原理
Eureka Server
Eureka Server作为服务注册中心,负责存储、管理和提供服务实例信息。服务实例信息包括服务名、IP地址、端口号等。Eureka Server支持集群部署,以保证高可用性和容错能力。不同节点的Eureka Server之间通过Replicate(复制)进行数据同步,确保各节点之间的服务注册表保持一致。
- 启动过程:- 当Eureka Server启动时,它会加载自动配置类(如
EurekaServerAutoConfiguration
),初始化上下文对象(如DefaultEurekaServerContext
),并启动服务接口(通过Jersey框架发布RESTful风格的服务接口)。- Eureka Server会创建一个服务注册表,用于存储所有已注册的服务实例信息。 - 服务注册:- Eureka Server通过
AbstractInstanceRegistry#register()
方法接收客户端的注册请求,将实例信息存储到内存中的ConcurrentHashMap
。 - 心跳续约:- Eureka Client定期(默认每30秒)向Eureka Server发送心跳请求,通过
renew()
方法更新实例的最后更新时间戳。- 如果Eureka Server在一定时间(默认90秒)内未收到某个实例的心跳,则认为该实例已下线,并从注册表中移除。 - 自我保护机制:- 当Eureka Server在短时间内丢失过多客户端心跳时,会进入自我保护模式,不再剔除因心跳超时的服务实例,确保在异常情况下仍能提供可用的服务列表。
Eureka Client
Eureka Client嵌入到每个微服务应用中,分为服务提供者客户端和服务消费者客户端。服务提供者客户端负责在启动时向Eureka Server注册自身信息,并定期发送心跳信号以维持注册状态。服务消费者客户端则通过查询Eureka Server获取所需服务的实例列表,并与之建立连接进行通信。
- 服务注册:- Eureka Client在启动时,通过
EurekaHttpClient
向Eureka Server发送注册请求,包括服务元数据(如服务ID、主机地址、端口等)。- Eureka Server接收到注册请求后,将该信息存储在内存中,并同步至其他节点以实现数据一致性。 - 心跳续约:- Eureka Client开启定时任务,定期(默认每30秒)向Eureka Server发送心跳信号,以证明当前服务是可用状态。- 心跳续约的源码实现在
InstanceInfoReplicator
类中,通过heartbeatExecutor
执行定时任务。 - 服务发现:- Eureka Client通过
DiscoveryClient
从Eureka Server获取所需服务的实例列表,并缓存在本地,减少对Eureka Server的直接依赖。- 当需要调用服务时,Eureka Client首先从本地缓存中获取服务实例信息,如果缓存不存在或已过期,则向Eureka Server发送查询请求。
实践实例
以下是一个简单的Spring Boot项目,演示Eureka的基本使用。
步骤一:创建Eureka Server
- 添加依赖: 在
pom.xml
中添加Spring Cloud Eureka Server依赖。<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-server</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency>
- 配置Eureka Server: 在
application.yml
中配置Eureka Server的相关参数。server:port:8761eureka:instance:hostname: localhost client:register-with-eureka:falsefetch-registry:falseservice-url:defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
- 启动Eureka Server: 在主类上添加
@EnableEurekaServer
注解,启动Eureka Server。@SpringBootApplication@EnableEurekaServerpublicclassEurekaServerApplication{publicstaticvoidmain(String[] args){SpringApplication.run(EurekaServerApplication.class, args);}}
步骤二:创建Eureka Client(服务提供者)
- 添加依赖: 在
pom.xml
中添加Spring Cloud Eureka Client依赖。<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency>
- 配置Eureka Client: 在
application.yml
中配置服务的基本信息和Eureka Server的地址。server:port:8080spring:application:name: eureka-clienteureka:client:service-url:defaultZone: http://localhost:8761/eureka/
- 启动Eureka Client: 在主类上添加
@EnableEurekaClient
注解(Spring Cloud 2.x版本后,可省略)。@SpringBootApplication// @EnableEurekaClient // 在Spring Cloud 2.x及以上版本可以省略publicclassEurekaClientApplication{publicstaticvoidmain(String[] args){SpringApplication.run(EurekaClientApplication.class, args);}}
- 创建REST接口: 在服务提供者中创建一个简单的REST接口,供服务消费者调用。
@RestControllerpublicclassHelloController{@GetMapping("/hello")publicStringhello(){return"Hello from Eureka Client!";}}
通过以上步骤,即可搭建一个基本的Eureka服务注册与发现系统。Eureka Server作为服务注册中心,Eureka Client作为服务实例,共同实现了服务的自动注册与发现机制。
源码分析
这里仅对Eureka源码中的关键部分进行说明。Eureka的源码实现涉及多个组件和类,包括
EurekaServerAutoConfiguration
、
EurekaHttpClient
、
DiscoveryClient
、
InstanceInfoReplicator
等。
- EurekaServerAutoConfiguration:负责Eureka Server的自动配置,包括初始化上下文、启动服务接口等。
- EurekaHttpClient:Eureka Client用于与Eureka Server通信的客户端工具类,封装了HTTP请求的细节。
- DiscoveryClient:Eureka Client用于发现服务的核心类,提供了获取服务实例列表、缓存管理等功能。
- InstanceInfoReplicator:负责Eureka Client的心跳续约功能,通过定时任务向Eureka Server发送心跳信号。
下面咱们逐个介绍
以下是对Eureka源码中
EurekaServerAutoConfiguration
、
EurekaHttpClient
、
DiscoveryClient
、
InstanceInfoReplicator
等关键类的详细分析,深入到实现代码层面:
EurekaServerAutoConfiguration
此类是Eureka Server的自动配置类,主要负责初始化Eureka Server的上下文并启动服务接口。其核心实现包括:
- @EnableEurekaServer:这是一个组合注解,它包含了
@Import(EurekaServerMarkerConfiguration.class)
,用于导入Eureka Server的标记配置类,以便进行自动配置。 - eurekaServerContextInitializer:这是一个
ServletContextListener
,用于在Servlet容器启动时初始化Eureka Server的上下文。 - peerAwareInstanceRegistry、eurekaClientConfig等:这些是通过
@Bean
注解定义的Spring Bean,分别用于创建Eureka的实例注册表和客户端配置对象。
EurekaHttpClient
此类是Eureka Client用于与Eureka Server通信的客户端工具类。它封装了HTTP请求的细节,提供了发送GET、POST等HTTP请求的方法。其核心实现包括:
- requestExecutor:这是一个
ExecutorService
,用于执行异步的HTTP请求。 - execute方法:此方法接收一个
HttpRequest
对象,并返回一个HttpResponse
对象。它使用Apache HttpClient库来发送HTTP请求,并处理响应。 - shutdown方法:此方法用于关闭
EurekaHttpClient
,释放相关资源。
DiscoveryClient
此类是Eureka Client用于发现服务的核心类。它提供了获取服务实例列表、缓存管理等功能。其核心实现包括:
- fetchRegistry方法:此方法用于从Eureka Server获取服务注册表信息,并将其缓存在本地。
- getInstancesByVipAddress方法:此方法根据虚拟IP地址(VIP)从本地缓存中获取服务实例列表。
- shutdown方法:此方法用于关闭
DiscoveryClient
,释放相关资源,并取消所有定时任务。 - initScheduledTasks方法:此方法用于初始化
DiscoveryClient
的定时任务,包括缓存刷新任务、心跳续约任务等。
InstanceInfoReplicator
此类负责Eureka Client的心跳续约功能。它通过定时任务向Eureka Server发送心跳信号,以证明当前服务是可用状态。其核心实现包括:
- run方法:这是
InstanceInfoReplicator
的核心方法,它实现了Runnable
接口。在此方法中,它首先会检查是否需要发送心跳(例如,实例信息是否已变更、是否已到达发送心跳的间隔时间等)。如果需要发送心跳,则通过EurekaHttpClient
向Eureka Server发送心跳请求。 - start方法:此方法用于启动
InstanceInfoReplicator
的定时任务。它使用ScheduledExecutorService
来安排定时任务,并设置任务的执行周期。 - stop方法:此方法用于停止
InstanceInfoReplicator
的定时任务,并释放相关资源。
综上所述,通过对Eureka源码中这些关键类的分析,我们可以深入了解Eureka的实现原理和工作机制。这些类共同协作,实现了Eureka的服务注册、发现、心跳续约等核心功能。
版权归原作者 字节熊猫 所有, 如有侵权,请联系我们删除。