在分析了Eureka的部分源码之后,相信大家对Eureka的服务治理机制已经有了进一步的理解。在本节中,我们从使用的角度对Eureka中的一些常用配置内容进行详细的介绍,以帮助我们根据自身环境与业务特点来进行个性化的配置调整。
在Eureka的服务治理体系中,主要分为服务端与客户端两个不同的角色,服务端为服务注册中心,而客户端为各个提供接口的微服务应用。当我们构建了高可用的注册中心之后,该集群中所有的微服务应用和后续将要介绍的一些基础类应用(如配置中心、API网关等)都可以视作该体系下的一个微服务(Eureka客户端)。服务注册中心也一样,只是高可用环境下的服务注册中心除了作为客户端之外,还为集群中的其他客户端提供了服务注册的特殊功能。所以,Eureka客户端的配置对象存在于所有Eureka服务治理体系下的应用实例中。在实际使用Spring Cloud Eureka 的过程中,我们所做的配置内容几乎都是对Eureka客户端配置进行操作,所以了解这部分的配置内容,对于用好Eureka非常有帮助。
Eureka客户端的主要配置分为以下两个方面。
- 服务注册相关的配置信息,包括服务注册中心的地址、服务获取的时间间隔、可用区域等。
- 服务实例相关的配置信息,包括服务实例的名称、IP地址,端口号,健康检查路径等。
而Eureka服务端更多地类似于一个现成产品,大多数情况下,我们不需要修改它的配置信息。所以在本书中,我们对此不进行过多的介绍,有兴趣的读者可以查看org.springframework.cloud.netflix.eureka.server.EurekaServerConfigBean类的定义来做进一步学习,这些参数均以eureka.server作为前缀。另外值得一提的是,我们在学习本书内容进行本地调试的时候,可以通过设置该类中的enableSelfPerservation参数来关闭注册中心的“自我保护”功能,以防止关闭的实例无法被服务注册中心剔除的问题,这一点我们在“服务治理机制”一节中也有所介绍。
服务注册配置
关于服务类的配置信息,我们可以通过查看org.springframework.cloud.netflix.eureka.EurekaClientConfigBean的源码来获得比官网文档更为详尽的内容,这些配置信息都以eureka.client为前缀,下面我们针对一些常用的配置信息做进一步的介绍和说明。
指定注册中心
在本章第1节的示例中,我们演示了如何将一个Spring Boot应用纳入Eureka的服务治理体系中,除了引入Eureka的依赖之外,就是在配置文件中指定注册中心,主要通过eureka.client.serviceUrl参数实现,该参数的定义如下所示,他的配置值存储在HashMap类型中,并且设有一组默认值,其默认值的key为DefaultZone、value为http://localhost:8761/eureka/。
private Map<String, String> serviceUrl = new HashMap<>();
{
this.serviceUrl.put(DEFAULT_ZONE, DEFAULT_URL);
}
public static final String DEFAULT_URL = "http://localhost:8761" + DEFAULT_PREFIX + "/";
public staitc final String DEFAULT_ZONE = "defaultZone";
由于之前实现的服务注册中心使用了1111端口,所以我们做了如下的配置,来讲应用注册到对应的Eureka服务端中。
eureka.client.serviceUrl.defaultZone=http://localhost:1111/eureka/
当我们构建了高可用服务注册中心集群时,我们可以为参数的value配置多个注册中心的地址(通过逗号分隔)。比如下面的例子:
eureka.client.serviceUrl.defaultZone=http://peer1:1111/eureka/ ,http://peer2:1112/eureka/
另外,为了服务注册中心的安全考虑,很多时候我们都会为服务注册中心加入安全校验,这个时候,在配置serviceUrl时,需要在value值的URL中加入相应的安全校验信息,比如http://<username>:<password>@localhost:1111/eureka。其中,<username>为安全信息校验的用户名,<password>为该用户的密码。
其他配置
下面整理了org.springframework.cloud.netflix.eureka.EurekaClientConfigBean中定义的常量配置参数以及对应的说明和默认值,这些参数均以eureka.client为前缀。
这些常用配置均已eureka.client
为前缀。
参数名 | 说明 | 默认值 |
---|---|---|
enabled | 启用Eureka客户端 | true |
registryFetchIntervalSeconds | 从Eureka服务端获取注册信息的间隔时间,单位为秒 | 30 |
instanceInfoReplicationIntervalSeconds | 更新实例信息的变化到Eureka服务端的间隔时间,单位为秒 | 30 |
initialInstanceInfoReplicationIntervalSeconds | 初始化实例信息到Eureka服务端的间隔时间,单位为秒 | 40 |
eurekaServiceUrlPollIntervalSeconds | 轮询Eureka服务端地址更改的间隔时间,单位为秒。当我们与Spring CLoud Config整合,动态刷新Eureka的serviceURL地址时需要关注该参数 | 300 |
eurekaServerReadTimeoutSeconds | 读取Eureka Server信息的超时时间,单位为秒 | 8 |
eurekaServerConnectTimeoutSeconds | 链接Eureka Server的超时时间,单位为秒 | 5 |
eurekaServerTotalConnections | 从Eureka客户端到所有Eureka服务端的连接总数 | 200 |
eurekaServerTotalConnectionsPerHost | 从Eureka客户端到每个Eureka服务端主机的连接总数 | 50 |
eurekaConnectionIdleTimeoutSeconds | Eureka服务端连接的空闲关闭时间,单位为秒 | 30 |
heartbeatExecutorThreadPoolSize | 心跳连接池的初始化线程数 | 2 |
heartbeatExecutorExponentialBackOffBound | 心跳超时重试延迟时间的最大乘数值 | 10 |
cacheRefreshExecutorThreadPoolSize | 缓存刷新线程池的初始化线程数 | 2 |
cacheRefreshExecutorExponentialBackOffBound | 缓存刷新重试延迟时间的最大乘数值 | 10 |
useDnsForFetchingServiceUrls | 使用DNS来获取Eureka服务端的serviceUrl | false |
registerWithEureka | 是否要将自身的实例信息注册到Eureka服务端 | true |
preferSameZoneEureka | 是否偏好使用处于相同Zone的Eureka服务端 | true |
filterOnlyUpInstances | 获取实例时是否过滤,仅保留UP状态的实例 | true |
fetchRegistry | 是否从Eureka服务端获取注册信息 | true |
服务实例类配置
关于服务实例类配置信息,我们可以通过查看org.springframework.cloud.netflix.eureka.EurekaInstanceConfigBean
的源码来获取详细内容,这些配置信息都以eureka.instance
为前缀。下面我们针对一些常用的配置信息做一些详细的说明。
元数据
在org.springframework.cloud.netflix.eureka.EurekaInstanceConfigBean
的配置实例中有一大部分内容是对服务实例元数据的配置,那么什么是服务实例的元数据呢?它是Eureka客户端在向服务注册中心发送注册请求时,用来描述自身服务信息的对象,其中包含了一些标准化的元数据,比如服务名称,实例名称,实例IP,实例端口等用于服务治理的重要信息,以及一些用于负载均衡策略或是其他特殊用途的自定义元数据信息。
在使用SpringCloudEureka的时候,所有的配置信息都通过org.springframework.cloud.netflix.eureka.EurekaInstanceConfigBean进行加载,但在真正进行服务注册的时候,还是会包装成com.netflix.appinfo.InstanceInfo对象发送给Eureka服务端。这两个的定义非常相似,我们可以直接查看com.netflix.appinfo.InstanceInfo类中的详细定义来了解原生Eureka对元数据的定义。其中,Map<String, String> metadata = new ConcurrentHashMap<String, String>()是自定义的元数据信息,而其他成员变量则是标准化的元数据信息。Spring Cloud的EurekaInstanceConfigBean对原生数据对象做了一些配置优化处理,在后续的介绍中,我们也会提到这些内容。
我们可以通过eureka.instance.<properties>=<value>的格式对标准化元数据直接进行配置,其中<properties>就是EurekaInstanceConfigBean对象中的成员变量名,而对于自定义元数据,可以通过
eureka.instance.metadataMap.<key>=<value>的格式来进行配置,比如:
eureka.instance.metadataMap.zone=shanghai
接下来,我们将针对一些常用元数据配置做进一步的介绍和说明。
实例名配置
实例名,即InstanceInfo中的instanceId参数,它是区分同一服务中不同实例的唯一标识。在Netflix Eurek的原生实现中,实例名采用主机名作为默认值,这样的设置是的在同一主机上无法同时启动多个相同的服务实例。所以在Spring Cloud Eureka的配置中,针对同一主机启动多个实例的情况,对实例名的默认命名做了更为合理的扩展,它采用了如下默认规则:
${spring.cloud.client.hostname}:${spring.application.name}:${spring.application.instance_id}:${server.port}
对于实例名的命名规则,我们可以通过eureka.instance.instanceId参数来进行配置。比如,在本地进行客户端负载均衡调试时,需要启动同一服务的多个实例,如果我们直接启动同一个应用必然会导致端口冲突。虽然可以在命令行中指定不同的server.port来启动,但这样还是略显麻烦。实际上,我们可以直接通过设置server.port=0或者使用随机数server.port=${random.int[10000,19999]}来让Tomcat启动的时候采用随机端口。但这个时候我们会发现注册到Eureka Server的实例名都是相同的,这会使得只有一个服务实例能够正常提供服务。对于这个问题,我们就可以通过这是实例名规则来轻松解决:
eureka.instance.instanceId=${spring.application.name}:${random.int}
通过上面的配置,利用应用名加随机数的方式来区分不同的实例,从而实习那在同一主机上,不指定端口就能轻松启动多个实例的效果。
端点配置
在InstanceInfo中,我们可以看到一些URL的配置信息,比如homePageUrl、statusPageUrl、healthCheckUrl,它们分别代表了应用主页的URL、状态页的URL、健康检查的URL。其中,状态页和健康检查的URL在Spring Cloud Eureka中默认使用了spring-boot-actuator模块提供的/info端点和/heath端点。虽然我们之前的示例中并没有对这些端点做具体的设置,但实际上这些URL地址的配置非常重要。为了服务的正常运作,我们必须确保Eureka客户端的/heath端点在发送元数据的时候,是一个能够被注册中心访问到的地址,否则服务注册中心不会根据应用的健康检查来更改状态(仅当启用了heathcheck功能时,以该端点信息作为健康检查标准)。而/info端点如果不正确的话,会导致Eureka面板中点击服务实例时,我发访问到服务实例提供的信息接口。
大多数情况下,我们并不需要修改这几个URL的配置,但在一些特殊情况下,比如,为应用设置了context-path,这时,所有spring-boot-actuator模块的监控端点都会增加一个前缀。所以我们就需要做类似如下的配置,为/info和/heath端点也加上类似的前缀信息:
management.context-path=/hello
eureka.instance.statusPageUrlPath=${management.context-path}/info
eureka.instance.healthCheckUrlPath=${management.context-path}/heath
另外,有时候为了安全考虑,也可能会修改/info和/heath端点的原始路径。这个时候,我们也需要做一些特殊的配置,比如像下面这样:
endpoints.info.path=/appInfo
endpoints.heath.path=/checkHealth
eureka.instance.statusPageUrlPath=${endpoints.info.path}
eureka.instance.healthCheckUrlPath=${endpoints.heath.path}
在上面举例的两个示例中,我们使用了eureka.instance.statusPageUrlPath和eureka.instance.healthCheckUrlPath参数这两个配置值有一个共同特点,它们都是用相对路径来进行配置。由于Eureka的服务注册中心默认会以HTTP的方式来访问和暴露这些端点,因此当客户端应用以HTTPS的方式来暴露服务和监控端点时,相对路径的配置方式就无法满足需求了。所以,Spring Cloud Eureka还提供了绝对路径的配置参数,具体实例如下所示:
eureka.instance.statusPageUrl=https://${eureka.instance.hostname}/info
eureka.instance.healthCheckUrl=https://${eureka.instance.hostname}/heath
eureka.instance.homePageUrl=https://${eureka.instance.hostname}/
健康检测
默认情况下,Eureka中各个服务实例的健康检测并不是通过spring-boot-actuator模块的/health端点来实现的,而是依靠客户端心跳的方式来保持服务实例的存活。在Eureka的服务续约与服务剔除机制下,客户端的健康状态从注册到注册中心开始都会处于UP状态,除非心跳终止一段时间之后,服务注册中心将其剔除。默认的心跳的实现方式可以有效检查客户端进程是否正常运作,但却无法保证客户端应用能够正常提供服务。由于大多数的应用与这些外部资源无法联通的时候,实际上已经不能提供正常的对外服务了,但是因为客户端的心跳依然在运行,所以它还是会被服务消费者调用,而这样的调用实际上并不能获得预期的结果。
在Spring Cloud Eureka中,我们可以通过简单的配置,把Eureka客户端的健康检测交给spring-boot-actouator模块的/health端点,以实现更加全面的健康状态维护。详细的配置步骤如下所示:
- 在pom.xml中引入spring-boot-starter-actuator模块的依赖。
- 在application.properties中增加参数配置eureka.client.healthcheck.enabled=true.
- 如果客户端的/health端点路径做了一些特殊处理,请参考巧文介绍的端点配置时的方法进行配置,让服务注册中心可以正确访问到健康检测端点。
其他配置
除了上面介绍的配置参数外,下面整理了一些org.springframework.cloud.netflix.eureka.EurekaInstanceConfigBean中定义的配置参数以及对应的说明和默认值,这些参数均以eureka.instance为前缀。
参数名 | 说明 | 默认值 |
---|---|---|
preferIpAddress | 是否优先使用IP地址作为主机名的标识 | false |
leaseRenewalIntervalInSeconds | Eureka客户端向服务端发送心跳的时间间隔,单位为秒 | 30 |
leaseExpirationDurationInSeconds | Eureka服务端在收到最后一次心跳之后等待的时间上限,单位为秒。超过该时间之后服务端会将该服务实例从服务清单中剔除,从而禁止服务调用请求被发送到该实例上 | 90 |
nonSecurePort | 非安全的通信端口号 | 80 |
securePort | 安全的通信端口号 | 443 |
nonSecurePortEnabled | 是否启用非安全的通信端口号 | true |
securePortEnabled | 是否启用安全的通信端口号 | |
appname | 服务名,默认取spring.application.name的配置值,如果没有则为unknown | |
hostname | 主机名,不配置的时候讲根据操作系统的主机名来获取 |
在上面的这些配置中,除了前三个配置参数在需要的时候可以做一些调整,其他的参数配置大多数情况下不需要进行配置,使用默认值即可。