1. 服务发现:尤里卡客户端

服务发现是基于微服务架构的关键原则之一。 试图手动配置每个客户端或某种约定方式可能很难,而且很脆弱。 Eureka 是 Netflix 服务发现服务器和客户端。 服务器可以配置和部署为高度可用,每个服务器将注册服务的状态复制给其他服务器。spring-doc.cadn.net.cn

1.1. 如何包含Eureka客户端

要在项目中包含 Eureka 客户端,使用带有组 ID 的起始码org.springframework.cloud以及一个伪影IDSpring-cloud-starter-Netflix-Eureka-client. 请参阅 Spring Cloud Project 页面,了解如何使用当前的 Spring Cloud 发布列车来设置你的构建系统。spring-doc.cadn.net.cn

1.2. 在尤里卡注册

当客户端注册 Eureka 时,它会提供关于自身的元数据——如主机、端口、健康指示网址、主页及其他详细信息。 Eureka 会从属于某个服务的每个实例接收心跳消息。 如果心跳在可配置的时间表内失败,该实例通常会从注册表中移除。spring-doc.cadn.net.cn

以下示例展示了一个最小的Eureka客户端应用:spring-doc.cadn.net.cn

@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服务器注册。定位Eureka服务器需要配置,如下示例所示:spring-doc.cadn.net.cn

application.yml
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/

在上述例子中,默认区域是一个神奇字符串的退回值,它为任何不表达偏好的客户端提供服务URL(换句话说,它是有用的默认值)。spring-doc.cadn.net.cn

默认区域财产是大小写区分的,需要骆驼壳,因为服务网址性质是映射<字符串,字符串>.因此,默认区域属性不遵循正常的Spring靴蛇壳约定默认区域.

默认应用名称(即服务ID)、虚拟主机和非安全端口(取自环境)是${spring.application.name},${spring.application.name}${server.port}分别。spring-doc.cadn.net.cn

拥有Spring-cloud-starter-Netflix-Eureka-client在类路径上,应用既是Eureka的“实例”(即它自己注册)也是“客户端”(它可以查询注册表以定位其他服务)。 实例行为由以下因素驱动尤里卡.实例。*配置键,但如果你确保应用有一个值,默认作是可以的spring.application.name(这是尤里卡服务ID或VIP的默认设置)。spring-doc.cadn.net.cn

有关可配置选项的详细信息,请参见 EurekaInstanceConfigBeanEurekaClientConfigBeanspring-doc.cadn.net.cn

要禁用Eureka发现客户端,可以设置Eureka.client.enabledfalse.Eureka Discovery客户端也会被禁用spring.cloud.discovery.enabled设置为false.spring-doc.cadn.net.cn

目前不支持将 Spring Cloud Netflix Eureka 服务器的版本作为路径参数。这意味着你不能在上下文路径中设置版本 (eurekaServerURLContext).相反,你可以在服务器URL中包含版本(例如,你可以设置defaultZone: localhost:8761/eureka/v2).

1.3. 使用Eureka服务器进行身份验证

如果eureka.client.serviceUrl.defaultZoneURLs中嵌入了凭证(卷曲风格,如下:用户:password@localhost:8761/Eureka). 对于更复杂的需求,你可以创建一个@Bean类型DiscoveryClientOptionalArgs并注入客户端过滤器所有这些应用都应用于客户端到服务器的调用。spring-doc.cadn.net.cn

当Eureka服务器要求客户端证书进行认证时,客户端证书和信任存储可以通过属性配置,如下示例所示:spring-doc.cadn.net.cn

application.yml
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需要为真才能启用 Eureka 客户端 TLS。 什么时候Eureka.client.tls.trust-store省略,则使用JVM默认信任存储。默认值为eureka.client.tls.key商店类型Eureka.client.tls.trust-store-type是PKCS12。当密码属性被省略时,假设密码为空。spring-doc.cadn.net.cn

由于 Eureka 的限制,无法支持每服务器的基本认证凭证,因此只使用最先找到的那一组。

