一、Eureka简介
Eureka是Netflix开源的服务发现组件,本身是一个基于REST的服务。它包含Server和Client两部分。SpringCloud将它集成在子项目SpringCloud Netflix中,从而实现微服务的注册与发现。
二、EureKa原理
Eureka包含两个组件:Eureka Server 和 Eureka Client,它们的作用如下:
Eureka Server 提供服务发现能力,各个微服务启动时,会向Eureka Server 注册自己的信息(例如IP、端口、微服务名称等),Eureka Server会存储这些信息。
Eureka Client 是一个Java客户端,用于简化与Eureka Server的交互。
微服务启动后,会周期性(默认30秒)地向Eureka Server 发送心跳以续约自己的“租期”。
如果Eureka Server 在一定时间内没有接收到某个微服务实例的心跳,Eureka Server将会注销该实例(默认90秒)。
默认情况下,Eureka Server 同时也是Eureka Client。多个Eureka Server 实例,互相之间通过复制的方式,来实现服务注册表中数据的同步。
Eureka Client 会缓存服务注册表中的信息。这种方式有一定的优势–首先,微服务无须每次请求都查询Eureka Server,从而降低了Eureka Server的压力;其次,即使Eureka Server所有节点都宕调,服务消费者依然可以使用缓存中的信息找到服务提供者并完成调用。
综上,Eureka通过心跳检查、客户端缓存等机制,提高了系统的灵活性、可伸缩性和可用性。
三、编写Eureka Server
创建一个maven项目,或者使用Spring Initializar快速创建项目:
1、在创建好的maven项目中添加以下依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
</dependency>
2、编写启动类,在启动类上添加@EnableEurekaServer注解,声明这是一个Eureka Server。
package com.ms.cloud.eureka.server;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@EnableEurekaServer
@SpringBootApplication
public class EurekaServer {
public static void main(String[] args) {
SpringApplication.run(EurekaServer.class, args);
}
}
3、在配置文件application.yml中添加以下内容。
server:
port: 9001
eureka:
client:
registerWithEureka: false
fetchRegistry: false
serviceUrl:
defaultZone: http://localhost:9001/eureka/
简单解释下上述配置:
eureka.client.registerWithEureka: 表示是否将自己注册到Eureka Server,默认为true。由于当前应用就是Eureka Server,故而设为false。
eureka.client.fetchRegistry: 表示是否从Eureka Server获取注册信息,默认为true。因为这是一个单点的Eureka Server,不需要同步其他的Eureka Server节点的数据,故而设为false。
eureka.client.serviceUrl.defaultZone: 设置与Eureka Server交互的地址,查询服务和注册服务都需要依赖这个地址。默认是http://localhost:8761/eureka;多个地址可使用逗号分隔。
启动Eureka Server,访问http://localhost:9001,可看到如图所示的界面
你可能会注意到页面上有个Application–ms-cloud-provider-server,这就是后面我要讲的,如何将微服务注册到Eureka Server上。
四、微服务注册到Eureka Server上
1、创建maven项目,在pom.xml中添加以下依赖。
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
2、在配置文件中application.yml中添加以下配置。
p: 10350
h: localhost:9001
server:
port: ${p}
eureka:
instance:
preferIpAddress: true
client:
serviceUrl:
defaultZone: http://${h}/eureka/
spring:
application:
name: ms-cloud-provider-server
version: 1.0.0
其中spring.application.name用于指定注册到Eureka Server 上的应用名称;eureka.instance.preferIpAddress=true表示将自己的IP注册到Eureka Server。如不配置该属性或将其配置为false,则表示注册微服务所在操作系统的hostname到Eureka Server。
4、编写启动类,在启动类上添加@EnableDiscoveryClient注解,声明这是一个Eureka Client。
package com.ms.cloud.provider.server;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@EnableEurekaClient
@SpringBootApplication
public class ProviderServerApplication {
public static void main(String[] args) {
SpringApplication.run(ProviderServerApplication.class, args);
}
}
也可以使用@EnableEurekaClient注解替代@EnableDiscoveryClient。在SpringCloud中,服务发现组件有多种选择,例如Zookeeper、Consul等。@EnableDiscoveryClient为各种服务组件提供了支持,该注解是spring-cloud-commons项目的注解,是一个高度的抽象;而@EnableEurekaClient表明是Eureka的Client,该注解是spring-cloud-netflix项目中的注解,只能与Eureka一起工作。当Euraka在项目的classpath中时,两个注解没有区别。
启动服务,这样就可以将微服务注册到Eureka Server上了,如前面图所示,可以在Eureka的查询页面看到该应用信息。
五、Eureka Server的高可用
Eureka Server 可以通过运行多个实例并相互注册的方式实现高可用部署,Eureka Server实例会彼此增量地同步信息,从而确保所有节点数据一致。事实上,节点之间相互注册是Eureka Server的默认行为。
在单节点Eureka Server上,修改配置为:
p: 9001
h: localhost:9001
p1: 9002
h1: localhost:9002
spring:
application:
name: discoveryServer
version: 1.0.0
---
spring:
profiles: dev
server:
port: ${p}
eureka:
instance:
preferIpAddress: true
client:
registerWithEureka: false
fetchRegistry: false
serviceUrl:
defaultZone: http://${h}/eureka/
---
spring:
profiles: test
server:
port: ${p}
eureka:
instance:
preferIpAddress: true
client:
registerWithEureka: false
fetchRegistry: false
serviceUrl:
defaultZone: http://${h}/eureka/
---
spring:
profiles: prod1
server:
port: ${p}
eureka:
instance:
preferIpAddress: true
client:
serviceUrl:
defaultZone: http://${h1}/eureka/
---
spring:
profiles: prod2
server:
port: ${p1}
eureka:
instance:
preferIpAddress: true
client:
serviceUrl:
defaultZone: http://${h}/eureka/
1、打包项目,并使用以下命令启动两个Eureka Server节点
java -jar xx-xx-xx.jar --spring.profiles.active=prod1
java -jar xx-xx-xx.jar --spring.profiles.active=prod2
2、访问http://localhost:9001会发现有discoveryServer应用,同理在9002也能发现,相互注册了。
六、Eureka的自我保护模式
默认情况下,如果Eureka Server在一定时间内没有接收到某个微服务实例的心跳,Eureka Server将会注销该实例(默认90秒)。但当网络分区故障时,微服务与Eureka Server之间无法正常通信,以上行为可能变得非常危险了——因为微服务本身其实是健康的,此时本不应该注销这个微服务。
Eureka通过“自我保护模式”来解决这个问题——当Eureka Server节点在短时间内丢失过多客户端时(可能发生了网络分区故障),那么这个节点就会进入自我保护模式。一旦进入该模式,Eureka Server就会保护服务注册表中的信息,不再删除服务注册表中的数据(也就是不会注销任何微服务)。当网络故障恢复后,该Eureka Server 节点会自动退出自我保护模式。
综上,自我保护模式是一种应对网络异常的安全保护措施。它的架构哲学是宁可同时保留所有微服务(健康的微服务和不健康的微服务都会保留),也不盲目注销任何健康的微服务。使用自我保护模式,可以让Eureka集群更加的健壮、稳定。
在SpringCloud中可以使用eureka.server.enable-self-preservation = false 禁用自我保护模式。