一篇文章,让你看懂 Spring Cloud 之 Eureka

5,002 阅读5分钟

Eureka

什么是 Eureka?

Eureka 由 Netflix 开发,是一种基于REST(Representational State Transfer)的服务,用于定位服务(服务注册与发现),以实现中间层服务的负载均衡和故障转移,此服务被称为 Eureka Server。同时,它还附带了基于 Java 的客户端组件:Eureka Client,它使得客户端与 Eureka Server 的交互变得更加的容易。

以下就是一个简单的服务调用过程:

  1. 由服务提供方将服务注册到 Eureka Server
  2. 服务消费者通过 Eureka Server 获取服务提供方的真实地址
  3. 服务消费者通过真实的地址调用服务

在服务提供者注册到 Eureka Server 的过程中,它会将自身的元数据(包括主机、端口等以及其他自定义的信息)都注册到 Eureka Server 中,服务消费者通过 Eureka Server 即可获取这些信息,所以对于 Eureka 来说,它不会限定服务消费者与服务提供者之间的具体该如何通讯,这些都是由服务消费者与服务提供者决定,你可以自行选择任意你喜欢的方式,如 HTTP、RPC、Thrift 等。

实战

接下来我们就搭建一个简单的 Eureka 集群。

得益于 Spring CloudEureka 的封装,使得我们使用它十分简单。首先自然是要创建一个项目的脚手架,这个可以通过 官方工具 来快速搭建 Spring Cloud 的开发环境。

首先我们需要选择构建工具、Java 和 Spring Boot 的版本,以及填写 groupId,artifactId,项目名以及包名等基础信息。

此系列的教程使用的 Spring Boot 版本是 2.1.8,对应的 Spring Cloud 的版本是 Greenwich.SR2。

其次,需要选择项目的依赖项

因为我们的目的只是搭建 Eureka 的集群,所以我们只需要选择以下几个依赖即可:

  • spring-boot-starter-web
  • eureka-server
  • eureka-client

除了这两个之外,还有以下几个依赖项是比较常用的,所以我们也将它们加入依赖:

  • configuration-processor

  • lombok

  • spring-boot-starter-actuator

依赖选择完成后点击下载,就能创建一个基础的 Spring Cloud 开发环境。将它导入 IDE 后,看起来应该是这样的:

此处我手动修改了两个地方,一是将 application.properties 改为了 application.yml,二是添加了 bootstrap.yml,熟悉 Spring Boot 的同学对这个文件应该不陌生。

接下来还有些准备工作要做,因为要在本地搭建集群,所以我们还需要修改本机的 hosts 文件(在 Windows 系统中位于:C:\Windows\System32\drivers\etc),创建三个虚拟的域名用于 Eureka Server。我们向 hosts 文件添加三行数据,将 localhost 指向三个虚拟域名:

127.0.0.1 peer1
127.0.0.1 peer2
127.0.0.1 peer3

为确保修改生效,可以在命令行执行:ipconfig /flushdns 来刷新 hosts

配置完成后,我们还需对项目进行一些简单的配置。

  1. bootstrap.yml 中添加应用名称:
spring:
  application:
    ## 服务的名称,可以任意修改,但是需要确保在整个系统中的唯一性
    name: eureka
eureka:
  client:
    serviceUrl:
      defaultZone: http://peer1:8761/eureka/,http://peer2:8762/eureka/,http://peer3:8763/eureka/
  1. application.yml 中添加注册中心的地址以及三个 profile 并设置不同的端口
eureka:
  client:
    serviceUrl:
      defaultZone: http://peer1:8761/eureka/,http://peer2:8762/eureka/,http://peer3:8763/eureka/
---
spring:
  profiles: peer1
server:
  port: 8761
eureka:
  instance:
    hostname: peer1
---
spring:
  profiles: peer2
eureka:
  instance:
    hostname: peer2
server:
  port: 8762
---
spring:
  profiles: peer3
eureka:
  instance:
    hostname: peer3
server:
  port: 8763

  1. 在应用启动类上添加注解 @EnableEurekaServer
@EnableEurekaServer
@SpringBootApplication
public class RegistryEurekaApplication {

	public static void main(String[] args) {
		SpringApplication.run(RegistryEurekaApplication.class, args);
	}

}

所有的准备工作已经完成,接下来我们分别在三个终端中以不同的 profile 启动我们的 Eureka Server:

mvn -Dmaven.test.skip=true clean install
cd target/
java -jar -Dspring.profiles.active=peer1 registry-0.0.1-SNAPSHOT.jar
java -jar -Dspring.profiles.active=peer2 registry-0.0.1-SNAPSHOT.jar
java -jar -Dspring.profiles.active=peer3 registry-0.0.1-SNAPSHOT.jar

在启动的过程中可能会打印错误日志,这是由于注册中心还没有启动完成,导致启动的时候连接其他注册中心失败而产生的错误,这个错误会在三个服务都完全启动后消失。

服务启动后,就可以在浏览器中打开它了,因为我们的服务是由三个节点组成,所以可以打开任意一个:http://peer1:8761/

DS Replicas 以及 Instances currently registered with Eureka 中,都可以看到我们启动的节点的状态。

至此,我们已经成功搭建了一个有三个节点的注册中心。

Eureka 的自我保护机制

当我们关闭掉一个实例后,Eureka Server 可能会出现以下的提示:

EMERGENCY! EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP WHEN THEY'RE NOT. RENEWALS ARE LESSER THAN THRESHOLD AND HENCE THE INSTANCES ARE NOT BEING EXPIRED JUST TO BE SAFE.

这是因为 Eureka 进入了自我保护机制。默认情况下,Eureka Server 在一定时间内如果没有接收到某个实例的心跳,就会移除该实例。但是可能会有这种情况:当网络分区故障时,服务与 Eureka Server 无法正常通信,但是服务本身是正常的,此时就不该移除该服务,所以 Eureka 就引入了自我保护机制。当 Eureka 进入此机制时,它将不再移除任何服务,哪怕服务不可用。

你可以查看这个问题以及官方文档了解更多关于自我保护机制的内容,此处不做过多讲解。

关于 Eureka 的环境搭建就介绍到这里了,下一篇文章,我将介绍 Spring Cloud Config