如果你想自定义 Eureka HTTP 客户端使用的 RestTemplate,可能需要创建一个EurekaClientHttpRequestFactorySupplier并提供你自己的逻辑来生成ClientHttpRequestFactory实例。spring-doc.cadn.net.cn

Eureka HTTP 客户端使用 RestTemplate 的所有默认超时相关属性都设置为无限。因此,要指定超时值,必须直接用属性 在Eureka.client.rest-template-timeout. (所有超时属性均以毫秒为单位。)spring-doc.cadn.net.cn

application.yml
eureka:
  client:
    rest-template-timeout:
      connect-timeout: 5000
      connect-request-timeout: 8000
      socket-timeout: 10000

1.4. 状态页面与健康指示器

Eureka实例的状态页面和健康指示默认为/信息/健康分别是 Spring Boot 执行器应用中有用端点的默认位置。即使是执行器应用,如果你使用非默认上下文路径或 servlet 路径(例如server.servletPath=/custom). 以下示例展示了两种设置的默认值:spring-doc.cadn.net.cn

application.yml
eureka:
  instance:
    statusPageUrlPath: ${server.servletPath}/info
    healthCheckUrlPath: ${server.servletPath}/health

这些链接会出现在客户端使用的元数据中,在某些情况下用来决定是否向你的应用发送请求,所以如果它们准确无误会很有帮助。spring-doc.cadn.net.cn

在 Dalston 中,更改管理上下文路径时还必须设置状态和健康检查 URL。该管理上下文路径。该要求从 Edgware 开始被取消。

1.5. 注册安全应用

如果你的应用想通过HTTPS联系,你可以在EurekaInstanceConfigBean:spring-doc.cadn.net.cn

这样做会使Eureka发布显示对安全通信偏好的实例信息。春云发现客户端总是返回一个以https对于以这种方式配置的服务。同样,当服务以这种方式配置时,Eureka(本地)实例信息会有一个安全的健康检查 URL。spring-doc.cadn.net.cn

由于 Eureka 内部的工作方式,除非你明确覆盖这些页面,否则它仍然会发布一个不安全的状态和首页 URL。你可以使用占位符来配置 Eureka 实例的 URL,如下示例所示:spring-doc.cadn.net.cn

application.yml
eureka:
  instance:
    statusPageUrl: https://${eureka.hostname}/info
    healthCheckUrl: https://${eureka.hostname}/health
    homePageUrl: https://${eureka.hostname}/

(注意${Eureka.hostname}是仅在Eureka后续版本中提供的原生占位符。你也可以用Spring占位符实现同样的功能——例如,使用${eureka.instance.hostName}.)spring-doc.cadn.net.cn

如果你的应用运行在代理后面,且 SSL 终止在代理中(例如,如果你在 Cloud Foundry 或其他平台中作为服务运行),那么你需要确保代理“转发”的头部被应用程序拦截并处理。如果 Spring Boot 应用中嵌入的 Tomcat 容器对“X-Forwarded-\*”头有明确配置,这会自动发生。应用与自身之间的链接错误(主机、端口或协议错误)表明配置错误。

1.6. 尤里卡的健康检查

默认情况下,Eureka 使用客户端心跳来判断客户端是否已开启。除非另有说明,发现客户端不会根据Spring Boot执行器传播应用程序当前健康检查状态。因此,在成功注册后,Eureka 总是会宣布应用程序处于“UP”状态。通过启用 Eureka 健康检查,可以改变这种行为,从而将应用状态传播到 Eureka。因此,其他所有应用程序不会向状态以外的应用程序发送流量。以下示例展示了如何为客户端启用健康检查:spring-doc.cadn.net.cn

application.yml
eureka:
  client:
    healthcheck:
      enabled: true
Eureka.client.healthcheck.enabled=true只应该设置在application.yml.将值设置在bootstrap.yml会引起不良副作用,例如在Eureka中注册未知地位。

