Eureka是个基于内存的服务注册中心。
Eureka和zookeeper
CAP理论,一个分布式系统不可能同时满足C(一致性)、A(可用性)、P(分区容错性)三个特性。
Eureka和zookeeper在服务注册中心这个场景不一样的是,Eureka注重可用性,实现AP;而zookeeper注重一致性,实现CP。
zk会出现这样一种情况,当master节点因为网络故障与其他节点失去联系时,剩余节点会重新进行leader选举。问题在于,选举leader的时间太长,30 ~ 120s, 且选举期间整个zk集群都是不可用的,这就导致在选举期间注册服务瘫痪。
Eureka各个节点都是平等的,几个节点挂掉不会影响正常节点的工作,剩余的节点依然可以提供注册和查询服务。而Eureka的客户端在向某个Eureka注册或时如果发现连接失败,则会自动切换至其它节点,只要有一台Eureka还在,就能保证注册服务可用(保证可用性),只不过查到的信息可能不是最新的(不保证强一致性)。除此之外,Eureka还有一种自我保护机制,如果在15分钟内超过85%的节点都没有正常的心跳,那么Eureka就认为客户端与注册中心出现了网络故障,此时会出现以下几种情况:
- Eureka不再从注册列表中移除因为长时间没收到心跳而应该过期的服务
- Eureka仍然能够接受新服务的注册和查询请求,但是不会被同步到其它节点上(即保证当前节点依然可用)
- 当网络稳定时,当前实例新的注册信息会被同步到其它节点中
因此, Eureka可以很好的应对因网络故障导致部分节点失去联系的情况,而不会像zookeeper那样使整个注册服务瘫痪。
配置
Eureka配置太多了,参考 https://www.cnblogs.com/fangfuhai/p/7070325.html
Spring Cloud Eureka配置参考: https://www.cnblogs.com/li3807/p/7282492.html
Spring Cloud Eureka服务
添加以下依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
</dependency>
在Spring Boot启动类上增加@EnableEurekaServer注解即可启动一个Eureka服务器:
@SpringBootApplication
@EnableEurekaServer
public class Bootstrap {
public static void main(String[] args) {
SpringApplication.run(Bootstrap.class, args);
}
}
启动之后,访问根页面可以看到Eureka的页面:

一切看起来没什么问题,但是留意一下控制台,就会发现错误日志:
2018-02-07 01:18:25.331 ERROR 10836 --- [freshExecutor-0] com.netflix.discovery.DiscoveryClient : DiscoveryClient_PHOENIX-REGISTER/DESKTOP-6PN69LR:phoenix-register - was unable to refresh its cache! status = Cannot execute request on any known server
com.netflix.discovery.shared.transport.TransportException: Cannot execute request on any known server
at com.netflix.discovery.shared.transport.decorator.RetryableEurekaHttpClient.execute(RetryableEurekaHttpClient.java:111) ~[eureka-client-1.6.2.jar:1.6.2]
at com.netflix.discovery.shared.transport.decorator.EurekaHttpClientDecorator.getApplications(EurekaHttpClientDecorator.java:134) ~[eureka-client-1.6.2.jar:1.6.2]
at com.netflix.discovery.shared.transport.decorator.EurekaHttpClientDecorator$6.execute(EurekaHttpClientDecorator.java:137) ~[eureka-client-1.6.2.jar:1.6.2]
at com.netflix.discovery.shared.transport.decorator.SessionedEurekaHttpClient.execute(SessionedEurekaHttpClient.java:77) ~[eureka-client-1.6.2.jar:1.6.2]
at com.netflix.discovery.shared.transport.decorator.EurekaHttpClientDecorator.getApplications(EurekaHttpClientDecorator.java:134) ~[eureka-client-1.6.2.jar:1.6.2]
at com.netflix.discovery.DiscoveryClient.getAndStoreFullRegistry(DiscoveryClient.java:1013) [eureka-client-1.6.2.jar:1.6.2]
at com.netflix.discovery.DiscoveryClient.fetchRegistry(DiscoveryClient.java:927) [eureka-client-1.6.2.jar:1.6.2]
at com.netflix.discovery.DiscoveryClient.refreshRegistry(DiscoveryClient.java:1451) [eureka-client-1.6.2.jar:1.6.2]
at com.netflix.discovery.DiscoveryClient$CacheRefreshThread.run(DiscoveryClient.java:1418) [eureka-client-1.6.2.jar:1.6.2]
at java.util.concurrent.Executors$RunnableAdapter.call$$$capture(Executors.java:511) [na:1.8.0_161]
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java) [na:1.8.0_161]
at java.util.concurrent.FutureTask.run$$$capture(FutureTask.java:266) [na:1.8.0_161]
at java.util.concurrent.FutureTask.run(FutureTask.java) [na:1.8.0_161]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_161]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_161]
at java.lang.Thread.run(Thread.java:748) [na:1.8.0_161]
Eureka会尝试从其他节点同步服务注册信息,目前我们的Eureka服务器没有任何配置,因此Eureka是同步注册数据失败的。
单节点
在application.properties中添加配置:
# 是否把本服务注册到Eureka
eureka.client.register-with-eureka=false
指定服务注册中心地址,类型为 HashMap,并设置有一组默认值,默认的Key为 defaultZone;
默认的Value为 [http://localhost:8761/eureka](http://localhost:8761/eureka) ,
如果服务注册中心为高可用集群时,多个注册中心地址以逗号分隔。
如果服务注册中心加入了安全验证,这里配置的地址格式为:
http://<username>:<password>@localhost:8761/eureka
其中 <username> 为安全校验的用户名;<password> 为该用户的密码
eureka.client.service-url.defaultZone=http://localhost:8080/eureka/
这样配置,上面的报错就不会再出现了
集群配置
其实很简单,就是把单节点中的eureka.client.service-url.defaultZone配置成其他几个Eureka实例就行。
网友评论