Spring Cloud Document翻译(五)--Eureka

第三部分。Spring Cloud Netflix

1.0.0.BUILD-快照

该项目通过自动配置和Spring环境以及其他Spring编程模型习惯用法为Spring Boot应用程序提供Netflix OSS集成。通过一些简单的注释,您可以快速启用和配置应用程序内的常见模式,并使用经过实战考验的Netflix组件构建大型分布式系统。提供的模式包括服务发现(Eureka),断路器(Hystrix),智能路由(Zuul)和客户端负载平衡(Ribbon)。

11.服务发现:Eureka客户

Service Discovery是基于微服务的体系结构的关键原则之一。尝试手动配置每个客户端或某种形式的约定可能很难做到并且可能很脆弱。Eureka是Netflix服务发现服务器和客户端。可以配置和部署服务器以使其具有高可用性,每个服务器将注册服务的状态复制到其他服务器。

11.1如何包含Eureka客户端

要在项目中包含Eureka Client,请使用具有组ID org.springframework.cloud和工件ID 的starter spring-cloud-starter-netflix-eureka-client。有关使用当前Spring Cloud Release Train设置构建系统的详细信息,请参阅Spring Cloud Project页面

11.2在Eureka注册

当客户向Eureka注册时,它会提供有关自身的元数据 - 例如主机,端口,运行状况指示器URL,主页和其他详细信息。Eureka从属于服务的每个实例接收心跳消息。如果心跳故障超过可配置的时间表,则通常会从注册表中删除该实例。

以下示例显示了最小的Eureka客户端应用程序:

@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服务器需要进行配置,如以下示例所示:

application.yml。 

eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/

 

在前面的示例中,“defaultZone”是一个魔术字符串后备值,它为任何不表示首选项的客户端提供服务URL(换句话说,它是一个有用的默认值)。

默认的应用程序名称(即,服务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 的默认值),则默认值很好。

有关配置选项的更多详细信息,请参阅EurekaInstanceConfigBeanEurekaClientConfigBean

要禁用Eureka Discovery Client,您可以设置eureka.client.enabledfalse。当尤里卡发现客户端也将被禁止spring.cloud.discovery.enabled设置为false

11.3使用Eureka Server进行身份验证

如果其中一个eureka.client.serviceUrl.defaultZoneURL中嵌入了凭据,则会自动将HTTP基本身份验证添加到您的eureka客户端(卷曲样式,如下所示:) http://user:password@localhost:8761/eureka。对于更复杂的需求,您可以创建一个@Bean类型DiscoveryClientOptionalArgs并将ClientFilter实例注入其中,所有这些实例都应用于从客户端到服务器的调用。

[注意]

由于Eureka的限制,无法支持每服务器基本身份验证凭据,因此仅使用找到的第一个集合。

11.4状态页面和健康指标

Eureka实例的状态页面和运行状况指示器分别默认为/info/healthSpring Boot Actuator应用程序中有用端点的默认位置。如果使用非默认上下文路径或servlet路径(例如server.servletPath=/custom),则需要更改这些,即使对于Actuator应用程序也是如此。以下示例显示了两个设置的默认值:

application.yml。 

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

 

这些链接显示在客户端使用的元数据中,并在某些情况下用于决定是否向您的应用程序发送请求,因此如果它们准确,则会很有帮助。

[注意]

在Dalston中,还需要在更改管理上下文路径时设置状态和运行状况检查URL。从Edgware开始删除此要求。

11.5注册安全应用程序

如果您希望通过HTTPS联系您的应用,则可以在以下位置设置两个标志EurekaInstanceConfig

  • eureka.instance.[nonSecurePortEnabled]=[false]
  • eureka.instance.[securePortEnabled]=[true]

这样做会使Eureka发布实例信息,显示对安全通信的明确偏好。对于以这种方式配置的服务,Spring Cloud DiscoveryClient始终返回URI https。同样,当以这种方式配置服务时,Eureka(本机)实例信息具有安全的运行状况检查URL。

由于Eureka在内部工作的方式,它仍然会发布状态和主页的非安全URL,除非您也明确地覆盖这些URL。您可以使用占位符来配置eureka实例URL,如以下示例所示:

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}。)

[注意]

如果您的应用程序在代理后面运行,并且SSL终止在代理中(例如,如果您在Cloud Foundry或其他平台中作为服务运行),那么您需要确保代理“ 转发 ”标头被截获和处理通过申请。如果嵌入在Spring Boot应用程序中的Tomcat容器具有“X-Forwarded - \ *”标头的显式配置,则会自动发生这种情况。您的应用程序呈现给自己错误的链接(错误的主机,端口或协议)表明您的配置错误。

11.6 Eureka的健康检查