如果你需要对健康检查有更多控制权,可以考虑自己实施com.netflix.appinfo.健康检查处理员.spring-doc.cadn.net.cn

1.7. 实例和客户端的Eureka元数据

花点时间了解Eureka元数据的工作原理是值得的,这样你才能在自己的平台上以合理的方式使用它。 有标准元数据用于存储主机名、IP地址、端口号、状态页面和健康检查等信息。 这些数据会发布在服务登记册中,客户通过这些信息直接联系服务。 可以在实例注册中添加额外的元数据eureka.instance.metadataMap,且这些元数据可在远程客户端访问。 一般来说,除非客户端知道元数据的含义,否则额外的元数据不会改变客户端的行为。 在文档后面会描述几个特殊情况,Spring Cloud 已经为元数据映射赋予了意义。spring-doc.cadn.net.cn

1.7.1. 在Cloud Foundry上使用 Eureka

Cloud Foundry 有一个全局路由器,使同一应用的所有实例拥有相同的主机名(其他架构相似的 PaaS 解决方案也有同样的配置)。 这并不一定是使用Eureka的障碍。 不过,如果你使用路由器(根据你的平台设置,推荐甚至强制使用),你需要明确设置主机名和端口号(安全或非安全),让他们使用路由器。 你可能还想使用实例元数据,以便区分客户端上的实例(例如自定义负载均衡器中)。 默认情况下,eureka.instance.instanceIdvcap.application.instance_id如下例所示:spring-doc.cadn.net.cn

application.yml
eureka:
  instance:
    hostname: ${vcap.application.uris[0]}
    nonSecurePort: 80

根据你Cloud Foundry实例中安全规则的设置方式,你可能可以注册并使用主机虚拟机的IP地址进行服务对服务的直接调用。 此功能尚未在Pivotal Web Services(PWS)上提供。spring-doc.cadn.net.cn

1.7.2. 在 AWS 上使用 Eureka

如果应用计划部署到 AWS 云端,Eureka 实例必须配置为 AWS 支持。您可以通过以下方式自定义 EurekaInstanceConfigBean 来实现:spring-doc.cadn.net.cn

@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;
}

1.7.3. 更改Eureka实例ID

一个普通的Netflix Eureka实例注册的ID与其主机名相等(即每个主机只有一个服务)。 春云尤里卡提供了一个合理的默认,定义如下:spring-doc.cadn.net.cn

${spring.cloud.client.hostname}:${spring.application.name}:${spring.application.instance_id:${server.port}}spring-doc.cadn.net.cn

一个例子是我的主持人:我的应用名:8080.spring-doc.cadn.net.cn

通过使用 Spring Cloud,你可以通过在 中提供唯一标识符来覆盖该值eureka.instance.instanceId如下例所示:spring-doc.cadn.net.cn

application.yml
eureka:
  instance:
    instanceId: ${spring.application.name}:${vcap.application.instance_id:${spring.application.instance_id:${random.value}}}

在前述示例中显示的元数据以及多个服务实例部署于localhost时,插入随机值以使实例唯一。 在云铸造厂中,vcap.application.instance_id在 Spring Boot 应用中会自动填充,因此不需要随机值。spring-doc.cadn.net.cn

1.8. 使用 EurekaClient

一旦你拥有了一个作为发现客户端的应用,就可以用它来发现Eureka服务器上的服务实例。 一种方法是使用原生com.netflix.discovery.Eureka客户端(与春云相对发现客户端),如下例所示:spring-doc.cadn.net.cn

@Autowired
private EurekaClient discoveryClient;

public String serviceUrl() {
    InstanceInfo instance = discoveryClient.getNextServerFromEureka("STORES", false);
    return instance.getHomePageUrl();
}

