发博词
Spring Cloud Netflix文档,看这篇文档时,搜几个其中的关键词时,发现了几篇中文翻译,随便看了几段,发现跟翻译机器人翻译的有一拼,估计自己根本就没明白其中的意思,就更别说翻译对了。此文是在意译的基础上,将大部分应该代词直接替换成指代的实际对象,有歧义的地方应该比较少了。根据国内的情况,省略了部分翻译;如果发现有问题或者翻译不对的地方,欢迎留言讨论。
Service Discovery: Eureka Clients
微服务架构的关键准则之一就是有一个服务发现策略。尝试去手动配置或者使用某种形式的约定来确定某个远程服务会导致应用非常脆弱。Eurka提供了服务发现的服务端和客户端两个组件。Eurka服务端可以配置成高可用,某个Eurka服务端可以复制注册的服务信息给其他的Eurka服务端。
How to Include Eureka Client
Registering with Eureka
当一个Eurka客户端注册到一个Eurka服务端时,需要提供关于这个客户端的一些元数据,比如:host、port、health indicator url 地址、home page主页地址等等。Eureka 服务端接收来自注册到这个服务端的各个Eureka 客户端的心跳消息。如果心跳检测超时,Eureka服务端将删除此客户端的注册信息。
[Example eureka client]
上边的代码使用了@EnableEurekaClient为应用开启Eureka客户端的功能,如果你的应用中只有Eureka一种客户端,也可以使用@EnableDiscoveryClient来实现同样的效果。此外,还需要给Eureka客户端指定Eureka服务端的信息。例如:
[application.yml]
可以分别使用${spring.application.name}, ${spring.application.name} and ${server.port}来从Spring Cloud的运行时环境中获取应用的名字(service id)、主机地址和端口号。
@EnableEurekaClient注解把应用转化为一个Eureka Instance(可以自己注册到Eureka服务器,可以被别的服务使用)和一个Eureka Client(可以使用别的服务)。
Eureka Instance的表现用eureka.instance.*格式的配置来控制,但是如果你给应用指定了一个spring.application.name属性的话,大部分情况下,默认值就够用了;spring.application.name的值会被Eureka用来当作这个服务提供者的Service ID。
想查看更多的配置,可以去spring-cloud-netflix-eureka-client模块下面搜索EurekaInstanceConfigBean和EurekaClientConfigBean类来获取更多的信息。
Authenticating with the Eureka Server
如果eureka.client.serviceUrl.defaultZone设置的url,内嵌了身份认证,比如http://user:password@localhost:8761/eureka这样curl风格的格式,HTTP basic authentication认证机制将会被自动添加到Eureka客户端。如果你的需求更复杂,可以使用@Bean注解创建一个DiscoveryClientOptionalArgs 类型的bean,同时注入ClientFilter 的实例给这个bean,这个配置会在每一次Eureka客户端到Eureka服务端的调用中起作用。
Status Page and Health Indicator
一个Eureka Instance的状态页面和健康指示页面的默认地址分别是/info和/health,在一个Spring Boot Actuator的应用中这是默认地址是非常重要的endpoint。
如果你没有使用默认的context path和servlet path (例如:server.servletPath=/foo)或者management endpoint path(例如:management.contextPath=/admin),你需要像下面这样改变这两个配置的值:
[application.yml]
上边的两个配置,在某些场景下,会被用来决定是否给你的应用发送请求,所以正确的设置这两个值是非常有帮助的。
Registering a Secure Application
如果你的应用是通过HTTPS协议访问的,那么你可以设置EurekaInstanceConfig中的两个标志字段, eureka.instance.[nonSecurePortEnabled,securePortEnabled]=[false,true] 。这将明确的告诉Eureka实例通过HTTPS协议发送自身的信息。经过上边的配置,Spring Cloud的DiscoveryClient 将总是返回一个https://开头的url地址。Eureka Instance的health check url地址也将是https://协议的。
上边的配置是配置的Eureka内部的工作方式,对于维护人员需要访问的status url和home page url,除非明确的配置,否则还是HTTP协议的。可以像下面这样覆盖默认的配置:
[application.yml]
Eureka’s Health Checks
默认的,Eureka将会使用心跳来确定一个Eureka客户端是否在线。除非特别指定,Discovery Client 将不会传播应用当前的健康检测状态给Spring Boot Actuator。这也就意味着,当Eureka Client注册成功之后,这个Eureka Instance的实例的状态将不会再改变,一直是UP状态。我们可以通过启用健康检查来,持续的传播应用的状态给Eureka。这样,就只有状态时UP的应用才会接收到请求负载。
[application.yml]
警告:eureka.client.healthcheck.enabled=true应该只在application.yml中被设置。如果设置在bootstrap.yml将会引起不可预知的影响比如注册eureka出现unknown status。
如果你想更多的控制health checks的行为,你可以考虑实现你自己的com.netflix.appinfo.HealthCheckHandler。
Eureka Metadata for Instances and Clients
花一点时间理解一下Eureka元数据是如何工作的是非常值得的,因为有时候,你可能要使用这些元数据做一些有意义的事情。前面提到了一些常用的元数据:hostname、ip、port、status page url、health check等。这些元数据在Eureka Client注册时被推送到Eureka Server,然后其他的客户端在想使用此实例提供的服务时,可以直接连接到此Eureka Instance。通过eureka.instance.metadataMap,我们还可以添加一些其他的元数据,这些元数据同样可以在其他的远程Eureka Client中获取到,但是这些元数据一般来说,不会改变Eureka Client的表现,除非Eureka Client了解这些元数据的意义。
Using Eureka on Cloudfoundry
略。
Using Eureka on AWS
略。
Changing the Eureka Instance ID
一个普通的Netflix Eureka Instance注册到Eureka Server上时的id的值为当前主机的hostname(也就是说,一台机器一个service实例)。但是Spring Cloud Eureka提供了一个更合乎情理的默认值:
例如:
使用Spring Cloud Eureka时,你也可以提供一个唯一标识字符串给eureka.instance.instanceId。例如:
[application.yml]
这样,你就可以在本地部署多个service实例了,最后的随机值将将instanceId的值唯一。
Using the EurekaClient
一旦你的app使用@EnableDiscoveryClient 或者@EnableEurekaClient配置,他将会从Eureka Server发现所有的服务实例。一种方式是使用Eureka原声的API,com.netflix.discovery.EurekaClient,另一种方式是使用Spring Cloud的api DiscoveryClient。
注意
Don’t use the EurekaClient in @PostConstruct method or in a @Scheduled method (or anywhere where the ApplicationContext might not be started yet). It is initialized in a SmartLifecycle (with phase=0) so the earliest you can rely on it being available is in another SmartLifecycle with higher phase.
Alternatives to the native Netflix EurekaClient
略。
Why is it so Slow to Register a Service?
略。
Zones
如果你将所有的Eureka客户端分成多个区域,你可能希望这些客户端在获取其他的服务时,首先尝试同一个区域内的其他服务,在尝试其他区域的其他服务。Eureka提供了这个功能,你只需要正确使用就可以实现这个目标。
首先,你需要确认每个zone都有多个Eureka Server,而且他们互相链接。
下一步你需要做的是告诉Eureka Server你的服务在哪一个zone。可以使用metadataMap 属性来传递这个信息。例如,如果service1部署在zone1和zone2,你需要像下面这样去配置:
[Service 1 in Zone 1]
[Service 1 in Zone 2]
Notice
- EnableEurekaClient和EnableDiscoveryClient的区别?
What’s the difference between EnableEurekaClient and EnableDiscoveryClient?
SpringCLoud中的“Discovery Service”有多种实现,比如:eureka, consul, zookeeper。
1,@EnableDiscoveryClient注解是基于spring-cloud-commons依赖,并且在classpath中实现;
2,@EnableEurekaClient注解是基于spring-cloud-netflix依赖,只能为eureka作用;
如果你的classpath中添加了eureka,则它们的作用是一样的。
- DiscoveryClientOptionalArgs的用法?
com.netflix.discovery.DiscoveryClient.DiscoveryClientOptionalArgs
Service Discovery: Eureka Server
How to Include Eureka Server
How to Run a Eureka Server
[Example eureka server]
High Availability, Zones and Regions
Eureka Server没有后端存储,但是所有注册过的服务实例必须发送心跳消息来更新他们自己的注册信息(这是没有后端存储的原因)。所有的Eureka Client也有一个所有Eureka Client的注册信息的缓存,存储在内存中(所以这些客户端不必在每一次调用其他服务的时候去Eureka Server拉取注册信息)。
默认情况下,每一个Eureka Server也是一个Eureka Client,需要至少一个service url来定位另一Eureka Server。如果没有提供,也能正常工作,但是将会不断的报出日志告诉你不能注册。
Standalone Mode
只要Client和Server活着,Eureka Client和Eureka Server的集合和心跳策略可以使一个Eureka Server能在缓存失效时完全复原。在非集群模式下,你可能更希望关闭Eureka Client不停拉取注册的client的信息的功能,以此来停止获取注册信息持续的失败的情况下继续尝试。
[application.yml (Standalone Eureka Server)]
注意,serviceUrl指向的是当前的Eureka Server实例。
Peer Awareness
Eureka可以通过运行多个实例,互相注册来提高弹性和可用性。事实上,这也是Eureka默认的行为,给一个Eureka Server实例添加一个有效的serviceUrl 就可以使其这么工作了。
[application.yml (Two Peer Aware Eureka Servers)]
上边的样例配置,通过运行在不同的spring profile,可以运行同一个server在两台不同的机器上。你可以使用这个配置文件在一台主机上测试互相发现,想要解析peer1和peer2这两个hostname的话,需要修改本机的hosts文件。事实上,如果你的应用运行在一个知道自己的hostname的机器上(默认会使用java.net.InetAddress获取主机名),eureka.instance.hostname是不用设置的。
你可以在一个系统中添加多个实例,只要他们中的一个至少注册到一个其他任意实例上,他们将会同步所有的注册信息。
Prefer IP Address
对于Eureka,某些情况下,建议使用IP地址而不是hostname。设置eureka.instance.preferIpAddress为true,注册到Eureka Server时,将会使用Ip而不是hostname。