1. 服务发现:尤里卡客户端
服务发现是基于微服务架构的关键原则之一。 试图手动配置每个客户端或某种约定方式可能很难,而且很脆弱。 Eureka 是 Netflix 服务发现服务器和客户端。 服务器可以配置和部署为高度可用,每个服务器将注册服务的状态复制给其他服务器。
1.1. 如何包含Eureka客户端
要在项目中包含 Eureka 客户端,使用带有组 ID 的起始码org.springframework.cloud以及一个伪影IDSpring-cloud-starter-Netflix-Eureka-client.
请参阅 Spring Cloud Project 页面,了解如何使用当前的 Spring Cloud 发布列车来设置你的构建系统。
1.2. 在尤里卡注册
当客户端注册 Eureka 时,它会提供关于自身的元数据——如主机、端口、健康指示网址、主页及其他详细信息。 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服务器注册。定位Eureka服务器需要配置,如下示例所示:
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
在上述例子中,默认区域是一个神奇字符串的退回值,它为任何不表达偏好的客户端提供服务URL(换句话说,它是有用的默认值)。
这默认区域财产是大小写区分的,需要骆驼壳,因为服务网址性质是映射<字符串,字符串>.因此,默认区域属性不遵循正常的Spring靴蛇壳约定默认区域. |
默认应用名称(即服务ID)、虚拟主机和非安全端口(取自环境)是${spring.application.name},${spring.application.name}和${server.port}分别。
拥有Spring-cloud-starter-Netflix-Eureka-client在类路径上,应用既是Eureka的“实例”(即它自己注册)也是“客户端”(它可以查询注册表以定位其他服务)。
实例行为由以下因素驱动尤里卡.实例。*配置键,但如果你确保应用有一个值,默认作是可以的spring.application.name(这是尤里卡服务ID或VIP的默认设置)。
有关可配置选项的详细信息,请参见 EurekaInstanceConfigBean 和 EurekaClientConfigBean。
要禁用Eureka发现客户端,可以设置Eureka.client.enabled自false.Eureka Discovery客户端也会被禁用spring.cloud.discovery.enabled设置为false.
目前不支持将 Spring Cloud Netflix Eureka 服务器的版本作为路径参数。这意味着你不能在上下文路径中设置版本 (eurekaServerURLContext).相反,你可以在服务器URL中包含版本(例如,你可以设置defaultZone: localhost:8761/eureka/v2). |
1.3. 使用Eureka服务器进行身份验证
如果eureka.client.serviceUrl.defaultZoneURLs中嵌入了凭证(卷曲风格,如下:用户:password@localhost:8761/Eureka).
对于更复杂的需求,你可以创建一个@Bean类型DiscoveryClientOptionalArgs并注入客户端过滤器所有这些应用都应用于客户端到服务器的调用。
当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需要为真才能启用 Eureka 客户端 TLS。 什么时候Eureka.client.tls.trust-store省略,则使用JVM默认信任存储。默认值为eureka.client.tls.key商店类型和Eureka.client.tls.trust-store-type是PKCS12。当密码属性被省略时,假设密码为空。
| 由于 Eureka 的限制,无法支持每服务器的基本认证凭证,因此只使用最先找到的那一组。 |
如果你想自定义 Eureka HTTP 客户端使用的 RestTemplate,可能需要创建一个EurekaClientHttpRequestFactorySupplier并提供你自己的逻辑来生成ClientHttpRequestFactory实例。
Eureka HTTP 客户端使用 RestTemplate 的所有默认超时相关属性都设置为无限。因此,要指定超时值,必须直接用属性 在Eureka.client.rest-template-timeout. (所有超时属性均以毫秒为单位。)
eureka:
client:
rest-template-timeout:
connect-timeout: 5000
connect-request-timeout: 8000
socket-timeout: 10000
1.4. 状态页面与健康指示器
Eureka实例的状态页面和健康指示默认为/信息和/健康分别是 Spring Boot 执行器应用中有用端点的默认位置。即使是执行器应用,如果你使用非默认上下文路径或 servlet 路径(例如server.servletPath=/custom). 以下示例展示了两种设置的默认值:
eureka:
instance:
statusPageUrlPath: ${server.servletPath}/info
healthCheckUrlPath: ${server.servletPath}/health
这些链接会出现在客户端使用的元数据中,在某些情况下用来决定是否向你的应用发送请求,所以如果它们准确无误会很有帮助。
| 在 Dalston 中,更改管理上下文路径时还必须设置状态和健康检查 URL。该管理上下文路径。该要求从 Edgware 开始被取消。 |
1.5. 注册安全应用
如果你的应用想通过HTTPS联系,你可以在EurekaInstanceConfigBean:
-
eureka.instance。[nonSecurePortEnabled]=[false] -
eureka.instance。[securePortEnabled]=[true]
这样做会使Eureka发布显示对安全通信偏好的实例信息。春云发现客户端总是返回一个以https对于以这种方式配置的服务。同样,当服务以这种方式配置时,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 或其他平台中作为服务运行),那么你需要确保代理“转发”的头部被应用程序拦截并处理。如果 Spring Boot 应用中嵌入的 Tomcat 容器对“X-Forwarded-\*”头有明确配置,这会自动发生。应用与自身之间的链接错误(主机、端口或协议错误)表明配置错误。 |
1.6. 尤里卡的健康检查
默认情况下,Eureka 使用客户端心跳来判断客户端是否已开启。除非另有说明,发现客户端不会根据Spring Boot执行器传播应用程序当前健康检查状态。因此,在成功注册后,Eureka 总是会宣布应用程序处于“UP”状态。通过启用 Eureka 健康检查,可以改变这种行为,从而将应用状态传播到 Eureka。因此,其他所有应用程序不会向状态以外的应用程序发送流量。以下示例展示了如何为客户端启用健康检查:
eureka:
client:
healthcheck:
enabled: true
Eureka.client.healthcheck.enabled=true只应该设置在application.yml.将值设置在bootstrap.yml会引起不良副作用,例如在Eureka中注册未知地位。 |
如果你需要对健康检查有更多控制权,可以考虑自己实施com.netflix.appinfo.健康检查处理员.
1.7. 实例和客户端的Eureka元数据
花点时间了解Eureka元数据的工作原理是值得的,这样你才能在自己的平台上以合理的方式使用它。
有标准元数据用于存储主机名、IP地址、端口号、状态页面和健康检查等信息。
这些数据会发布在服务登记册中,客户通过这些信息直接联系服务。
可以在实例注册中添加额外的元数据eureka.instance.metadataMap,且这些元数据可在远程客户端访问。
一般来说,除非客户端知道元数据的含义,否则额外的元数据不会改变客户端的行为。
在文档后面会描述几个特殊情况,Spring Cloud 已经为元数据映射赋予了意义。
1.7.1. 在Cloud Foundry上使用 Eureka
Cloud Foundry 有一个全局路由器,使同一应用的所有实例拥有相同的主机名(其他架构相似的 PaaS 解决方案也有同样的配置)。
这并不一定是使用Eureka的障碍。
不过,如果你使用路由器(根据你的平台设置,推荐甚至强制使用),你需要明确设置主机名和端口号(安全或非安全),让他们使用路由器。
你可能还想使用实例元数据,以便区分客户端上的实例(例如自定义负载均衡器中)。
默认情况下,eureka.instance.instanceId是vcap.application.instance_id如下例所示:
eureka:
instance:
hostname: ${vcap.application.uris[0]}
nonSecurePort: 80
根据你Cloud Foundry实例中安全规则的设置方式,你可能可以注册并使用主机虚拟机的IP地址进行服务对服务的直接调用。 此功能尚未在Pivotal Web Services(PWS)上提供。
1.7.2. 在 AWS 上使用 Eureka
如果应用计划部署到 AWS 云端,Eureka 实例必须配置为 AWS 支持。您可以通过以下方式自定义 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;
}
1.7.3. 更改Eureka实例ID
一个普通的Netflix Eureka实例注册的ID与其主机名相等(即每个主机只有一个服务)。 春云尤里卡提供了一个合理的默认,定义如下:
${spring.cloud.client.hostname}:${spring.application.name}:${spring.application.instance_id:${server.port}}
一个例子是我的主持人:我的应用名:8080.
通过使用 Spring Cloud,你可以通过在 中提供唯一标识符来覆盖该值eureka.instance.instanceId如下例所示:
eureka:
instance:
instanceId: ${spring.application.name}:${vcap.application.instance_id:${spring.application.instance_id:${random.value}}}
在前述示例中显示的元数据以及多个服务实例部署于localhost时,插入随机值以使实例唯一。
在云铸造厂中,vcap.application.instance_id在 Spring Boot 应用中会自动填充,因此不需要随机值。
1.8. 使用 EurekaClient
一旦你拥有了一个作为发现客户端的应用,就可以用它来发现Eureka服务器上的服务实例。
一种方法是使用原生com.netflix.discovery.Eureka客户端(与春云相对发现客户端),如下例所示:
@Autowired
private EurekaClient discoveryClient;
public String serviceUrl() {
InstanceInfo instance = discoveryClient.getNextServerFromEureka("STORES", false);
return instance.getHomePageUrl();
}
|
不要使用 |
1.8.1. Eureka客户端与Jersey
默认情况下,EurekaClient 使用 Spring 的Rest模板用于HTTP通信。
如果你想用 Jersey,你需要把 Jersey 依赖添加到你的类路径中。
以下示例展示了你需要添加的依赖关系:
<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 负载均衡器。
你也可以使用org.springframework.cloud.client.discovery.DiscoveryClient,该API为发现客户端提供一个简单的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. 为什么注册服务这么慢?
成为实例还涉及定期的心跳声进入登记处
(通过客户的服务网址)默认持续时间为30秒。
客户端在实例、服务器和客户端的本地元数据相同之前,服务才可供客户端发现
缓存(所以可能需要3个心跳)。
你可以通过设置来改变周期eureka.instance.leaseRenewalIntervalInSeconds.
将其设为小于30可以加快客户端连接其他服务的速度。
在生产环境中,最好还是坚持默认,因为服务器内部会对租约续期进行假设。
1.11. 区域
如果你将 Eureka 客户端部署到多个区域,你可能更倾向于让这些客户端先使用同一区域内的服务,再尝试在另一个区域的服务。 要设置好这些,你需要正确配置你的Eureka客户端。
首先,你需要确保每个区域都部署了Eureka服务器,并且 他们是彼此的同辈。 更多信息请参见分区和区域部分。
接下来,你需要告诉尤里卡你的服务所在的区域。
你可以通过使用元数据地图财产。
例如,如果第一线同时部署到两个平台第一区和第二区,你需要在 中设置以下尤里卡属性第一线:
1号线在1区
eureka.instance.metadataMap.zone = zone1
eureka.client.preferSameZoneEureka = true
第2区的1号线
eureka.instance.metadataMap.zone = zone2
eureka.client.preferSameZoneEureka = true
1.12. 刷新尤里卡客户端
默认情况下,尤里卡客户端Bean 是可刷新的,这意味着 Eureka 客户端属性可以被更改和刷新。
刷新发生时,客户端会从Eureka服务器取消注册,可能会有短暂的等待时间
其中并非所有给定服务实例都可用。一种防止这种情况的方法是禁用
能够刷新Eureka客户端。要完成这个集合Eureka.client.refresh.enable=false.
1.13. 使用 Eureka 配合 Spring Cloud LoadBalancer
我们支持Spring Cloud负载均衡器ZonePreferenceServiceInstanceListSupplier.
这区Eureka 实例元数据中的值(eureka.instance.metadataMap.zone)用于设置
值Spring-云-负载均衡区用于按区域过滤服务实例的属性。
如果缺少这个,且如果spring.cloud.loadbalancer.eureka.approximateZoneFromHostname旗帜设置为true,
它可以使用服务器主机名中的域名作为该区域的代理。
如果没有其他区域数据来源,则根据客户端配置(而非实例配置)进行猜测。
我们取eureka.client.availabilityZones,即从区域名称到区域列表的映射,并抽出实例自身区域的第一个区域(即Eureka.client.region,默认为“us-east-1”,以兼容原生Netflix)。