默认情况下,Eureka使用客户端心跳来确定客户端是否已启动。除非另有说明,否则Discovery Client不会根据Spring Boot Actuator传播应用程序的当前运行状况检查状态。因此,在成功注册后,Eureka始终宣布应用程序处于“UP”状态。通过启用Eureka运行状况检查可以更改此行为,从而将应用程序状态传播到Eureka。因此,每个其他应用程序都不会向“UP”以外的状态下的应用程序发送流量。以下示例显示如何为客户端启用运行状况检查:

application.yml。 

eureka:
  client:
    healthcheck:
      enabled: true

 

[警告]

eureka.client.healthcheck.enabled=true应该只设置application.yml。设置值bootstrap.yml会导致不良副作用,例如在Eureka中注册UNKNOWN状态。

如果您需要更多控制健康检查,请考虑实施自己的健康检查com.netflix.appinfo.HealthCheckHandler

11.7实例和客户端的Eureka元数据

值得花一点时间了解Eureka元数据的工作原理,因此您可以在平台中使用它。存在标准元数据,用于提供主机名,IP地址,端口号,状态页和运行状况检查等信息。这些发布在服务注册表中,客户端使用它们以直接的方式联系服务。可以将附加元数据添加到实例注册中eureka.instance.metadataMap,并且可以在远程客户端中访问此元数据。通常,除非客户端了解元数据的含义,否则其他元数据不会更改客户端的行为。本文稍后将介绍几种特殊情况,其中Spring Cloud已经为元数据映射赋予了意义。

11.7.1在Cloud Foundry上使用Eureka

Cloud Foundry有一个全局路由器,因此同一个应用程序的所有实例都具有相同的主机名(具有类似架构的其他PaaS解决方案具有相同的安排)。这不一定是使用Eureka的障碍。但是,如果您使用路由器(建议甚至强制使用,具体取决于您的平台的设置方式),您需要明确设置主机名和端口号(安全或非安全),以便他们使用路由器。您可能还希望使用实例元数据,以便区分客户端上的实例(例如,在自定义负载平衡器中)。默认情况下,eureka.instance.instanceIdis vcap.application.instance_id,如以下示例所示:

application.yml。 

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

 

根据在Cloud Foundry实例中设置安全规则的方式,您可以注册并使用主机VM的IP地址进行直接的服务到服务调用。Pivotal Web Services(PWS)尚未提供此功能。

11.7.2在AWS上使用Eureka

如果计划将应用程序部署到AWS云,则必须将Eureka实例配置为支持AWS。您可以通过自定义EurekaInstanceConfigBean来执行此操作,如下所示:

@Bean
@Profile("!default")
public EurekaInstanceConfigBean eurekaInstanceConfig(InetUtils inetUtils) {
  EurekaInstanceConfigBean b = new EurekaInstanceConfigBean(inetUtils);
  AmazonInfo info = AmazonInfo.Builder.newBuilder().autoBuild("eureka");
  b.setDataCenterInfo(info);
  return b;
}

11.7.3更改Eureka实例ID

一个vanilla Netflix Eureka实例注册的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,如以下示例所示:

application.yml。 

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

 

使用前面示例中显示的元数据和部署在localhost上的多个服务实例,将随机值插入其中以使实例唯一。在Cloud Foundry中,vcap.application.instance_id会自动在Spring Boot应用程序中填充,因此不需要随机值。

11.8使用EurekaClient

一旦您拥有作为发现客户端的应用程序,就可以使用它从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();
}
[小费]

不要EurekaClient@PostConstruct方法或@Scheduled方法中使用(或者ApplicationContext可能尚未启动的任何地方)。它在SmartLifecycle(with phase=0)中初始化,因此最早可以依赖它的是另一个SmartLifecycle具有更高阶段的可用。

11.8.1没有Jersey的EurekaClient

默认情况下,EurekaClient使用Jersey进行HTTP通信。如果您希望避免来自Jersey的依赖项,则可以将其从依赖项中排除。Spring Cloud基于Spring自动配置传输客户端RestTemplate。以下示例显示Jersey被排除在外:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    <exclusions>
        <exclusion>
            <groupId>com.sun.jersey</groupId>
            <artifactId>jersey-client</artifactId>
        </exclusion>
        <exclusion>
            <groupId>com.sun.jersey</groupId>
            <artifactId>jersey-core</artifactId>
        </exclusion>
        <exclusion>
            <groupId>com.sun.jersey.contribs</groupId>
            <artifactId>jersey-apache-client4</artifactId>
        </exclusion>
    </exclusions>
</dependency>

11.9 Native Netflix EurekaClient的替代方案

您无需使用原始Netflix EurekaClient。此外,在某种包装后面使用它通常更方便。Spring Cloud 通过逻辑Eureka服务标识符(VIP)而不是物理URL 支持Feign(REST客户端构建器)和SpringRestTemplate。要使用固定的物理服务器列表配置功能区,可以设置<client>.ribbon.listOfServers以逗号分隔的物理地址(或主机名)列表,其中<client>是客户端的ID。

