Spring Cloud Netflix Features
通过向 Eureka 提供有关自身的信息(例如主机、端口、状态页 URL 等)并定期发送心跳,Eureka 客户端可以注册到 Eureka 服务器。Eureka 服务器从客户端接收这些心跳,并将关于注册服务的 state 复制到其他服务器,从而实现高可用性。
Eureka 客户端可以使用本机 Netflix EurekaClient 或 Spring Cloud DiscoveryClient 从 Eureka 服务器发现服务实例。通过配置 Eureka 服务器的区域和区域偏好,客户端可以优先使用与其位于同一区域的服务实例。此外,可以通过禁用 Eureka 客户端的刷新功能来提高服务发现的可用性。
Service Discovery: Eureka Clients
服务发现是基于微服务的体系结构的关键原则之一。尝试手工配置每个客户端或某种形式的约定可能很难做到,并且可能很脆弱。Eureka 是 Netflix 服务发现服务器和客户端。服务器可以被配置和部署为高可用性,每个服务器会将关于注册服务的 state 复制到其他服务器。
How to Include Eureka Client
要在您的项目中包含 Eureka 客户端,请使用组 ID 为 org.springframework.cloud
且构件 ID 为 spring-cloud-starter-netflix-eureka-client
的入门指南。有关使用当前 Spring Cloud 版本发布版设置构建系统的详细信息,请参见 Spring Cloud Project page。
Registering with Eureka
当客户端在 Eureka 中注册时,它提供有关其自身的信息 - 例如,主机、端口、运行状况指示符 URL、主页和其他详细信息。Eureka 从属于某个服务的每个实例接收心跳消息。如果超过可配置时间表的运行状况,则通常将该实例从注册表中删除。
以下示例展示了一个最小的 Eureka Client 应用程序:
@SpringBootApplication
@RestController
public class Application {
@RequestMapping("/")
public String home() {
return "Hello world";
}
public static void main(String[] args) {
new SpringApplicationBuilder(Application.class).web(true).run(args);
}
}
请注意,前面的示例显示了一个普通的 Spring Boot 应用程序。通过在类路径上拥有 spring-cloud-starter-netflix-eureka-client
,您的应用程序就会自动在 Eureka Server 中注册。如以下示例所示,需要配置来定位 Eureka server:
eureka: client: serviceUrl: defaultZone: http://localhost:8761/eureka/
在上述示例中,defaultZone
是一个魔术字符串后备值,它为任何不表达偏好的客户端提供服务 URL(换句话说,它是一个有用的默认值)。
defaultZone
属性区分大小写且需要驼峰大小写,因为 serviceUrl
属性是 Map<String, String>
。因此,defaultZone
属性不遵循 default-zone
的常规 Spring Boot 蛇形大小写惯例。
默认应用程序名称(即,服务 ID)、虚拟主机和非安全端口(取自 Environment
)分别为 ${spring.application.name}”、“${spring.application.name}
和 ${server.port}
。
在类路径上有 spring-cloud-starter-netflix-eureka-client
使应用同时成为 Eureka 的“实例
”(即,它注册自身)和“客户端
”(它可以查询注册表以找到其他服务)。该实例行为由 eureka.instance.*
配置键驱动,但是如果确保应用程序有 spring.application.name
的值,则默认值很合适(这是 Eureka 服务 ID 或 VIP 的默认值)。
请参阅 {github-code}/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/EurekaInstanceConfigBean.java[EurekaInstanceConfigBean] 和 {github-code}/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/EurekaClientConfigBean.java[EurekaClientConfigBean],了解有关可配置选项的详细信息。
要禁用 Eureka Discovery Client,可以将 eureka.client.enabled
设置为 false
。当将 spring.cloud.discovery.enabled
设置为 false
时,Eureka Discovery Client 也将被禁用。
目前不支持将 Spring Cloud Netflix Eureka 服务器的版本指定为路径参数。这意味着你无法在上下文路径中设置版本 ( |
Authenticating with the Eureka Server
如果 eureka.client.serviceUrl.defaultZone
URL 之一嵌入了凭据(curl 样式,如下所示:https://user:password@localhost:8761/eureka
),则 HTTP 基本认证将自动添加到您的 eureka 客户端。对于更复杂的需求,您可以创建一个 @Bean
类型的 DiscoveryClientOptionalArgs
,并将 ClientFilter
实例注入其中,所有这些都应用于从客户端到服务器的调用。
当 Eureka 服务器需要客户端证书进行身份验证时,客户端证书和信任存储可以通过属性进行配置,如下例所示:
eureka:
client:
tls:
enabled: true
key-store: <path-of-key-store>
key-store-type: PKCS12
key-store-password: <key-store-password>
key-password: <key-password>
trust-store: <path-of-trust-store>
trust-store-type: PKCS12
trust-store-password: <trust-store-password>
eureka.client.tls.enabled
需要为 true 以启用 Eureka 客户端 TLS。当省略 eureka.client.tls.trust-store
时,将使用 JVM 默认信任存储。eureka.client.tls.key-store-type
和 eureka.client.tls.trust-store-type
的默认值为 PKCS12。当省略密码属性时,假定密码为空。
由于 Eureka 中的限制,无法支持按服务器划分的基于身份验证的凭据,因此仅使用找到的第一组凭据。 |
如果您想自定义 Eureka HTTP Client 使用的 RestTemplate,则可能需要创建一个 EurekaClientHttpRequestFactorySupplier
的 bean,并提供您自己的逻辑来生成 ClientHttpRequestFactory
实例。
用于 Eureka HTTP 客户端的 RestTemplate 所有的默认超时相关属性均设定为 3 分钟(与 Apache HC5 默认的 RequestConfig
和 SocketConfig
保持一致)。因此,要指定超时值,你必须使用 eureka.client.rest-template-timeout
属性直接指定值。(所有超时属性均以毫秒为单位。)
eureka:
client:
rest-template-timeout:
connect-timeout: 5000
connect-request-timeout: 8000
socket-timeout: 10000
在使用默认 Apache HTTP 客户端请求工场时,可使用一个附加参数来配置超时,以逐出空闲连接。默认值为 30 秒。必须以毫秒为单位指定值。
eureka:
client:
rest-template-timeout:
idle-timeout: 30000
Status Page and Health Indicator
对于 Eureka 实例,状态页面和运行状况指标的默认值分别为 /info
和 /health
,它们是 Spring Boot Actuator 应用程序中有用端点的默认位置。即使对于 Actuator 应用程序,如果你使用的是非默认上下文路径或 servlet 路径(例如 server.servletPath=/custom
),你也需要更改它们。以下示例显示了这两个设置的默认值:
eureka: instance: statusPageUrlPath: ${server.servletPath}/info healthCheckUrlPath: ${server.servletPath}/health
这些链接会显示在客户端使用的元数据中,并且在某些情况下用于确定是否将请求发送到你的应用程序,因此,请确保这些链接准确无误。
在 Dalston 中,在更改管理上下文的路径时,还需要设置状态和健康检查 URL。从 Edgware 开始,此要求被移除。 |
Registering a Secure Application
如果你的应用程序希望通过 HTTPS 联系,则可以在 EurekaInstanceConfigBean
中设置两个标志:
-
eureka.instance.[nonSecurePortEnabled]=[false]
-
eureka.instance.[securePortEnabled]=[true]
执行此操作可使 Eureka 发布显示对安全通信的明显偏好的实例信息。Spring Cloud DiscoveryClient
始终为以此方式配置的服务返回以 https
开头的 URI。同样,当以这种方式配置服务时,Eureka(原生)实例信息具有安全的运行状况检查 URL。
由于 Eureka 内部工作方式的原因,除非你明确覆盖它们,否则它仍会为状态和主页发布一个非安全 URL。你可以使用占位符来配置 eureka 实例 URL,如下例所示:
eureka: instance: statusPageUrl: https://${eureka.hostname}/info healthCheckUrl: https://${eureka.hostname}/health homePageUrl: https://${eureka.hostname}/
(请注意,${eureka.hostname}
是一个仅在 Eureka 后续版本中可用的本机占位符。你也可以使用 Spring 占位符实现相同的功能,例如,使用 ${eureka.instance.hostName}
。)
如果您的应用程序在代理后面运行,并且 SSL 终止位于代理中(例如,如果您在 Cloud Foundry 或其他平台中作为服务运行),则需要确保代理 “forwarded” 标头被拦截并由应用程序处理。如果嵌入在 Spring Boot 应用程序中的 Tomcat 容器对“X-Forwarded-\*” 标头有明确的配置,则会自动发生这种情况。您的应用程序呈现的指向其自身的链接不正确(错误的主机、端口或协议)表明您将此配置错误。 |
Eureka’s Health Checks
默认情况下,Eureka 使用客户端心跳来确定客户端是否处于正常运行状态。除非另有说明,否则不会传播应用程序的当前运行状况状态,根据 Spring Boot Actuator 应用程序。因此,在成功注册后,Eureka 始终会宣布应用程序处于“正常运行”状态。可以通过启用 Eureka 运行状况检查来更改此行为,这样做会导致将应用程序状态传播到 Eureka。因此,所有其他应用程序都不会向处于“正常运行”状态以外状态的应用程序发送流量。以下示例展示了如何为客户端启用运行状况检查:
eureka: client: healthcheck: enabled: true
eureka.client.healthcheck.enabled=true
应仅在 application.yml
中设置。在 bootstrap.yml
中设置值会导致不良的副作用,例如以 UNKNOWN
状态在 Eureka 中注册。
如果你需要对运行状况检查进行更多控制,请考虑实现你自己的 com.netflix.appinfo.HealthCheckHandler
。
Eureka Metadata for Instances and Clients
花点时间了解 Eureka 元数据的工作原理是值得的,这样你才能使用它以适合你的平台的方式。用于诸如主机名、IP 地址、端口号、状态页、运行状况检查等信息有标准元数据。这些元数据在服务注册表中发布,并且客户端可以使用这些元数据以直接方式联系服务。可以在 eureka.instance.metadataMap
的实例注册中添加附加元数据,并且可以在远程客户端访问此元数据。通常,附加元数据不会更改客户端的行为,除非将客户端告知元数据含义。在本文档的后面将介绍几种特殊情况,其中 Spring Cloud 已经为元数据映射分配了含义。
Using Eureka on Cloud Foundry
Cloud Foundry 有一个全局路由器,这样同一应用程序的所有实例都具有相同的主机名(具有类似架构的其他 PaaS 解决方案也有相同的排列)。这并不一定妨碍使用 Eureka。但是,如果你使用路由器(推荐甚至强制使用,具体取决于你的平台设置方式),则需要明确设置主机名和端口号(安全或非安全),以便使用路由器。你可能还希望使用实例元数据,以便可以在客户端(例如,自定义负载平衡器)上区分实例。默认情况下,eureka.instance.instanceId
为 vcap.application.instance_id
,如下例所示:
eureka: instance: hostname: ${vcap.application.uris[0]} nonSecurePort: 80
根据在 Cloud Foundry 实例中设置安全规则的方式,您也许可以注册并使用主机 VM 的 IP 地址进行直接服务到服务的调用。Pivotal Web Services ( PWS) 尚未提供此功能。
Using Eureka on AWS
如果应用程序计划部署到 AWS 云,则必须配置 Eureka 实例以使其支持 AWS。您可以通过自定义 {github-code}/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/EurekaInstanceConfigBean.java[EurekaInstanceConfigBean] 来完成此操作,如下所示:
@Bean
@Profile("!default")
public EurekaInstanceConfigBean eurekaInstanceConfig(InetUtils inetUtils) {
EurekaInstanceConfigBean bean = new EurekaInstanceConfigBean(inetUtils);
AmazonInfo info = AmazonInfo.Builder.newBuilder().autoBuild("eureka");
bean.setDataCenterInfo(info);
return bean;
}
Changing the Eureka Instance ID
原生的 Netflix Eureka 实例注册了 ID,该 ID 等于其主机名(即,每个主机只有一个服务)。Spring Cloud Eureka 提供了一个明智的默认值,定义如下:
${spring.cloud.client.hostname}:${spring.application.name}:${spring.application.instance_id:${server.port}}
一个示例是 myhost:myappname:8080
。
使用 Spring Cloud,你可以通过在 eureka.instance.instanceId
中提供唯一标识符来覆盖此值,如下例所示:
eureka: instance: instanceId: ${spring.application.name}:${vcap.application.instance_id:${spring.application.instance_id:${random.value}}}
在前面示例中显示的元数据和部署在本地主机上的多个服务实例中,会将随机值插入其中,以使实例唯一。在 Cloud Foundry 中,vcap.application.instance_id
会在 Spring Boot 应用程序中自动填充,因此不需要随机值。
Using the EurekaClient
一旦你有一个发现客户端应用程序,你可以使用它从 spring-cloud-eureka-server 中发现服务实例。实现此目的的一种方法是使用本机 com.netflix.discovery.EurekaClient
(与 Spring Cloud DiscoveryClient
相对),如下例所示:
@Autowired private EurekaClient discoveryClient; public String serviceUrl() { InstanceInfo instance = discoveryClient.getNextServerFromEureka("STORES", false); return instance.getHomePageUrl(); }
不要在 |
Underlying HTTP clients
EurekaClient
在幕后使用 RestTemplate
、WebClient
或 JerseyClient
。为了使用 EurekaClient
,你需要在你的类路径上拥有一个受支持的 HTTP 客户端。
要使用 RestTemplate
,请将 spring-boot-starter-web
添加到你的依赖项中。要使用 WebClient
,请将 spring-boot-starter-webflux
添加到你的依赖项中。如果当 eureka.client.webclient.enabled
设置为 true
时,RestTemplate
和 WebClient
都在类路径上,则将使用 WebClient
。否则,将使用 RestTemplate
。
如果你希望使用 Jersey,你需要将 Jersey 依赖项添加到你的类路径上。以下示例显示了你需要添加的依赖项:
<dependencies>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-client</artifactId>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-core</artifactId>
</dependency>
<dependency>
<groupId>com.sun.jersey.contribs</groupId>
<artifactId>jersey-apache-client4</artifactId>
</dependency>
</dependencies>
Alternatives to the Native Netflix EurekaClient
你不必使用原始的Netflix EurekaClient
。此外,在某种包装的后面使用它通常更方便。Spring Cloud支持 Spring Cloud LoadBalancer通过逻辑Eureka服务标识符(VIP)而不是物理URL支持Feign(REST客户端构建器)。
你还可以使用 org.springframework.cloud.client.discovery.DiscoveryClient
,它为发现客户端提供了一个简单的 API(不针对 Netflix),如下例所示:
@Autowired private DiscoveryClient discoveryClient; public String serviceUrl() { List<ServiceInstance> list = discoveryClient.getInstances("STORES"); if (list != null && list.size() > 0 ) { return list.get(0).getUri(); } return null; }
Why Is It so Slow to Register a Service?
作为一个实例还涉及到向注册表(通过客户端的 serviceUrl
)定期发送心跳,默认持续时间为 30 秒。在实例、服务器和客户端在它们的本地缓存中都具有相同元数据之前,该服务对客户端不可用进行发现(因此可能需要 3 次心跳)。你可以通过设置 eureka.instance.leaseRenewalIntervalInSeconds
来更改这个时间段。将其设置成小于 30 的值可以加快客户端连接到其他服务的进程。在生产环境中,最好坚持使用默认值,因为服务器中的内部计算假设了续约期限。
Zones
如果你已将 Eureka 客户端部署到多个区域,你可能更希望这些客户端在尝试其他区域中的服务之前使用同一区域中的服务。要进行该设置,你需要正确配置你的 Eureka 客户端。
首先,你需要确保你已将 Eureka 服务器部署到每个区域并且它们彼此是同级。有关更多信息,请参阅 spring-cloud-eureka-server-zones-and-regions 部分。
接下来,你需要告诉 Eureka 你的服务位于哪个区域。你可以使用 metadataMap
属性来执行此操作。例如,如果“服务 1”部署在“区域 1”和“区域 2”中,则需要在“服务 1”中设置以下 Eureka 属性:
区域 1 中的服务 1
eureka.instance.metadataMap.zone = zone1
eureka.client.preferSameZoneEureka = true
区域 2 中的服务 1
eureka.instance.metadataMap.zone = zone2
eureka.client.preferSameZoneEureka = true
Refreshing Eureka Clients
默认情况下,EurekaClient
bean 是可刷新的,这意味着 Eureka 客户端属性可以被更改和刷新。当发生刷新时,客户端将从 Eureka 服务器注销,并且可能有很短的一段时间内给定服务的所有实例不可用。消除这种情况发生的一种方法是禁用刷新 Eureka 客户端的能力。为此,设置 eureka.client.refresh.enable=false
。
Using Eureka with Spring Cloud LoadBalancer
我们为 Spring Cloud LoadBalancer ZonePreferenceServiceInstanceListSupplier
提供支持。Eureka 实例元数据中的 “区域”值 (eureka.instance.metadataMap.zone
) 用于设置 spring-cloud-loadbalancer-zone
属性,该属性用于按区域筛选服务实例。
如果缺少该值,并且 spring.cloud.loadbalancer.eureka.approximateZoneFromHostname
标志设置为 true
,它可以使用服务器主机名中的域名作为区域的代理。
如果没有其他区域数据源,则会根据客户端配置(而不是实例配置)进行猜测。我们采用 eureka.client.availabilityZones
,它是一个来自区域名称到区域列表的映射,并为实例自己的区域(也就是 eureka.client.region
)提取第一个区域,而 eureka.client.region
的默认值为 “us-east-1”,以便与原生 Netflix 兼容。
Service Discovery: Eureka Server
本部分介绍如何设置 Eureka 服务器。
How to Include Eureka Server
要在您的项目中包含 Eureka Server,请使用组 ID 为 org.springframework.cloud
且构件 ID 为 spring-cloud-starter-netflix-eureka-server
的入门指南。有关使用当前 Spring Cloud 版本发布版设置构建系统的详细信息,请参见 Spring Cloud Project page。
如果您的项目已使用 Thymeleaf 作为其模板引擎,则 Eureka 服务器的 Freemarker 模板可能无法正确加载。在这种情况下,需要手动配置模板加载器: |
spring: freemarker: template-loader-path: classpath:/templates/ prefer-file-system-access: false
How to Run a Eureka Server
以下示例展示了一个极简的 Eureka 服务器:
@SpringBootApplication
@EnableEurekaServer
public class Application {
public static void main(String[] args) {
new SpringApplicationBuilder(Application.class).web(true).run(args);
}
}
该服务器在 /eureka/*
下具有一个带有 UI 和 HTTP API 端点的主页,用于正常的 Eureka 功能。
以下链接包含一些 Eureka 背景阅读: flux capacitor 和 google group discussion。
由于 Gradle 的依赖项解析规则和缺少父 bom 特性,依赖于 build.gradle
|
defaultOpenForTrafficCount
and its effect on EurekaServer warmup time
Netflix Eureka 的 waitTimeInMsWhenSyncEmpty
设置开始时不会考虑 Spring Cloud Eureka 服务器。要启用预热时间,请将 eureka.server.defaultOpenForTrafficCount=0
设置为。
High Availability, Zones and Regions
Eureka 服务器没有一个后端存储,但注册表中的服务实例必须向其发送心跳才能保持其注册处于最新状态(因此这可以在内存中完成)。客户端还具有一个 Eureka 注册的内存缓存(因此他们不必在每次请求服务时都去注册表)。
默认情况下,每个 Eureka 服务器也是一个 Eureka 客户端,并且需要(至少一个)服务 URL 来找到对等服务器。如果您没有提供,该服务会运行并工作,但它会在您的日志中引起很多噪音,因为它无法向对等服务器注册。
Standalone Mode
只要存在某种监视器或弹性运行时(例如 Cloud Foundry)可以让它保持活动状态,两个缓存(客户端和服务器)和心跳相结合就会让独立的 Eureka 服务器相当有弹性以应对故障。在独立模式下,您可能更愿意关闭客户端行为,以免它不断尝试并无法访问其对等服务器。以下示例显示了如何关闭客户端行为:
server: port: 8761 eureka: instance: hostname: localhost client: registerWithEureka: false fetchRegistry: false serviceUrl: defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
请注意,serviceUrl
指向的与本地实例相同的主机。
Peer Awareness
通过运行多个实例并要求它们彼此注册,可以让 Eureka 变得更有弹性并且随时可用。实际上,这是默认行为,所以您需要做的只是向对等服务器添加一个有效的 serviceUrl
,如下面的示例所示:
--- 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 外观文件中运行两个主机(“peer1”和“peer2”)上的同一服务器。您可以在一台主机上使用此配置来测试对等感知(在生产中这样做没有多大价值),通过操作 /etc/hosts
来解析主机名。实际上,如果您运行在知道其自身主机名的计算机上,就不需要 eureka.instance.hostname
(默认情况下,使用 java.net.InetAddress
进行查找)。
您可以在系统中添加多个对等服务器,只要它们都通过至少一个边缘彼此连接,它们就会在它们之间同步注册。如果对等服务器在物理上是分离的(在一个数据中心内部或多个数据中心之间),那么从原理上讲,该系统可以在“脑裂”类型的故障中存活下来。您可以在系统中添加多个对等服务器,只要它们都直接彼此连接,它们就会在它们之间同步注册。
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
When to Prefer IP Address
在某些情况下,Eureka 最好通告服务 IP 地址而不是主机名。将 eureka.instance.preferIpAddress
设置为 true
,当应用程序在 eureka 中注册时,它会使用其 IP 地址而不是其主机名。
如果无法通过 Java 来确认主机名,那么 IP 地址会被发送到 Eureka。设置 |
Securing The Eureka Server
您可以简单地通过 spring-boot-starter-security
将 Spring Security 添加到服务器的类路径中来保护您的 Eureka 服务器。 默认情况下,当 Spring Security 在类路径中时,它将要求在发送到应用程序的每个请求中都包含一个有效的 CSRF 标记。Eureka 客户端通常不会拥有有效的跨站点请求伪造 (CSRF) 标记,您需要禁用 /eureka/**
端点的此要求。例如:
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.authorizeHttpRequests((authz) -> authz
.anyRequest().authenticated())
.httpBasic(withDefaults());
http.csrf().ignoringRequestMatchers("/eureka/**");
return http.build();
}
有关 CSRF 的详细信息,请参阅 Spring Security documentation。
可以在 Spring Cloud Samples 中找到 Eureka Server 演示 repo。
Configuration properties
要查看所有 Spring Cloud Netflix 相关配置属性的列表,请查看 the Appendix page。