12. 服务发现:Eureka 服务器

本节介绍如何设置 Eureka 服务器。

12.1 如何包括 Eureka 服务器

要将 Eureka Server 包含在您的项目中,请使用组 ID 为org.springframework.cloud且工件 ID 为spring-cloud-starter-netflix-eureka-server的启动程序。有关使用当前 Spring Cloud Release Train 设置构建系统的详细信息,请参见Spring Cloud Project 页面

Note

如果您的项目已经使用 Thymeleaf 作为其模板引擎,则可能无法正确加载 Eureka 服务器的 Freemarker 模板。在这种情况下,必须手动配置模板加载器:

application.yml.

spring:
  freemarker:
    template-loader-path: classpath:/templates/
    prefer-file-system-access: false

12.2 如何运行 Eureka 服务器

以下示例显示了最小的 Eureka 服务器:

@SpringBootApplication
@EnableEurekaServer
public class Application {

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

}

该服务器具有一个主页,该主页具有/eureka/*下的 Eureka 正常功能的 UI 和 HTTP API 端点。

以下链接具有一些 Eureka 的背景知识:flux capacitor谷歌小组讨论

Tip

由于 Gradle 的依赖性解析规则以及缺少父 bom 功能,取决于spring-cloud-starter-netflix-eureka-server可能导致应用程序启动失败。要解决此问题,请添加 Spring Boot Gradle 插件并按如下所示导入 Spring Cloud Starter 父 Bom:

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}"
}
}

12.3 高可用性,区域和区域

Eureka 服务器没有后端存储,但是注册表中的所有服务实例都必须发送心跳 signal 以使其注册保持最新(因此可以在内存中完成)。Client 端还具有 Eureka 注册的内存缓存(因此,对于每个对服务的请求,它们都不必转到注册表)。

默认情况下,每个 Eureka 服务器也是 EurekaClient 端,并且需要(至少一个)服务 URL 来定位对等方。如果您不提供该服务,则该服务将运行并运行,但是它将使您的日志充满关于无法向对等方注册的噪音。

另请参阅 Client 端上的以下是功能区支持的详细信息,了解“区域和区域”。

12.4 独立模式

只要有某种监视器或弹性运行时(例如 Cloud Foundry),这两个缓存(Client 端和服务器)以及心跳的组合就可以使独立的 Eureka 服务器对故障具有相当的恢复能力。在独立模式下,您可能希望关闭 Client 端行为,以便它不会 continue 尝试并无法到达其对等对象。以下示例显示了如何关闭 Client 端行为:

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指向与本地实例相同的主机。

12.5 同行意识

通过运行多个实例并要求它们相互注册,可以使 Eureka 更具弹性并可以使用。实际上,这是默认行为,因此,使它起作用所需要做的就是向对等方添加一个有效的serviceUrl,如以下示例所示:

application.yml(两个对等的 Eureka 服务器).

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

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

在前面的示例中,我们有一个 YAML 文件,通过在不同的 Spring 配置文件中运行该服务器,可以在两个主机(peer1peer2)上运行同一服务器。您可以使用此配置通过操纵/etc/hosts解析主机名来测试单个主机上的对等感知(在生产环境中这样做没有太大价值)。实际上,如果您在知道其主机名的计算机上运行,则不需要eureka.instance.hostname(默认情况下,使用java.net.InetAddress查找它)。

您可以将多个对等方添加到系统,并且只要它们均通过至少一个边缘彼此连接,它们就可以在彼此之间同步注册。如果对等点在物理上是分开的(在一个数据中心内部或在多个数据中心之间),则该系统原则上可以承受“裂脑”型故障。您可以将多个对等方添加到系统中,并且只要它们都直接相互连接,它们就可以在彼此之间同步注册。

application.yml(三个对等感知 Eureka 服务器).

eureka:
  client:
    serviceUrl:
      defaultZone: http://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

12.6 何时首选 IP 地址

在某些情况下,Eureka 最好公布服务的 IP 地址而不是主机名。将eureka.instance.preferIpAddress设置为true,并且当应用程序向 eureka 注册时,它将使用其 IP 地址而不是其主机名。

Tip

如果 Java 无法确定主机名,则 IP 地址将发送到 Eureka。设置主机名的唯一明确方法是设置eureka.instance.hostname属性。您可以在运行时使用环境变量设置主机名,例如eureka.instance.hostname=${HOST_NAME}

12.7 保护 Eureka 服务器

您只需通过spring-boot-starter-security将 Spring Security 添加到服务器的 Classpath 中,即可保护 Eureka 服务器。默认情况下,当 Spring Security 在 Classpath 上时,它将要求将有效的 CSRF 令牌与每个请求一起发送到应用程序。 EurekaClient 通常不会拥有有效的跨站点请求伪造(CSRF)令牌,您需要针对/eureka/**端点禁用此要求。例如:

@EnableWebSecurity
class WebSecurityConfig extends WebSecurityConfigurerAdapter {

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

有关 CSRF 的更多信息,请参见Spring Security 文档

可以在 Spring Cloud Samples repo中找到演示版 Eureka Server。

12.8 JDK 11 支持

在 JDK 11 中删除了 Eureka 服务器所依赖的 JAXB 模块。如果打算在运行 Eureka 服务器时使用 JDK 11,则必须在 POM 或 Gradle 文件中包括这些依赖项。

<dependency>
    <groupId>javax.xml.bind</groupId>
    <artifactId>jaxb-api</artifactId>
    <version>2.3.0</version>
</dependency>
<dependency>
    <groupId>com.sun.xml.bind</groupId>
    <artifactId>jaxb-core</artifactId>
    <version>2.3.0</version>
</dependency>
<dependency>
    <groupId>com.sun.xml.bind</groupId>
    <artifactId>jaxb-impl</artifactId>
    <version>2.3.0</version>
</dependency>