1.服务发现:Eureka客户
Service Discovery是基于微服务的体系结构的关键原则之一。尝试手动配置每个客户端或某种形式的约定可能很难做到并且可能很脆弱。Eureka是Netflix服务发现服务器和客户端。可以配置和部署服务器以使其具有高可用性,每个服务器将关于已注册服务的状态复制到其他服务器。
1.1如何包含Eureka客户端
要在项目中包含Eureka Client,请使用组ID为ID org.springframework.cloud
且工件ID为的starter spring-cloud-starter-netflix-eureka-client
。有关使用当前Spring Cloud Release Train设置构建系统的详细信息,请参阅Spring Cloud Project页面。
1.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 的默认值),则默认值很好。
有关可配置选项的更多详细信息,请参阅EurekaInstanceConfigBean和EurekaClientConfigBean。
要禁用Eureka Discovery Client,您可以设置eureka.client.enabled
为false
。
1.3使用Eureka Server进行身份验证
如果其中一个eureka.client.serviceUrl.defaultZone
URL中嵌入了凭据,则会自动将HTTP基本身份验证添加到您的eureka客户端(卷曲样式,如下所示:) http://user:password@localhost:8761/eureka
。对于更复杂的需求,您可以创建一个@Bean
类型DiscoveryClientOptionalArgs
并将ClientFilter
实例注入其中,所有这些实例都应用于从客户端到服务器的调用。
由于Eureka的限制,无法支持每服务器基本身份验证凭据,因此仅使用找到的第一个集合。 |
1.4状态页面和健康指标
Eureka实例的状态页面和运行状况指示符分别默认为/info
和/health
Spring Boot Actuator应用程序中有用端点的默认位置。如果使用非默认上下文路径或servlet路径(例如server.servletPath=/custom
),则需要更改这些,即使对于Actuator应用程序也是如此。以下示例显示了两个设置的默认值:
application.yml。
eureka:
instance:
statusPageUrlPath: ${server.servletPath}/info
healthCheckUrlPath: ${server.servletPath}/health
这些链接显示在客户端使用的元数据中,并在某些情况下用于决定是否向您的应用程序发送请求,因此如果它们准确,则会很有帮助。
在Dalston中,还需要在更改管理上下文路径时设置状态和运行状况检查URL。从Edgware开始删除此要求。 |
1.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 - \ *”标头的显式配置,则会自动发生这种情况。您的应用程序呈现给自己错误的链接(错误的主机,端口或协议)表明您的配置错误。 |
1.6尤里卡的健康检查
默认情况下,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
。
1.7实例和客户端的Eureka元数据
值得花些时间了解Eureka元数据的工作原理,因此您可以在平台中使用它。有标准元数据可用于提供主机名,IP地址,端口号,状态页和运行状况检查等信息。这些发布在服务注册表中,客户端使用它们以直接的方式联系服务。可以将附加元数据添加到实例注册中eureka.instance.metadataMap
,并且可以在远程客户端中访问此元数据。通常,除非客户端了解元数据的含义,否则其他元数据不会更改客户端的行为。本文档后面将介绍几种特殊情况,其中Spring Cloud已经为元数据映射赋予了意义。
1.7.1在Cloud Foundry上使用Eureka
Cloud Foundry有一个全局路由器,因此同一个应用程序的所有实例都具有相同的主机名(具有类似架构的其他PaaS解决方案具有相同的安排)。这不一定是使用Eureka的障碍。但是,如果您使用路由器(建议甚至强制使用,具体取决于您的平台的设置方式),您需要明确设置主机名和端口号(安全或非安全),以便他们使用路由器。您可能还希望使用实例元数据,以便区分客户端上的实例(例如,在自定义负载平衡器中)。默认情况下,eureka.instance.instanceId
is vcap.application.instance_id
,如以下示例所示:
application.yml。
eureka:
instance:
hostname: ${vcap.application.uris[0]}
nonSecurePort: 80
根据在Cloud Foundry实例中设置安全规则的方式,您可以注册并使用主机VM的IP地址进行直接服务到服务调用。Pivotal Web Services(PWS)尚未提供此功能。
1.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;
}
1.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}}}
1.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 具有更高阶段的可用。 |
1.8.1没有泽西岛的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>
1.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;
}
1.10为什么注册服务这么慢?
作为实例还涉及到注册表(通过客户端serviceUrl
)的定期心跳,默认持续时间为30秒。在实例,服务器和客户端在其本地缓存中都具有相同的元数据之前,客户端无法发现服务(因此可能需要3次心跳)。您可以通过设置更改期间eureka.instance.leaseRenewalIntervalInSeconds
。将其设置为小于30的值可加快使客户端连接到其他服务的过程。在生产中,最好坚持使用默认值,因为服务器中的内部计算会对租赁续订期做出假设。
1.11区
如果已将Eureka客户端部署到多个区域,则可能希望这些客户端在尝试其他区域中的服务之前使用同一区域内的服务。要进行此设置,您需要正确配置您的Eureka客户端。
首先,您需要确保将Eureka服务器部署到每个区域,并确保它们彼此对等。有关 详细信息,请参阅有关区域和区域的部分。
接下来,您需要告诉Eureka您的服务所在的区域。您可以使用该metadataMap
属性来执行此操作。例如,如果service 1
部署到两zone 1
和zone 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