Eureka 目前的状态:Eureka 目前 1.x 版本还在更新,可是应该不会更新新的功能了,只是对现有功能进行维护,升级并兼容所需的依赖。 Eureka 2.x 已经胎死腹中了。可是,这也不表明 Eureka 就是不能用了。若是你须要一个简便易于部署的注册中心,Eureka 仍是一个很好的选择。云服务环境中,基本上全部实例地址和微服务名称都在不断变化,也并不太须要 Eureka 所缺乏的持久化特性。当你的集群属于中小规模的时候(节点小于 1000 个), Eureka 依然是一个不错的选择。当你的集群很大的时候,Eureka 的同步机制可能就限制了他的表现。java
Eureka 的设计比较小巧,没有复杂的同步机制,也没有复杂的持久化机制,集群关系只是简单的将收到的客户端请求转发到集群内的其余 Eureka 实例。Eureka 自己也只有注册中心的功能,不像其余种类的注册中心那样,将注册中心和配置中心合在一块儿,例如 Consul 和 nacos。node
Eureka 的交互流程以下:git
首先,Service A 经过 Eureka Client 发送注册请求(Register)到同一可用区的 Eureka Server 1。以后经过发送心跳请求(Renew)到这个 Eureka Server 1. Eureka Server 1 收到这些请求的时候,会处理这些请求并将这些请求转发到其余的集群内的 Eureka Server 2 和 Eureka Server 3. Eureka Server 2 和 Eureka Server 3 不会再转发收到的 Eureka Server 1 转发过来的请求。而后,Service B 还有 Service C 经过 Eureka 获取到了 Service A 的位置,最后调用了 Service A。github
对于本地没有查询到的微服务,Eureka Server 还会从远程 Region 的 Eureka Server 去获取,例如这里对于 Service D,本地没有查到,Eureka Server 会返回远程 Region 的 Service D 的实例。因为本地有 Service A,因此确定不会返回远程 Region 的 Service A 的实例。而且,本地是定时拉取的远程 Region 的 Service 列表,并非每次查询的时候现查询的。spring
通常的,微服务之间的互相调用,并不通过 Eureka,也不会涉及到 Eureka 客户端了,而是经过负载均衡器调用,这个咱们后面就会提到。apache
这里咱们忽略全部的 AWS 相关的术语以及配置还有相关逻辑处理。缓存
Eureka 中的术语:服务器
spring.application.name
指定的服务名称。eureka: instance: #通常不用咱们本身设置,EurekaInstanceConfigBean 的构造器会经过 InetUtils 获取 ip 地址 #ip-address: #通常不用咱们本身设置,EurekaInstanceConfigBean 的构造器会经过 InetUtils 获取 hostname #hostname: #注册到 eureka 上面供其余实例访问的地址使用 ip 进行注册,其余实例会经过 ip 进行访问 prefer-ip-address: true #不用设置 non-secure-port,自动使用 server.port 做为 non-secure-port #non-secure-port: #若是 secure-port-enabled 是 true,则会自动使用 server.port 做为 secure-port;咱们通常内部调用不用 ssl,因此不须要配置 secure-port #secure-port: #默认是启用 non-secure-port 的 non-secure-port-enabled: true #默认是不启用 secure-port 的,咱们通常内部调用不用 ssl secure-port-enabled: false #个性化的实例id,包括 ip:微服务名称:端口 instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port} # app名称,不填写在 Spring-cloud-netflix 体系下默认就是 spring.application.name appname: ${spring.application.name} #app组名称归类用的,目前也没什么用 app-group-name: common #实例命名空间,目前也没什么用 namespace: public
eureka: instance: # 健康检查地址,默认是 /actuator/health health-check-url-path: /actuator/health # 实例状态地址,默认是 /actuator/info status-page-url-path: /actuator/info # 首页地址,默认是 / home-page-url-path: /
eureka: instance: # 服务过时时间配置,超过这个时间没有接收到心跳EurekaServer就会将这个实例剔除 # 注意,EurekaServer必定要设置eureka.server.eviction-interval-timer-in-ms不然这个配置无效 # 这个配置通常为服务刷新时间配置的三倍 # 默认90s lease-expiration-duration-in-seconds: 15 #服务刷新时间配置,每隔这个时间会主动心跳一次 #默认30s lease-renewal-interval-in-seconds: 5 registry: #请参考 wait-time-in-ms-when-sync-empty 配置说明 default-open-for-traffic-count: 1 #初始指望发送心跳请求的实例个数,默认为1,在有新实例注册的时候,会 +1,有注销的时候会 -1,初始默认为 1 通常由于本身也注册到 eureka 上 expected-number-of-clients-sending-renews: 1 #实例注册后是否马上开始服务,默认为 false,通常注册后还须要作一些操做,因此注册实例的状态是 STARTING。后面改变状态后会更新为 UP instance-enabled-onit: false
eureka: instance: #元数据map,咱们能够本身使用,放一些个性化的元数据,目前只有 configPath 和 zone 比较有用。 configPath 是使用 spring-cloud-config 的时候会设置 metadata-map: # spring cloud 体系中,可用区的配置放入元数据中,key 为 zone zone: zone1
Eureka 客户端配置:网络
eureka: instance: # 可用区列表,key 为 region,value 为 zone availability-zones: region1: zone1, zone2 region2: zone3 # 所在区域,经过这个读取 availability-zones 获取 zone,而后经过 zone 读取 service-url 获取对应的 eureka url # 这里的逻辑对应的类是 ConfigClusterResolver 和 ZoneAffinityClusterResolver region: region1 # key 为 zone,value 为 eureka 连接,以逗号分隔 service-url: # 默认eureka集群,这里必须是defaultZone,不能用-替换大写,与其余的配置不同,由于实在EurekaClientConfigBean里面写死的 defaultZone: http://127.0.0.1:8211/eureka/ zone1: http://127.0.0.1:8212/eureka/ zone2: http://127.0.0.1:8213/eureka/ zone3: http://127.0.0.1:8214/eureka/ # 若是上面 eureka server 地址相关配置更新了,多久以后会从新读取感知到 eureka-service-url-poll-interval-seconds: 300 # 是否使用 dns 获取,若是指定了则经过下面的 dns 配置获取,而不是上面的 service-url use-dns-for-fetching-service-urls: false # dns 配置 # eureka-server-d-n-s-name: # dns 配置的 eureka server 的 port # eureka-server-port: # dns 配置的 eureka server 的 port 后面的 uri 前缀 context # eureka-server-u-r-l-context: # 若是设置为 true,则同一个 zone 下的 eureka 会跑到前面优先访问。默认为 true prefer-same-zone-eureka: true
拉取服务实例信息相关配置:app
eureka: instance: # 是否从 eureka 上面拉取实例 fetch-registry: true # 若是只想获取一个特定 virtual host name 的实例列表,就配置 registry-refresh-single-vip-address #registry-refresh-single-vip-address: # 客户端请求头指定服务端返回的实例信息是压缩的信息仍是完整信息,默认是完整信息 # full, compact client-data-accept: full # eureka client 刷新本地缓存时间 # 默认30s registry-fetch-interval-seconds: 5 # eureka client 刷新本地缓存(定时拉取 eureka 实例列表)线程池大小,默认为 2 cache-refresh-executor-thread-pool-size: 2 # eureka client 刷新本地缓存(定时拉取 eureka 实例列表)线程池任务最大延迟时间,这个配置是定时拉取任务延迟(registry-fetch-interval-seconds)的倍数,默认 10 倍 cache-refresh-executor-exponential-back-off-bound: 10 # 是否禁用增量拉取,若是网络条件很差,能够禁用,每次都会拉取全量 disable-delta: false # 只保留状态为 UP 的实例,默认为 true filter-only-up-instances: true #能够指定也从某些 region 拉取服务实例 #fetch-remote-regions-registry: # 是否打日志记录每次拉取实例信息与当前缓存内的实例信息变化 log-delta-diff: true #在spring cloud 环境中,DiscoveryClient 用的其实都是 CompositeDiscoveryClient,这个 CompositeDiscoveryClient 逻辑其实就是多个 DiscoveryClient 共存,先访问一个,没找到就经过下一个寻找 #这个order决定了顺序,默认为 0 order: 0
eureka: instance: # 是否将本身注册到 eureka 上面 register-with-eureka: true # 是否在初始化的时候就注册到 eureka,通常设置为 false,由于实例还不能正常提供服务 should-enforce-registration-at-init: false # 是否在关闭的时候注销实例,默认为 true should-unregister-on-shutdown: true # 是否对于实例状态改变动新进行限流,默认为 true on-demand-update-status-change: true # 实例信息同定时同步到 Eureka Server 的间隔时间。每隔这么长时间,检查实例信息(即eureka.instance配置信息)是否发生变化,若是发生变化,则同步到 Eureka Server,默认 30s # 主要检查两类信息,分别是服务地址相关信息,以及服务过时时间与刷新时间配置信息 instance-info-replication-interval-seconds: 30 # 实例信息同定时同步到 Eureka Server 的初始延迟时间,默认 40s initial-instance-info-replication-interval-seconds: 40
eureka: instance: # 代理相关配置 # proxy-host: # proxy-port: # proxy-user-name: # proxy-password: # 是否对于发往 Eureka Server 的 http 请求启用 gzip,目前已通过期了,只要 Eureka Server 启用了 gzip,请求就是 gzip 压缩的 g-zip-content: true # httpclient 的连接超时,默认 5s eureka-server-connect-timeout-seconds: 5 # httpclient 的读取超时,默认 5s eureka-server-read-timeout-seconds: 8 # httpclient 的空闲链接超时,默认 30s eureka-connection-idle-timeout-seconds: 30 # httpclient 的总链接数量,默认 200 eureka-server-total-connections: 200 # httpclient 的每一个 host 的链接数量 eureka-server-total-connections-per-host: 50 # tls 相关配置,默认没有启用 # tls: # enabled: false # key-password: # key-store: # key-store-password: # key-store-type: # trust-store: # trust-store-password: # trust-store-type:
eureka: server: #主动检查服务实例是否失效的任务执行间隔,默认是 60s eviction-interval-timer-in-ms: 3000 #这个配置在两个地方被使用: #若是启用用了自我保护,则会 renewal-threshold-update-interval-ms 指定的时间内,收到的心跳请求个数是否小于实例个数乘以这个 renewal-percent-threshold #定时任务检查过时实例,每次最多过时 1 - renewal-percent-threshold 这么多比例的实例 renewal-percent-threshold: 0.85
eureka: server: #注意,最好全部的客户端实例配置的心跳时间相关的配置,是相同的。这样使用自我保护的特性最准确。 #关闭自我保护 #咱们这里不使用自我保护,由于: #自我保护主要针对集群中网络出现问题,致使有不少实例没法发送心跳致使不少实例状态异常,可是实际实例还在正常工做的状况,不要让这些实例不参与负载均衡 #启用自我保护的状况下,就会中止对于实例的过时 #可是,若是出现这种状况,其实也表明不少实例没法读取注册中心了。 #而且还有一种状况就是,Eureka 重启。虽然不常见,可是对于镜像中其余的组件更新咱们仍是很频繁的 #我倾向于从客户端对于实例缓存机制来解决这个问题,若是返回实例列表为空,则使用上次的实例列表进行负载均衡,这样既能解决 Eureka 重启的状况,又能处理一些 Eureka 网络隔离的状况 #自我保护模式基于每分钟须要收到 renew (实例心跳)请求个数,若是启用了自我保护模式,只有上一分钟接收到的 renew 个数,大于这个值,实例过时才会被注销 enable-self-preservation: false # 每分钟须要收到 renew (实例心跳)请求个数是须要动态刷新的,这个刷新间隔就是 renewal-threshold-update-interval-ms #更新流程大概是:计算当前一共有多少实例,若是大于以前指望的实例量 * renewal-percent-threshold(或者没开启自我保护模式),则更新指望的实例数量为当前一共有多少实例 #以后根据指望的实例数量,计算指望须要收到的实例心跳请求个数 = 指望的实例数量 * (60 / expected-client-renewal-interval-seconds) * renewal-percent-threshold #公式中 60 表明一分钟,由于公式用到了 expected-client-renewal-interval-seconds,也就是实例平均心跳间隔,为了使这个公式准确,最好每一个实例配置同样的心跳时间 #默认 900000ms = 900s = 15min renewal-threshold-update-interval-ms: 900000 #上面提到的实例平均心跳间隔,或者说是指望的心跳间隔,为了使这个公式准确,最好每一个实例配置同样的心跳时间 #默认 30s expected-client-renewal-interval-seconds: 30 #这个配置在两个地方被使用: #若是启用用了自我保护,则会 renewal-threshold-update-interval-ms 指定的时间内,收到的心跳请求个数是否小于实例个数乘以这个 renewal-percent-threshold #定时任务检查过时实例,每次最多过时 1 - renewal-percent-threshold 这么多比例的实例 renewal-percent-threshold: 0.85
eureka: server: #Eureka Server 从配置中更新同一区域内的其余 Eureka Server 实例列表间隔,默认10分钟 peer-eureka-nodes-update-interval-ms: 600000 #启动时从其余 Eureka Server 同步服务实例信息的最大重试次数,直到实例个数不为 0,默认为 0,这样其实就是不一样步 registry-sync-retries: 0 #启动时从其余 Eureka Server 同步服务实例信息重试间隔 registry-sync-retry-wait-ms: 30000 #集群内至少有多少个 UP 的 Eureka Server 实例数量,当前 Eureka Server 状态为 UP。默认 -1,也就是 Eureka Server 状态不考虑 UP 的集群内其余 Eureka Server 数量。 min-available-instances-for-peer-replication: -1 #请求其余实例任务的最大超时时间,默认 30 秒 max-time-for-replication: 30000 #用来处理同步任务的线程数量,有两个线程池,一个处理批量同步任务,默认大小为20 max-threads-for-peer-replication: 20 #另外一个处理非批量任务(若是没用 AWS Autoscaling 对接相关特性则没有啥用),默认大小为20 max-threads-for-status-replication: 20 #处理批量任务的线程池队列长度,默认为 10000 max-elements-in-peer-replication-pool: 10000 #处理非批量任务的线程池队列长度,默认为 10000 max-elements-in-status-replication-pool: 10000 #Eureka Server 经过 httpclient 访问其余 Eureka Server 同步实例,httpclient 的链接超时,默认 200ms peer-node-connect-timeout-ms: 200 #httpclient 的读取超时,默认 200ms,通常不用太长 peer-node-read-timeout-ms: 200 #httpclient 的最大总链接数量,默认 1000 peer-node-total-connections: 1000 #httpclient 的对于某一 host 最大总链接数量,默认 500 peer-node-total-connections-per-host: 500 #httpclient 的链接空闲保持时间,默认 30s peer-node-connection-idle-timeout-seconds: 30
eureka: server: #请求其余 Region 的 httpclient 的链接超时,默认 1000ms remote-region-connect-timeout-ms: 1000 #请求其余 Region 的 httpclient 的读取超时,默认 1000ms remote-region-read-timeout-ms: 1000 #请求其余 Region 的 httpclient 的最大总链接数量,默认 1000 remote-region-total-connections: 1000 #请求其余 Region 的 httpclient 的对于某一 host 最大总链接数量,默认 500 remote-region-total-connections-per-host: 500 #请求其余 Region 的 httpclient 的链接空闲保持时间,默认 30s remote-region-connection-idle-timeout-seconds: 30 #请求其余 Region 的 http 请求是否开启 gzip,对于其余 Region 咱们认为网络链接是比较慢的,因此默认开启压缩 g-zip-content-from-remote-region: true # remote-region-urls-with-name: # region2eureka1: http://127:0:0:1:8212/eureka/ # region2eureka2: http://127:0:0:1:8213/eureka/ # remote-region-app-whitelist: #若是须要从其余 Region 获取实例信息,这个获取间隔,默认为 30s remote-region-registry-fetch-interval: 30 #若是须要从其余 Region 获取实例信息,这个任务的线程池,默认为 20个 remote-region-fetch-thread-pool-size: 20
启动一个 Eureka 注册中心服务器很是简单,咱们这里使用的是 Spring Cloud 封装好的启动包。Eureka 1.x 的 Eureka Server 是纯基于 servlet 的应用。为了与 Spring Cloud 结合使用,须要粘合模块,这就是 spring-cloud-netflix-eureka-server。在 spring-cloud-netflix-eureka-server 中,也有一个和 com.netflix.eureka.EurekaBootStrap
代码很相似的启动类,即 org.springframework.cloud.netflix.eureka.server.EurekaServerBootstrap
。在咱们启动 EurekaServer 实例的时候,只用加入对于 spring-cloud-starter-eureka-server 的依赖便可。以后经过 @EnableEurekaServer 注解便可启动一个 Eureka 服务器实例。
Eureka Server 的依赖:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>spring-cloud-iiford</artifactId> <groupId>com.github.hashjang</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>spring-cloud-iiford-eureka-server</artifactId> <dependencies> <dependency> <groupId>com.github.hashjang</groupId> <artifactId>spring-cloud-iiford-service-common</artifactId> <version>${project.version}</version> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-netflix-eureka-server</artifactId> </dependency> </dependencies> </project>
Eureka Server 的配置:
参考咱们上面的配置便可:application.yml
Eureka Server 的启动类:EurekaServerApplication.java
package com.github.hashjang.iiford.eureka.server; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; @SpringBootApplication @EnableEurekaServer public class EurekaServerApplication { public static void main(String[] args) { SpringApplication.run(EurekaServerApplication.class, args); } }