2. 服务发现:Eureka 服务器

本节介绍如何设置 Eureka 服务器。spring-doc.cadn.net.cn

2.1. 如何包含 Eureka 服务器

要在您的项目中包含 Eureka Server,请使用组 ID 为 org.springframework.cloud、构件 ID 为 spring-cloud-starter-netflix-eureka-server 的Starters。有关如何使用当前 Spring Cloud 发行版系列配置构建系统的详细信息,请参阅 Spring Cloud 项目页面spring-doc.cadn.net.cn

如果您的项目已经使用 Thymeleaf 作为模板引擎,则 Eureka 服务器的 Freemarker 模板可能无法正确加载。此时,有必要手动配置模板加载器:
application.yml
spring:
  freemarker:
    template-loader-path: classpath:/templates/
    prefer-file-system-access: false

2.2. 如何运行一个 Eureka 服务器

以下示例展示了一个最小化的 Eureka 服务器:spring-doc.cadn.net.cn

@SpringBootApplication
@EnableEurekaServer
public class Application {

    public static void main(String[] args) {
        new SpringApplicationBuilder(Application.class).web(true).run(args);
    }

}

服务器具有一个主页,包含用户界面和 HTTP API 端点,用于提供常规的 Eureka 功能,路径为 /eureka/*spring-doc.cadn.net.cn

以下链接提供了一些关于 Eureka 的背景资料:通量稳定器Google 群组讨论spring-doc.cadn.net.cn

由于 Gradle 的依赖解析规则以及缺乏父 BOM(Bill of Materials)功能,依赖 spring-cloud-starter-netflix-eureka-server 可能导致应用程序启动时失败。为解决此问题,请添加 Spring Boot Gradle 插件,并按如下方式导入 Spring Cloud Starter 父 BOM:spring-doc.cadn.net.cn

build.gradle
buildscript {
  dependencies {
    classpath("org.springframework.boot:spring-boot-gradle-plugin:{spring-boot-docs-version}")
  }
}

apply plugin: "spring-boot"

dependencyManagement {
  imports {
    mavenBom "org.springframework.cloud:spring-cloud-dependencies:{spring-cloud-version}"
  }
}

2.3.defaultOpenForTrafficCount和EurekaServer预热时间的影响

Netflix Eureka 的 waitTimeInMsWhenSyncEmpty 设置在 Spring Cloud Eureka 服务器启动初期未被采纳。为启用预热时间,请设置 eureka.server.defaultOpenForTrafficCount=0spring-doc.cadn.net.cn

2.4. 高可用性、区域和区段

Eureka 服务器没有后端存储,但注册表中的所有服务实例都必须发送心跳以保持其注册信息的最新(因此可以内存中完成)。</p><p>客户端也维护着 Eureka 注册信息的内存缓存(因此它们无需在每次请求服务时都去查询注册表)。spring-doc.cadn.net.cn

默认情况下,每个 Eureka 服务器同时也是 Eureka 客户端,并且至少需要提供一个服务 URL 才能定位对等节点。如果您未提供该 URL,服务仍会运行并正常工作,但会向您的日志中输出大量关于无法注册到对等节点的噪声信息。spring-doc.cadn.net.cn

2.5. 独立模式

客户端缓存和服务器端缓存的结合,以及心跳机制,使得独立运行的 Eureka 服务器在出现故障时仍具有相当强的容错能力,只要存在某种监控或弹性运行时环境(例如 Cloud Foundry)来维持其运行即可。在独立模式下,您可能更倾向于关闭客户端行为,以避免其持续尝试连接其对等节点却不断失败。以下示例展示了如何关闭客户端行为:spring-doc.cadn.net.cn

application.yml(独立 Eureka 服务器)
server:
  port: 8761

eureka:
  instance:
    hostname: localhost
  client:
    registerWithEureka: false
    fetchRegistry: false
    serviceUrl:
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/

注意,serviceUrl 指向的主机与本地实例相同。spring-doc.cadn.net.cn

2.6. 节点感知

Eureka 可以通过运行多个实例并要求它们相互注册,从而变得更加健壮和可用。实际上,这是默认行为,因此您只需向一个对等节点添加一个有效的 serviceUrl 即可使其正常工作,如下例所示:spring-doc.cadn.net.cn

application.yml(两个对等感知的 Eureka 服务器)
---
spring:
  profiles: peer1
eureka:
  instance:
    hostname: peer1
  client:
    serviceUrl:
      defaultZone: https://peer2/eureka/

---
spring:
  profiles: peer2
eureka:
  instance:
    hostname: peer2
  client:
    serviceUrl:
      defaultZone: https://peer1/eureka/

在前面的例子中,我们有一个 YAML 文件,可以通过在不同的 Spring 配置文件中运行它,使同一服务器在两个主机(peer1peer2)上运行。您可利用此配置在单台主机上测试对等节点感知能力(在生产环境中这样做价值不大),方法是将 /etc/hosts 修改为解析主机名。事实上,如果您在一台能够识别自身主机名的机器上运行(默认情况下,它是通过 java.net.InetAddress 查找的),则 eureka.instance.hostname 并非必需。spring-doc.cadn.net.cn

您可以向系统中添加多个对等节点,只要它们彼此之间至少通过一条边相互连接,即可在彼此之间同步注册信息。如果这些对等节点在物理上相互分离(例如位于同一数据中心内或分布在多个数据中心之间),那么该系统原则上能够应对‘脑裂’类型的故障。您可以向系统中添加多个对等节点,只要它们彼此直接相连,即可在彼此之间同步注册信息。spring-doc.cadn.net.cn

application.yml(三个感知服务的Eureka服务器)
eureka:
  client:
    serviceUrl:
      defaultZone: https://peer1/eureka/,http://peer2/eureka/,http://peer3/eureka/

---
spring:
  profiles: peer1
eureka:
  instance:
    hostname: peer1

---
spring:
  profiles: peer2
eureka:
  instance:
    hostname: peer2

---
spring:
  profiles: peer3
eureka:
  instance:
    hostname: peer3

2.7. 何时优先使用IP地址

在某些情况下,更倾向于让 Eureka 宣告服务的 IP 地址而非主机名。spring-doc.cadn.net.cn

spring-doc.cadn.net.cn

eureka.instance.preferIpAddress 设置为 true,当应用程序向 Eureka 注册时,它将使用其 IP 地址而非主机名。spring-doc.cadn.net.cn

spring-doc.cadn.net.cn

如果 Java 无法确定主机名,则会将 IP 地址发送至 Eureka。仅通过设置 eureka.instance.hostname 属性这一显式方式可设定主机名。您也可在运行时通过环境变量进行设置——例如,eureka.instance.hostname=${HOST_NAME}spring-doc.cadn.net.cn

2.8. 保护Eureka服务器

您可以通过将Spring Security添加到服务器类路径中来简单地保护您的Eureka服务器spring-boot-starter-security。默认情况下,当Spring Security在类路径上时,它将要求每个请求都发送有效的CSRFTokens。Eureka客户端通常不会拥有有效的跨站请求伪造(CSRF)Tokens,因此您需要禁用对/eureka/**端点的此要求。例如:spring-doc.cadn.net.cn

@EnableWebSecurity
class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().ignoringAntMatchers("/eureka/**");
        super.configure(http);
    }
}

有关CSRF的更多信息,请参阅Spring Security文档spring-doc.cadn.net.cn

在 Spring Cloud 示例仓库 repo 中可找到一个 Eureka Server 的演示实例。spring-doc.cadn.net.cn

2.9. 支持 JDK 11

由于 JDK 11 中已移除 Eureka 服务器所依赖的 JAXB 模块,如果您计划在运行 Eureka 服务器时使用 JDK 11,则必须在您的 POM 文件或 Gradle 文件中添加这些依赖项。spring-doc.cadn.net.cn

<dependency>
    <groupId>org.glassfish.jaxb</groupId>
    <artifactId>jaxb-runtime</artifactId>
</dependency>