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 复制到其他服务器。
Service Discovery is one of the key tenets of a microservice-based architecture. Trying to hand-configure each client or some form of convention can be difficult to do and can be brittle. Eureka is the Netflix Service Discovery Server and Client. The server can be configured and deployed to be highly available, with each server replicating state about the registered services to the others.
How to Include Eureka Client
要在您的项目中包含 Eureka 客户端,请使用组 ID 为 org.springframework.cloud
且构件 ID 为 spring-cloud-starter-netflix-eureka-client
的入门指南。有关使用当前 Spring Cloud 版本发布版设置构建系统的详细信息,请参见 Spring Cloud Project page。
To include the Eureka Client in your project, use the starter with a group ID of org.springframework.cloud
and an artifact ID of spring-cloud-starter-netflix-eureka-client
.
See the Spring Cloud Project page for details on setting up your build system with the current Spring Cloud Release Train.
Registering with Eureka
当客户端在 Eureka 中注册时,它提供有关其自身的信息 - 例如,主机、端口、运行状况指示符 URL、主页和其他详细信息。Eureka 从属于某个服务的每个实例接收心跳消息。如果超过可配置时间表的运行状况,则通常将该实例从注册表中删除。
When a client registers with Eureka, it provides meta-data about itself — such as host, port, health indicator URL, home page, and other details. Eureka receives heartbeat messages from each instance belonging to a service. If the heartbeat fails over a configurable timetable, the instance is normally removed from the registry.
以下示例展示了一个最小的 Eureka Client 应用程序:
The following example shows a minimal Eureka client application:
@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:
Note that the preceding example shows a normal Spring Boot application.
By having spring-cloud-starter-netflix-eureka-client
on the classpath, your application automatically registers with the Eureka Server. Configuration is required to locate the Eureka server, as shown in the following example:
eureka: client: serviceUrl: defaultZone: http://localhost:8761/eureka/
在上述示例中,defaultZone
是一个魔术字符串后备值,它为任何不表达偏好的客户端提供服务 URL(换句话说,它是一个有用的默认值)。
In the preceding example, defaultZone
is a magic string fallback value that provides the service URL for any client that does not express a preference (in other words, it is a useful default).
defaultZone
属性区分大小写且需要驼峰大小写,因为 serviceUrl
属性是 Map<String, String>
。因此,defaultZone
属性不遵循 default-zone
的常规 Spring Boot 蛇形大小写惯例。
The defaultZone
property is case sensitive and requires camel case because the serviceUrl
property is a Map<String, String>
. Therefore, the defaultZone
property does not follow the normal Spring Boot snake-case convention of default-zone
.
默认应用程序名称(即,服务 ID)、虚拟主机和非安全端口(取自 Environment
)分别为 ${spring.application.name}”、“${spring.application.name}
和 ${server.port}
。
The default application name (that is, the service ID), virtual host, and non-secure port (taken from the Environment
) are ${spring.application.name}
, ${spring.application.name}
and ${server.port}
, respectively.
在类路径上有 spring-cloud-starter-netflix-eureka-client
使应用同时成为 Eureka 的“实例
”(即,它注册自身)和“客户端
”(它可以查询注册表以找到其他服务)。该实例行为由 eureka.instance.*
配置键驱动,但是如果确保应用程序有 spring.application.name
的值,则默认值很合适(这是 Eureka 服务 ID 或 VIP 的默认值)。
Having spring-cloud-starter-netflix-eureka-client
on the classpath makes the app into both a Eureka “instance” (that is, it registers itself) and a “client” (it can query the registry to locate other services).
The instance behaviour is driven by eureka.instance.*
configuration keys, but the defaults are fine if you ensure that your application has a value for spring.application.name
(this is the default for the Eureka service ID or 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],了解有关可配置选项的详细信息。
See {github-code}/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/EurekaInstanceConfigBean.java[EurekaInstanceConfigBean] and {github-code}/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/EurekaClientConfigBean.java[EurekaClientConfigBean] for more details on the configurable options.
要禁用 Eureka Discovery Client,可以将 eureka.client.enabled
设置为 false
。当将 spring.cloud.discovery.enabled
设置为 false
时,Eureka Discovery Client 也将被禁用。
To disable the Eureka Discovery Client, you can set eureka.client.enabled
to false
. Eureka Discovery Client will also be disabled when spring.cloud.discovery.enabled
is set to false
.
目前不支持将 Spring Cloud Netflix Eureka 服务器的版本指定为路径参数。这意味着你无法在上下文路径中设置版本 ( |
Specifying the version of the Spring Cloud Netflix Eureka server as a path parameter is not currently supported. This means you cannot set the version in the context path ( |
Authenticating with the Eureka Server
如果 eureka.client.serviceUrl.defaultZone
URL 之一嵌入了凭据(curl 样式,如下所示:https://user:password@localhost:8761/eureka
),则 HTTP 基本认证将自动添加到您的 eureka 客户端。对于更复杂的需求,您可以创建一个 @Bean
类型的 DiscoveryClientOptionalArgs
,并将 ClientFilter
实例注入其中,所有这些都应用于从客户端到服务器的调用。
HTTP basic authentication is automatically added to your eureka client if one of the eureka.client.serviceUrl.defaultZone
URLs has credentials embedded in it (curl style, as follows: https://user:password@localhost:8761/eureka
).
For more complex needs, you can create a @Bean
of type DiscoveryClientOptionalArgs
and inject ClientFilter
instances into it, all of which is applied to the calls from the client to the server.
当 Eureka 服务器需要客户端证书进行身份验证时,客户端证书和信任存储可以通过属性进行配置,如下例所示:
When Eureka server requires client side certificate for authentication, the client side certificate and trust store can be configured via properties, as shown in following example:
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。当省略密码属性时,假定密码为空。
The eureka.client.tls.enabled
needs to be true to enable Eureka client side TLS. When eureka.client.tls.trust-store
is omitted, a JVM default trust store is used. The default value for eureka.client.tls.key-store-type
and eureka.client.tls.trust-store-type
is PKCS12. When password properties are omitted, empty password is assumed.
由于 Eureka 中的限制,无法支持按服务器划分的基于身份验证的凭据,因此仅使用找到的第一组凭据。 |
Because of a limitation in Eureka, it is not possible to support per-server basic auth credentials, so only the first set that are found is used. |
如果您想自定义 Eureka HTTP Client 使用的 RestTemplate,则可能需要创建一个 EurekaClientHttpRequestFactorySupplier
的 bean,并提供您自己的逻辑来生成 ClientHttpRequestFactory
实例。
If you want to customize the RestTemplate used by the Eureka HTTP Client you may want to create a bean of EurekaClientHttpRequestFactorySupplier
and provide your own logic for generating a ClientHttpRequestFactory
instance.
用于 Eureka HTTP 客户端的 RestTemplate 所有的默认超时相关属性均设定为 3 分钟(与 Apache HC5 默认的 RequestConfig
和 SocketConfig
保持一致)。因此,要指定超时值,你必须使用 eureka.client.rest-template-timeout
属性直接指定值。(所有超时属性均以毫秒为单位。)
All default timeout-related properties for RestTemplate used by the Eureka HTTP Client are set to 3 minutes (in keeping with Apache HC5 default RequestConfig
and SocketConfig
). Therefore, to specify the timeout values, you must specify the value directly with the properties in eureka.client.rest-template-timeout
. (All timeout properties are in milliseconds.)
eureka:
client:
rest-template-timeout:
connect-timeout: 5000
connect-request-timeout: 8000
socket-timeout: 10000
在使用默认 Apache HTTP 客户端请求工场时,可使用一个附加参数来配置超时,以逐出空闲连接。默认值为 30 秒。必须以毫秒为单位指定值。
When using the default Apache HTTP Client Request Factory, an additional parameter can be used to configure timeout for evicting idle connections. Default value is 30 seconds. Value must be specified in milliseconds.
eureka:
client:
rest-template-timeout:
idle-timeout: 30000
Status Page and Health Indicator
对于 Eureka 实例,状态页面和运行状况指标的默认值分别为 /info
和 /health
,它们是 Spring Boot Actuator 应用程序中有用端点的默认位置。即使对于 Actuator 应用程序,如果你使用的是非默认上下文路径或 servlet 路径(例如 server.servletPath=/custom
),你也需要更改它们。以下示例显示了这两个设置的默认值:
The status page and health indicators for a Eureka instance default to /info
and /health
respectively, which are the default locations of useful endpoints in a Spring Boot Actuator application.
You need to change these, even for an Actuator application if you use a non-default context path or servlet path (such as server.servletPath=/custom
). The following example shows the default values for the two settings:
eureka: instance: statusPageUrlPath: ${server.servletPath}/info healthCheckUrlPath: ${server.servletPath}/health
这些链接会显示在客户端使用的元数据中,并且在某些情况下用于确定是否将请求发送到你的应用程序,因此,请确保这些链接准确无误。
These links show up in the metadata that is consumed by clients and are used in some scenarios to decide whether to send requests to your application, so it is helpful if they are accurate.
在 Dalston 中,在更改管理上下文的路径时,还需要设置状态和健康检查 URL。从 Edgware 开始,此要求被移除。 |
In Dalston it was also required to set the status and health check URLs when changing that management context path. This requirement was removed beginning in Edgware. |
Registering a Secure Application
如果你的应用程序希望通过 HTTPS 联系,则可以在 EurekaInstanceConfigBean
中设置两个标志:
If your app wants to be contacted over HTTPS, you can set two flags in the EurekaInstanceConfigBean
:
-
eureka.instance.[nonSecurePortEnabled]=[false]
-
eureka.instance.[securePortEnabled]=[true]
执行此操作可使 Eureka 发布显示对安全通信的明显偏好的实例信息。Spring Cloud DiscoveryClient
始终为以此方式配置的服务返回以 https
开头的 URI。同样,当以这种方式配置服务时,Eureka(原生)实例信息具有安全的运行状况检查 URL。
Doing so makes Eureka publish instance information that shows an explicit preference for secure communication.
The Spring Cloud DiscoveryClient
always returns a URI starting with https
for a service configured this way.
Similarly, when a service is configured this way, the Eureka (native) instance information has a secure health check URL.
由于 Eureka 内部工作方式的原因,除非你明确覆盖它们,否则它仍会为状态和主页发布一个非安全 URL。你可以使用占位符来配置 eureka 实例 URL,如下例所示:
Because of the way Eureka works internally, it still publishes a non-secure URL for the status and home pages unless you also override those explicitly. You can use placeholders to configure the eureka instance URLs, as shown in the following example:
eureka: instance: statusPageUrl: https://${eureka.hostname}/info healthCheckUrl: https://${eureka.hostname}/health homePageUrl: https://${eureka.hostname}/
(请注意,${eureka.hostname}
是一个仅在 Eureka 后续版本中可用的本机占位符。你也可以使用 Spring 占位符实现相同的功能,例如,使用 ${eureka.instance.hostName}
。)
(Note that ${eureka.hostname}
is a native placeholder only available
in later versions of Eureka. You could achieve the same thing with
Spring placeholders as well — for example, by using ${eureka.instance.hostName}
.)
如果您的应用程序在代理后面运行,并且 SSL 终止位于代理中(例如,如果您在 Cloud Foundry 或其他平台中作为服务运行),则需要确保代理 “forwarded” 标头被拦截并由应用程序处理。如果嵌入在 Spring Boot 应用程序中的 Tomcat 容器对“X-Forwarded-\*” 标头有明确的配置,则会自动发生这种情况。您的应用程序呈现的指向其自身的链接不正确(错误的主机、端口或协议)表明您将此配置错误。 |
If your application runs behind a proxy, and the SSL termination is in the proxy (for example, if you run in Cloud Foundry or other platforms as a service), then you need to ensure that the proxy “forwarded” headers are intercepted and handled by the application. If the Tomcat container embedded in a Spring Boot application has explicit configuration for the 'X-Forwarded-\*` headers, this happens automatically. The links rendered by your app to itself being wrong (the wrong host, port, or protocol) is a sign that you got this configuration wrong. |
Eureka’s Health Checks
默认情况下,Eureka 使用客户端心跳来确定客户端是否处于正常运行状态。除非另有说明,否则不会传播应用程序的当前运行状况状态,根据 Spring Boot Actuator 应用程序。因此,在成功注册后,Eureka 始终会宣布应用程序处于“正常运行”状态。可以通过启用 Eureka 运行状况检查来更改此行为,这样做会导致将应用程序状态传播到 Eureka。因此,所有其他应用程序都不会向处于“正常运行”状态以外状态的应用程序发送流量。以下示例展示了如何为客户端启用运行状况检查:
By default, Eureka uses the client heartbeat to determine if a client is up. Unless specified otherwise, the Discovery Client does not propagate the current health check status of the application, per the Spring Boot Actuator. Consequently, after successful registration, Eureka always announces that the application is in 'UP' state. This behavior can be altered by enabling Eureka health checks, which results in propagating application status to Eureka. As a consequence, every other application does not send traffic to applications in states other then 'UP'. The following example shows how to enable health checks for the client:
eureka: client: healthcheck: enabled: true
eureka.client.healthcheck.enabled=true
应仅在 application.yml
中设置。在 bootstrap.yml
中设置值会导致不良的副作用,例如以 UNKNOWN
状态在 Eureka 中注册。
eureka.client.healthcheck.enabled=true
should only be set in application.yml
. Setting the value in bootstrap.yml
causes undesirable side effects, such as registering in Eureka with an UNKNOWN
status.
如果你需要对运行状况检查进行更多控制,请考虑实现你自己的 com.netflix.appinfo.HealthCheckHandler
。
If you require more control over the health checks, consider implementing your own com.netflix.appinfo.HealthCheckHandler
.
Eureka Metadata for Instances and Clients
花点时间了解 Eureka 元数据的工作原理是值得的,这样你才能使用它以适合你的平台的方式。用于诸如主机名、IP 地址、端口号、状态页、运行状况检查等信息有标准元数据。这些元数据在服务注册表中发布,并且客户端可以使用这些元数据以直接方式联系服务。可以在 eureka.instance.metadataMap
的实例注册中添加附加元数据,并且可以在远程客户端访问此元数据。通常,附加元数据不会更改客户端的行为,除非将客户端告知元数据含义。在本文档的后面将介绍几种特殊情况,其中 Spring Cloud 已经为元数据映射分配了含义。
It is worth spending a bit of time understanding how the Eureka metadata works, so you can use it in a way that makes sense in your platform.
There is standard metadata for information such as hostname, IP address, port numbers, the status page, and health check.
These are published in the service registry and used by clients to contact the services in a straightforward way.
Additional metadata can be added to the instance registration in the eureka.instance.metadataMap
, and this metadata is accessible in the remote clients.
In general, additional metadata does not change the behavior of the client, unless the client is made aware of the meaning of the metadata.
There are a couple of special cases, described later in this document, where Spring Cloud already assigns meaning to the metadata map.
Using Eureka on Cloud Foundry
Cloud Foundry 有一个全局路由器,这样同一应用程序的所有实例都具有相同的主机名(具有类似架构的其他 PaaS 解决方案也有相同的排列)。这并不一定妨碍使用 Eureka。但是,如果你使用路由器(推荐甚至强制使用,具体取决于你的平台设置方式),则需要明确设置主机名和端口号(安全或非安全),以便使用路由器。你可能还希望使用实例元数据,以便可以在客户端(例如,自定义负载平衡器)上区分实例。默认情况下,eureka.instance.instanceId
为 vcap.application.instance_id
,如下例所示:
Cloud Foundry has a global router so that all instances of the same app have the same hostname (other PaaS solutions with a similar architecture have the same arrangement).
This is not necessarily a barrier to using Eureka.
However, if you use the router (recommended or even mandatory, depending on the way your platform was set up), you need to explicitly set the hostname and port numbers (secure or non-secure) so that they use the router.
You might also want to use instance metadata so that you can distinguish between the instances on the client (for example, in a custom load balancer).
By default, the eureka.instance.instanceId
is vcap.application.instance_id
, as shown in the following example:
eureka: instance: hostname: ${vcap.application.uris[0]} nonSecurePort: 80
根据在 Cloud Foundry 实例中设置安全规则的方式,您也许可以注册并使用主机 VM 的 IP 地址进行直接服务到服务的调用。Pivotal Web Services ( PWS) 尚未提供此功能。
Depending on the way the security rules are set up in your Cloud Foundry instance, you might be able to register and use the IP address of the host VM for direct service-to-service calls. This feature is not yet available on 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] 来完成此操作,如下所示:
If the application is planned to be deployed to an AWS cloud, the Eureka instance must be configured to be AWS-aware. You can do so by customizing the {github-code}/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/EurekaInstanceConfigBean.java[EurekaInstanceConfigBean] as follows:
@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 提供了一个明智的默认值,定义如下:
A vanilla Netflix Eureka instance is registered with an ID that is equal to its host name (that is, there is only one service per host). Spring Cloud Eureka provides a sensible default, which is defined as follows:
${spring.cloud.client.hostname}:${spring.application.name}:${spring.application.instance_id:${server.port}}
一个示例是 myhost:myappname:8080
。
An example is myhost:myappname:8080
.
使用 Spring Cloud,你可以通过在 eureka.instance.instanceId
中提供唯一标识符来覆盖此值,如下例所示:
By using Spring Cloud, you can override this value by providing a unique identifier in eureka.instance.instanceId
, as shown in the following example:
eureka: instance: instanceId: ${spring.application.name}:${vcap.application.instance_id:${spring.application.instance_id:${random.value}}}
在前面示例中显示的元数据和部署在本地主机上的多个服务实例中,会将随机值插入其中,以使实例唯一。在 Cloud Foundry 中,vcap.application.instance_id
会在 Spring Boot 应用程序中自动填充,因此不需要随机值。
With the metadata shown in the preceding example and multiple service instances deployed on localhost, the random value is inserted there to make the instance unique.
In Cloud Foundry, the vcap.application.instance_id
is populated automatically in a Spring Boot application, so the random value is not needed.
Using the EurekaClient
一旦你有一个发现客户端应用程序,你可以使用它从 spring-cloud-eureka-server 中发现服务实例。实现此目的的一种方法是使用本机 com.netflix.discovery.EurekaClient
(与 Spring Cloud DiscoveryClient
相对),如下例所示:
Once you have an application that is a discovery client, you can use it to discover service instances from the spring-cloud-eureka-server.
One way to do so is to use the native com.netflix.discovery.EurekaClient
(as opposed to the Spring Cloud DiscoveryClient
), as shown in the following example:
@Autowired private EurekaClient discoveryClient; public String serviceUrl() { InstanceInfo instance = discoveryClient.getNextServerFromEureka("STORES", false); return instance.getHomePageUrl(); }
不要在 Do not use the |
Underlying HTTP clients
EurekaClient
在幕后使用 RestTemplate
、WebClient
或 JerseyClient
。为了使用 EurekaClient
,你需要在你的类路径上拥有一个受支持的 HTTP 客户端。
EurekaClient
uses either RestTemplate
, WebClient
or JerseyClient
under the hood. In order to use the EurekaClient
, you need to have one of the supported HTTP clients on your classpath.
要使用 RestTemplate
,请将 spring-boot-starter-web
添加到你的依赖项中。要使用 WebClient
,请将 spring-boot-starter-webflux
添加到你的依赖项中。如果当 eureka.client.webclient.enabled
设置为 true
时,RestTemplate
和 WebClient
都在类路径上,则将使用 WebClient
。否则,将使用 RestTemplate
。
To use RestTemplate
, add spring-boot-starter-web
to your dependencies. To use WebClient
, add spring-boot-starter-webflux
to your dependencies. If both RestTemplate
and WebClient
are on the classpath when eureka.client.webclient.enabled
is set to true
, WebClient
is used. Otherwise, RestTemplate
is used.
如果你希望使用 Jersey,你需要将 Jersey 依赖项添加到你的类路径上。以下示例显示了你需要添加的依赖项:
If you wish to use Jersey instead, you need to add the Jersey dependencies to your classpath. The following example shows the dependencies you need to add:
<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客户端构建器)。
You need not use the raw Netflix EurekaClient
.
Also, it is usually more convenient to use it behind a wrapper of some sort.
Spring Cloud has support for spring-cloud-feign (a REST client builder) and Spring Cloud LoadBalancer through the logical Eureka service identifiers (VIPs) instead of physical URLs.
你还可以使用 org.springframework.cloud.client.discovery.DiscoveryClient
,它为发现客户端提供了一个简单的 API(不针对 Netflix),如下例所示:
You can also use the org.springframework.cloud.client.discovery.DiscoveryClient
, which provides a simple API (not specific to Netflix) for discovery clients, as shown in the following example:
@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 的值可以加快客户端连接到其他服务的进程。在生产环境中,最好坚持使用默认值,因为服务器中的内部计算假设了续约期限。
Being an instance also involves a periodic heartbeat to the registry
(through the client’s serviceUrl
) with a default duration of 30 seconds.
A service is not available for discovery by clients until the instance, the server, and the client all have the same metadata in their local
cache (so it could take 3 heartbeats).
You can change the period by setting eureka.instance.leaseRenewalIntervalInSeconds
.
Setting it to a value of less than 30 speeds up the process of getting clients connected to other services.
In production, it is probably better to stick with the default, because of internal computations in the server that make assumptions about the lease renewal period.
Zones
如果你已将 Eureka 客户端部署到多个区域,你可能更希望这些客户端在尝试其他区域中的服务之前使用同一区域中的服务。要进行该设置,你需要正确配置你的 Eureka 客户端。
If you have deployed Eureka clients to multiple zones, you may prefer that those clients use services within the same zone before trying services in another zone. To set that up, you need to configure your Eureka clients correctly.
首先,你需要确保你已将 Eureka 服务器部署到每个区域并且它们彼此是同级。有关更多信息,请参阅 spring-cloud-eureka-server-zones-and-regions 部分。
First, you need to make sure you have Eureka servers deployed to each zone and that they are peers of each other. See the section on spring-cloud-eureka-server-zones-and-regions for more information.
接下来,你需要告诉 Eureka 你的服务位于哪个区域。你可以使用 metadataMap
属性来执行此操作。例如,如果“服务 1”部署在“区域 1”和“区域 2”中,则需要在“服务 1”中设置以下 Eureka 属性:
Next, you need to tell Eureka which zone your service is in.
You can do so by using the metadataMap
property.
For example, if service 1
is deployed to both zone 1
and zone 2
, you need to set the following Eureka properties in service 1
:
区域 1 中的服务 1
Service 1 in Zone 1
eureka.instance.metadataMap.zone = zone1
eureka.client.preferSameZoneEureka = true
区域 2 中的服务 1
Service 1 in Zone 2
eureka.instance.metadataMap.zone = zone2
eureka.client.preferSameZoneEureka = true
Refreshing Eureka Clients
默认情况下,EurekaClient
bean 是可刷新的,这意味着 Eureka 客户端属性可以被更改和刷新。当发生刷新时,客户端将从 Eureka 服务器注销,并且可能有很短的一段时间内给定服务的所有实例不可用。消除这种情况发生的一种方法是禁用刷新 Eureka 客户端的能力。为此,设置 eureka.client.refresh.enable=false
。
By default, the EurekaClient
bean is refreshable, meaning the Eureka client properties can be changed and refreshed.
When a refresh occurs clients will be unregistered from the Eureka server and there might be a brief moment of time
where all instance of a given service are not available. One way to eliminate this from happening is to disable
the ability to refresh Eureka clients. To do this set eureka.client.refresh.enable=false
.
Using Eureka with Spring Cloud LoadBalancer
我们为 Spring Cloud LoadBalancer ZonePreferenceServiceInstanceListSupplier
提供支持。Eureka 实例元数据中的 “区域”值 (eureka.instance.metadataMap.zone
) 用于设置 spring-cloud-loadbalancer-zone
属性,该属性用于按区域筛选服务实例。
We offer support for the Spring Cloud LoadBalancer ZonePreferenceServiceInstanceListSupplier
.
The zone
value from the Eureka instance metadata (eureka.instance.metadataMap.zone
) is used for setting the
value of spring-cloud-loadbalancer-zone
property that is used to filter service instances by zone.
如果缺少该值,并且 spring.cloud.loadbalancer.eureka.approximateZoneFromHostname
标志设置为 true
,它可以使用服务器主机名中的域名作为区域的代理。
If that is missing and if the spring.cloud.loadbalancer.eureka.approximateZoneFromHostname
flag is set to true
,
it can use the domain name from the server hostname as a proxy for the zone.
如果没有其他区域数据源,则会根据客户端配置(而不是实例配置)进行猜测。我们采用 eureka.client.availabilityZones
,它是一个来自区域名称到区域列表的映射,并为实例自己的区域(也就是 eureka.client.region
)提取第一个区域,而 eureka.client.region
的默认值为 “us-east-1”,以便与原生 Netflix 兼容。
If there is no other source of zone data, then a guess is made, based on the client configuration (as opposed to the instance configuration).
We take eureka.client.availabilityZones
, which is a map from region name to a list of zones, and pull out the first zone for the instance’s own region (that is, the eureka.client.region
, which defaults to "us-east-1", for compatibility with native Netflix).
AOT and Native Image Support
Spring Cloud Netflix Eureka Client 集成支持 Spring AOT 转换和原生映像,但是仅在禁用刷新模式时支持。
Spring Cloud Netflix Eureka Client integration supports Spring AOT transformations and native images, however, only with refresh mode disabled.
如果您想在 AOT 或本机映像模式下运行 Eureka Client,请确保将 spring.cloud.refresh.enabled
设置为 false
。
If you want to run Eureka Client in AOT or native image modes, make sure to set spring.cloud.refresh.enabled
to false
Service Discovery: Eureka Server
本部分介绍如何设置 Eureka 服务器。
This section describes how to set up a Eureka server.
How to Include Eureka Server
要在您的项目中包含 Eureka Server,请使用组 ID 为 org.springframework.cloud
且构件 ID 为 spring-cloud-starter-netflix-eureka-server
的入门指南。有关使用当前 Spring Cloud 版本发布版设置构建系统的详细信息,请参见 Spring Cloud Project page。
To include Eureka Server in your project, use the starter with a group ID of org.springframework.cloud
and an artifact ID of spring-cloud-starter-netflix-eureka-server
.
See the Spring Cloud Project page for details on setting up your build system with the current Spring Cloud Release Train.
如果您的项目已使用 Thymeleaf 作为其模板引擎,则 Eureka 服务器的 Freemarker 模板可能无法正确加载。在这种情况下,需要手动配置模板加载器: |
If your project already uses Thymeleaf as its template engine, the Freemarker templates of the Eureka server may not be loaded correctly. In this case it is necessary to configure the template loader manually: |
spring: freemarker: template-loader-path: classpath:/templates/ prefer-file-system-access: false
How to Run a Eureka Server
以下示例展示了一个极简的 Eureka 服务器:
The following example shows a minimal Eureka server:
@SpringBootApplication
@EnableEurekaServer
public class Application {
public static void main(String[] args) {
new SpringApplicationBuilder(Application.class).web(true).run(args);
}
}
该服务器在 /eureka/*
下具有一个带有 UI 和 HTTP API 端点的主页,用于正常的 Eureka 功能。
The server has a home page with a UI and HTTP API endpoints for the normal Eureka functionality under /eureka/*
.
以下链接包含一些 Eureka 背景阅读: flux capacitor 和 google group discussion。
The following links have some Eureka background reading: flux capacitor and google group discussion.
由于 Gradle 的依赖项解析规则和缺少父 bom 特性,依赖于 Due to Gradle’s dependency resolution rules and the lack of a parent bom feature, depending on build.gradle
|
defaultOpenForTrafficCount
and its effect on EurekaServer warmup time
Netflix Eureka 的 waitTimeInMsWhenSyncEmpty
设置开始时不会考虑 Spring Cloud Eureka 服务器。要启用预热时间,请将 eureka.server.defaultOpenForTrafficCount=0
设置为。
Netflix Eureka’s waitTimeInMsWhenSyncEmpty
setting is not taken into account in Spring Cloud Eureka server at the beginning. In order to enable the warmup time, set eureka.server.defaultOpenForTrafficCount=0
.
High Availability, Zones and Regions
Eureka 服务器没有一个后端存储,但注册表中的服务实例必须向其发送心跳才能保持其注册处于最新状态(因此这可以在内存中完成)。客户端还具有一个 Eureka 注册的内存缓存(因此他们不必在每次请求服务时都去注册表)。
The Eureka server does not have a back end store, but the service instances in the registry all have to send heartbeats to keep their registrations up to date (so this can be done in memory). Clients also have an in-memory cache of Eureka registrations (so they do not have to go to the registry for every request to a service).
默认情况下,每个 Eureka 服务器也是一个 Eureka 客户端,并且需要(至少一个)服务 URL 来找到对等服务器。如果您没有提供,该服务会运行并工作,但它会在您的日志中引起很多噪音,因为它无法向对等服务器注册。
By default, every Eureka server is also a Eureka client and requires (at least one) service URL to locate a peer. If you do not provide it, the service runs and works, but it fills your logs with a lot of noise about not being able to register with the peer.
Standalone Mode
只要存在某种监视器或弹性运行时(例如 Cloud Foundry)可以让它保持活动状态,两个缓存(客户端和服务器)和心跳相结合就会让独立的 Eureka 服务器相当有弹性以应对故障。在独立模式下,您可能更愿意关闭客户端行为,以免它不断尝试并无法访问其对等服务器。以下示例显示了如何关闭客户端行为:
The combination of the two caches (client and server) and the heartbeats make a standalone Eureka server fairly resilient to failure, as long as there is some sort of monitor or elastic runtime (such as Cloud Foundry) keeping it alive. In standalone mode, you might prefer to switch off the client side behavior so that it does not keep trying and failing to reach its peers. The following example shows how to switch off the client-side behavior:
server: port: 8761 eureka: instance: hostname: localhost client: registerWithEureka: false fetchRegistry: false serviceUrl: defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
请注意,serviceUrl
指向的与本地实例相同的主机。
Notice that the serviceUrl
is pointing to the same host as the local instance.
Peer Awareness
通过运行多个实例并要求它们彼此注册,可以让 Eureka 变得更有弹性并且随时可用。实际上,这是默认行为,所以您需要做的只是向对等服务器添加一个有效的 serviceUrl
,如下面的示例所示:
Eureka can be made even more resilient and available by running multiple instances and asking them to register with each other.
In fact, this is the default behavior, so all you need to do to make it work is add a valid serviceUrl
to a peer, as shown in the following example:
--- 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
进行查找)。
In the preceding example, we have a YAML file that can be used to run the same server on two hosts (peer1
and peer2
) by running it in different Spring profiles.
You could use this configuration to test the peer awareness on a single host (there is not much value in doing that in production) by manipulating /etc/hosts
to resolve the host names.
In fact, the eureka.instance.hostname
is not needed if you are running on a machine that knows its own hostname (by default, it is looked up by using java.net.InetAddress
).
您可以在系统中添加多个对等服务器,只要它们都通过至少一个边缘彼此连接,它们就会在它们之间同步注册。如果对等服务器在物理上是分离的(在一个数据中心内部或多个数据中心之间),那么从原理上讲,该系统可以在“脑裂”类型的故障中存活下来。您可以在系统中添加多个对等服务器,只要它们都直接彼此连接,它们就会在它们之间同步注册。
You can add multiple peers to a system, and, as long as they are all connected to each other by at least one edge, they synchronize the registrations amongst themselves. If the peers are physically separated (inside a data center or between multiple data centers), then the system can, in principle, survive “split-brain” type failures. You can add multiple peers to a system, and as long as they are all directly connected to each other, they will synchronize the registrations amongst themselves.
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 地址而不是其主机名。
In some cases, it is preferable for Eureka to advertise the IP addresses of services rather than the hostname.
Set eureka.instance.preferIpAddress
to true
and, when the application registers with eureka, it uses its IP address rather than its hostname.
如果无法通过 Java 来确认主机名,那么 IP 地址会被发送到 Eureka。设置 If the hostname cannot be determined by Java, then the IP address is sent to Eureka.
Only explict way of setting the hostname is by setting |
Securing The Eureka Server
您可以简单地通过 spring-boot-starter-security
将 Spring Security 添加到服务器的类路径中来保护您的 Eureka 服务器。 默认情况下,当 Spring Security 在类路径中时,它将要求在发送到应用程序的每个请求中都包含一个有效的 CSRF 标记。Eureka 客户端通常不会拥有有效的跨站点请求伪造 (CSRF) 标记,您需要禁用 /eureka/**
端点的此要求。例如:
You can secure your Eureka server simply by adding Spring Security to your
server’s classpath via spring-boot-starter-security
. By default, when Spring Security is on the classpath it will require that
a valid CSRF token be sent with every request to the app. Eureka clients will not generally possess a valid
cross site request forgery (CSRF) token you will need to disable this requirement for the /eureka/**
endpoints.
For example:
@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。
For more information on CSRF see the Spring Security documentation.
可以在 Spring Cloud Samples 中找到 Eureka Server 演示 repo。
A demo Eureka Server can be found in the Spring Cloud Samples repo.
JDK 11 Support
JDK 11 中删除了 Eureka 服务器所依赖的 JAXB 模块。如果您打算在运行 Eureka 服务器时使用 JDK 11,则必须在您的 POM 或 Gradle 文件中包含这些依赖项。
The JAXB modules which the Eureka server depends upon were removed in JDK 11. If you intend to use JDK 11 when running a Eureka server you must include these dependencies in your POM or Gradle file.
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
</dependency>
Configuration properties
要查看所有 Spring Cloud Netflix 相关配置属性的列表,请查看 the Appendix page。
To see the list of all Spring Cloud Netflix related configuration properties please check the Appendix page.