不要使用尤里卡客户端@PostConstruct方法或在@Scheduled方法(或任何应用上下文可能还没开始。 它初始化为SmartLifecycle(其中相位=0),所以你最早能确定它是否存在的时候,就是在另一个地方SmartLifecycle相位更高。spring-doc.cadn.net.cn

1.8.1. Eureka客户端与Jersey

默认情况下,EurekaClient 使用 Spring 的Rest模板用于HTTP通信。 如果你想用 Jersey,你需要把 Jersey 依赖添加到你的类路径中。 以下示例展示了你需要添加的依赖关系:spring-doc.cadn.net.cn

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

1.9. Netflix 原生 EurekaClient 的替代方案

你不必使用Netflix的原始版尤里卡客户端. 而且通常用包装纸更方便。 Spring Cloud 通过逻辑 Eureka 服务标识符(VIP)而非物理 URL,支持 Feign(一个 REST 客户端构建器)和 Spring Cloud 负载均衡器spring-doc.cadn.net.cn

你也可以使用org.springframework.cloud.client.discovery.DiscoveryClient,该API为发现客户端提供一个简单的API(非Netflix专属),如下示例所示:spring-doc.cadn.net.cn

@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;
}

1.10. 为什么注册服务这么慢?

成为实例还涉及定期的心跳声进入登记处 (通过客户的服务网址)默认持续时间为30秒。 客户端在实例、服务器和客户端的本地元数据相同之前,服务才可供客户端发现 缓存(所以可能需要3个心跳)。 你可以通过设置来改变周期eureka.instance.leaseRenewalIntervalInSeconds. 将其设为小于30可以加快客户端连接其他服务的速度。 在生产环境中,最好还是坚持默认,因为服务器内部会对租约续期进行假设。spring-doc.cadn.net.cn

1.11. 区域

如果你将 Eureka 客户端部署到多个区域,你可能更倾向于让这些客户端先使用同一区域内的服务,再尝试在另一个区域的服务。 要设置好这些,你需要正确配置你的Eureka客户端。spring-doc.cadn.net.cn

首先,你需要确保每个区域都部署了Eureka服务器,并且 他们是彼此的同辈。 更多信息请参见分区和区域部分。spring-doc.cadn.net.cn

接下来,你需要告诉尤里卡你的服务所在的区域。 你可以通过使用元数据地图财产。 例如,如果第一线同时部署到两个平台第一区第二区,你需要在 中设置以下尤里卡属性第一线:spring-doc.cadn.net.cn

1号线在1区spring-doc.cadn.net.cn

eureka.instance.metadataMap.zone = zone1
eureka.client.preferSameZoneEureka = true

第2区的1号线spring-doc.cadn.net.cn

eureka.instance.metadataMap.zone = zone2
eureka.client.preferSameZoneEureka = true

1.12. 刷新尤里卡客户端

默认情况下,尤里卡客户端Bean 是可刷新的,这意味着 Eureka 客户端属性可以被更改和刷新。 刷新发生时,客户端会从Eureka服务器取消注册,可能会有短暂的等待时间 其中并非所有给定服务实例都可用。一种防止这种情况的方法是禁用 能够刷新Eureka客户端。要完成这个集合Eureka.client.refresh.enable=false.spring-doc.cadn.net.cn

1.13. 使用 Eureka 配合 Spring Cloud LoadBalancer

我们支持Spring Cloud负载均衡器ZonePreferenceServiceInstanceListSupplier. 这Eureka 实例元数据中的值(eureka.instance.metadataMap.zone)用于设置 值Spring-云-负载均衡区用于按区域过滤服务实例的属性。spring-doc.cadn.net.cn

如果缺少这个,且如果spring.cloud.loadbalancer.eureka.approximateZoneFromHostname旗帜设置为true, 它可以使用服务器主机名中的域名作为该区域的代理。spring-doc.cadn.net.cn

如果没有其他区域数据来源,则根据客户端配置(而非实例配置)进行猜测。 我们取eureka.client.availabilityZones,即从区域名称到区域列表的映射,并抽出实例自身区域的第一个区域(即Eureka.client.region,默认为“us-east-1”,以兼容原生Netflix)。spring-doc.cadn.net.cn