您还可以使用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;
}

11.10为什么注册服务这么慢?

作为实例还涉及到注册表(通过客户端serviceUrl)的定期心跳,默认持续时间为30秒。在实例,服务器和客户端在其本地缓存中都具有相同的元数据之前,客户端无法发现服务(因此可能需要3次心跳)。您可以通过设置更改期间eureka.instance.leaseRenewalIntervalInSeconds。将其设置为小于30的值会加快使客户端连接到其他服务的过程。在生产中,最好坚持使用默认值,因为服务器中的内部计算会对租赁续订期做出假设。

11.11区域

如果已将Eureka客户端部署到多个区域,则可能希望这些客户端在尝试其他区域中的服务之前使用同一区域内的服务。要进行此设置,您需要正确配置Eureka客户端。

首先,您需要确保将Eureka服务器部署到每个区域,并确保它们彼此对等。有关 详细信息,请参阅有关区域和区域的部分。

接下来,您需要告诉Eureka您的服务所在的区域。您可以使用该metadataMap属性来执行此操作。例如,如果service 1部署到两zone 1zone 2,你需要设置以下尤里卡特性service 1

1区的服务1

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

2区服务1

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

11.12刷新Eureka Client

默认情况下,EurekaClientbean是可刷新的,这意味着可以更改和刷新Eureka客户端属性。当刷新发生时,客户端将从Eureka服务器取消注册,并且可能存在短暂的时间,其中给定服务的所有实例都不可用。消除这种情况的一种方法是禁用刷新Eureka客户端的能力。要做这个设置eureka.client.refresh.enable=false

 

12.服务发现:Eureka Server

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

12.1如何包含Eureka服务器

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

[注意]

如果您的项目已使用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功能的UI和HTTP API端点/eureka/*

以下链接有一些Eureka背景阅读:磁通电容谷歌小组讨论

[小费]

由于Gradle的依赖关系解析规则和缺少父bom功能,取决于spring-cloud-starter-netflix-eureka-server可能导致应用程序启动失败。要解决此问题,请添加Spring Boot Gradle插件并导入Spring cloud starter parent 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服务器没有后端存储,但注册表中的服务实例都必须发送心跳以使其注册保持最新(因此可以在内存中完成)。客户端还有一个Eureka注册的内存缓存(因此,他们不必为服务的每个请求转到注册表)。

默认情况下,每个Eureka服务器也是Eureka客户端,并且需要(至少一个)服务URL来定位对等体。如果您不提供该服务,该服务将运行并正常运行,但它会在您的日志中填充很多关于无法向对等方注册的噪音。

有关区域和区域的客户端功能区支持的详细信息,请参见下文

12.4独立模式

两个缓存(客户端和服务器)和心跳的组合使得独立的Eureka服务器能够非常适应故障,只要有某种监视器或弹性运行时(例如Cloud Foundry)使其保持活动状态即可。在独立模式下,您可能更愿意关闭客户端行为,以便它不会继续尝试并且无法访问其对等方。以下示例显示如何关闭客户端行为:

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(两个Peer Aware 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文件,可以用于在两个主机(peer1peer2)上运行相同的服务器,方法是在不同的Spring配置文件中运行它。您可以使用此配置通过操作/etc/hosts来解析主机名来测试单个主机上的对等感知(在生产中执行此操作没有太大价值)。实际上,eureka.instance.hostname如果您在知道自己的主机名的计算机上运行,则不需要它(默认情况下,通过使用查找它java.net.InetAddress)。

您可以将多个对等体添加到系统中,并且只要它们通过至少一个边缘彼此连接,它们就会在它们之间同步注册。如果对等体在物理上是分开的(在数据中心内或在多个数据中心之间),那么系统原则上可以存在“ 裂脑 ”类型的故障。您可以向系统添加多个对等体,只要它们彼此直接连接,它们就会在它们之间同步注册。

application.yml(Three Peer Aware Eureka Servers)。 

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.preferIpAddresstrue,当应用程序向eureka注册时,它使用其IP地址而不是其主机名。

[小费]

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

12.7保护Eureka服务器

只需将Spring Security添加到服务器的类路径中即可保护您的Eureka服务器spring-boot-starter-security。默认情况下,当Spring Security位于类路径上时,它将要求在应用程序的每个请求中发送有效的CSRF令牌。Eureka客户端通常不会拥有有效的跨站点请求伪造(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 回购中找到演示Eureka Server 。

12.8 JDK 11支持

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

<dependency>
	<groupId>org.glassfish.jaxb</groupId>
	<artifactId>jaxb-runtime</artifactId>
</dependency>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章