Eureka是大名鼎鼎的Netflix开发的服务发现框架,本身是一个基于REST的服务,主要用于定位运行在AWS域中的中间层服务,以达到负载均衡和中间层服务故障转移的目的。SpringCloud将它集成在其子项目spring-cloud-netflix中,以实现SpringCloud的服务发现功能。
Eureka包含两个组件:Eureka Server和Eureka Client。
Eureka Server提供服务注册服务,各个节点启动后,会在Eureka Server中进行注册,这样EurekaServer中的服务注册表中将会存储所有可用服务节点的信息,服务节点的信息可以在界面中直观的看到。
Eureka Client是一个java客户端,用于简化与Eureka Server的交互,作为轮询负载均衡器,并提供服务的故障切换支持。
在应用启动后,将会向Eureka Server发送心跳,默认周期为30秒,如果Eureka Server在多个心跳周期内没有接收到某个节点的心跳,Eureka Server将会从服务注册表中把这个服务节点移除(默认90秒)。
Eureka Server之间通过复制的方式完成数据的同步,Eureka还提供了客户端缓存机制,即使所有的Eureka Server都挂掉,客户端依然可以利用缓存中的信息消费其他服务的API。综上,Eureka通过心跳检查、客户端缓存等机制,确保了系统的高可用性、灵活性和可伸缩性。
为什么要用Eureka而不是Zookeeper?
当向注册中心查询服务列表时,我们可以容忍注册中心返回的是几分钟以前的注册信息,但不能接受服务直接down掉不可用。也就是说,服务注册功能对可用性的要求要高于一致性。但是Zookeeper会出现这样一种情况,当master节点因为网络故障与其他节点失去联系时,剩余节点会重新进行leader选举。问题在于,选举leader的时间太长,30 ~ 120s, 且选举期间整个zk集群都是不可用的,这就导致在选举期间注册服务瘫痪。在云部署的环境下,因网络问题使得zk集群失去master节点是较大概率会发生的事,虽然服务能够最终恢复,但是漫长的选举时间导致的注册长期不可用是不能容忍的。
而Eureka各个节点都是平等的,几个节点挂掉不会影响正常节点的工作,剩余的节点依然可以提供注册和查询服务。而Eureka的客户端在向某个Eureka注册或时如果发现连接失败,则会自动切换至其它节点,只要有一台Eureka还在,就能保证注册服务可用(保证可用性),只不过查到的信息可能不是最新的(不保证强一致性)。除此之外,Eureka还有一种自我保护机制,如果在15分钟内超过85%的节点都没有正常的心跳,那么Eureka就认为客户端与注册中心出现了网络故障,此时会出现以下几种情况:
因此, Eureka可以很好的应对因网络故障导致部分节点失去联系的情况,而不会像zookeeper那样使整个注册服务瘫痪。
用Idea可以很方便的创建Eureka Server
配置application.yml
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
register-with-eureka: false
# instance:
# preferIpAddress: true
# hostname: localhost
server:
#自我保护模式,测试环境关闭,生产环境一定要打开
enable-self-preservation: false
spring:
application:
name: eureka-server
server:
port: 8761
启动入口Application需要加注解@EnableEurekaServer:
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
启动正常后,访问http://localhost:8761/:
接下来搭建测试的Eureka Client:
配置application.yml
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
spring:
application:
name: eureka-client
启动类Application添加注解@EnableEurekaClient 或者 @EnableDiscoveryClient
注意:SpringCLoud中的“Discovery Service”有多种实现,比如:eureka, consul, zookeeper。
@SpringBootApplication
@EnableDiscoveryClient
public class EurekaClientApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaClientApplication.class, args);
}
}
启动正常后,观察Eureka Server控制台,发现有个服务成功添加到注册表
访问http://localhost:8761/
由于Eureka是服务注册发现中心,如果Eureka挂了,我们整个服务就挂了。所以需要给Eureka搭建集群。
采用相互注册,即Eureka1向Eureka2注册,Eureka2向Eureka1注册。
创建2个Eureka
Eureka1 8761向8762注册:defaultZone: http://localhost:8762/eureka/
Eureka2 8762向8761注册:defaultZone: http://localhost:8761/eureka/
Eureka Client向Eureka1,Eureka2注册:defaultZone: http://localhost:8761/eureka/, http://localhost:8762/eureka/
改造如下:
application.yml:
spring:
profiles:
active: server1
application-server1.yml:
eureka:
client:
service-url:
defaultZone: http://localhost:8762/eureka/
# 表示是否注册自身到eureka服务器
register-with-eureka: false
# 是否从eureka上获取注册信息
# fetch-registry: false
instance:
preferIpAddress: true
# hostname: server1
server:
#自我保护模式,测试环境关闭,生产环境一定要打开
enable-self-preservation: false
spring:
application:
name: eureka-server1
server:
port: 8761
application-server2.yml:
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
# 表示是否注册自身到eureka服务器
register-with-eureka: false
# 是否从eureka上获取注册信息
# fetch-registry: false
instance:
preferIpAddress: true
# hostname: server2
server:
#自我保护模式,测试环境关闭,生产环境一定要打开
enable-self-preservation: false
spring:
application:
name: eureka-server2
server:
port: 8762
启动两个实例:
访问http://localhost:8761/,发现Eureka1中注册了Client
访问http://localhost:8762/,发现Eureka2中注册了Client。