eureka⼼跳_8个Eureka优化技巧,让效率提⾼10倍
1. Eureka的⾃我保护
服务注册到Eureka中以后。默认情况下每30s(默认)给Eureka发⼀次⼼跳,如果Eureka⼀段时间(默认90s)没收到⼼跳就会把该服务剔除。
但是有时候服务正常,只是由于⽹络异常抖动没有把⼼跳发送⾄Eureka,如果Eureka这时把服务剔除,当⽹络恢复正常时,服务也不会重新注册到Eureka(服务只有在启动得时候才注册Eureka)。服务通过Eureka是访问不了的。
为了防⽌这种误杀,Eureka提供了⾃我保护机制:Eureka在15分钟内收到服务端⼼跳数⼩于Eureka本应该收到的总⼼跳数 * ⾃我保护阈值(默认0.85)就会触发。该机制默认开启。等⽹络恢复后退出⾃我保护。
**总体思想就是:宁可保住不健康的,也不盲⽬注销任何健康的服务。**
⽐如我们有10台服务器,正常情况下15分钟应该给Eureka发送10 * (2 * 15 ) = 300 次⼼跳(30秒⼀次),但此时Eureka收到的⼼跳⼩于300 * 0.85 = 255,就会触发⾃我保护。不发⼼跳有2种可能。
1. 服务没挂,⽹络等原因,Eureka没收到服务⼼跳。⽹络恢复后继续发送⼼跳。
2. 服务挂了,来不及下线。那什么时候才从注册列表移除?就是等那些真的因为⽹络异常抖动保护起来的服务重新发送⼼跳。
* 那什么时候开⾃我保护什么时候不开呢?
1. 我个⼈⼀点点⼩思考,抛砖引⽟,服务多的来保护,服务少的不保护。
因为服务多的时候,超过15%没收到⼼跳,⽹络问题可能性更⼤。但是服务少超过15%没⼼跳,服务挂的可能性更⼤,如果把挂掉的服务保护起来,就会给客户端返回错
2. 当然为了保证线上系统的健壮稳定,可以在任何情况下开启⾃我保护。
⾃我保护配置如下:
eureka: server: ## ⾃我保护开启 enable-self-preservation: true ## ⾃我保护触发的阈值,可以适当修改 renewal-percent-threshold: 0.85
2. 快速下线
Eureka Server在启动时会创建⼀个定时任务,每隔⼀段时间(默认60秒),从当前服务清单中把超时没有续约(默认90秒)的服务剔除。我们可以把定时任务间隔的时间设置得短⼀点,做到快速下线。防⽌拉取到不可⽤的服务。
eureka: server: eviction-interval-timer-in-ms: 3000 //⽐如3s
3. 缓存优化
Eureka Server为了避免同时读写内存数据结构造成的并发冲突问题,采⽤了3级缓存机制来进⼀步提升服务请求的响应速度。
拉取注册表的步骤是:
1. ⾸先从ReadOnlyCacheMap⾥查缓存的注册表。
2. 若没有,就ReadWriteCacheMap⾥缓存的注册表。
3. 如果还没有,就从内存中获取实际的注册表数据。
当注册表发⽣变化的时候,先更新注册表数据和ReadWriteCacheMap⾥缓存的数据,默认30s后把ReadWriteCacheMap⾥⾯的数据更
新到ReadOnlyCacheMap。
为了提⾼服务被发现的速度。我们可以做⼀些设置。
1. 拉去服务的时候,不从ReadOnlyCacheMap⾥查,直接从ReadWriteCacheMap取。
eureka: server:use-read-only-response-cache: false //关闭从ReadOnlyCacheMap拉取数据。
2. 缩短ReadWriteCacheMap向ReadOnlyCacheMap同步的时间间隔,默认30秒,我们可以优化到3秒,这个根据⾃⼰的情况⽽定。eureka: server:response-cache-update-interval-ms: 3000
这⾥看源码的时候发现代码有个问题:
if (shouldUseReadOnlyResponseCache) { timer.schedule(getCacheUpdateTask(), new Date(((System.currentTimeMillis() / responseCa
为什么System.currentTimeMillis() 除以 responseCacheUpdateIntervalMs ⼜称responseCacheUpdateIntervalMs,这不还是原来
的System.currentTimeMillis() 吗?
其实⽤timer也是存在隐患的,就是多线程并⾏处理定时任务时,timer运⾏多个timetask时,只要其中之⼀没有捕获抛出的异常,其他任
务便会⾃动终⽌运⾏。可以改成⽤ScheduledExcutorService。
养养眼
4. 客户端开发⼩技巧
我们开发客户端的时候,如果不启动注册中⼼就会⼀直报注册中⼼链接超时的错。我们可以在开发的
时候做如下配置,让服务和注册中⼼脱钩。
eureka: client: ### 不拉取也不注册、跟注册中⼼没关系 enabled: false
5. 客户端拉取注册表更及时
api-client会定时到eureka-server拉取注册表。默认情况下每30秒拉取⼀次。可以根据实际情况设置拉取时间间隔。
eureka: client: fetch-registry=true ### 拉取注册表信息间隔时 registry-fetch-interval-seconds: 3
6. client.serviceUrl.defaultZone优化
api-client从eureka-server拉取注册表信息是按照defaultZone配置的顺序依次拉取的,当eureka1不可⽤的时候再从eureka2中获取/注册。但是如果eureka1⼀直不挂。所有的微服务都会先从eureka1中获取信息,导致eureka1压⼒过⼤。在实际⽣产中,每个微服务可以随机配置不同的defaultZone顺序。⼿动做到负载均衡。⽐如clientA的defaultZone:是eureka1,eureka2,eureka3;clientB的defaultZone:是eureka2,eureka3,eureka1。
eureka: client: serviceUrl: defaultZone: eureka1,eureka2,eureka3
7. client⼼跳频率
默认情况下,client每隔30秒就会向服务端发送⼀次⼼跳。这个时间也可以适当调⼩⼀点。
eureka: instance: ##每间隔30s,向服务端发送⼀次⼼跳,证明⾃⼰依然”存活“。 lease-renewal-interval-in-seconds: 30
8. 服务端剔除客户端的时间间隔
默认情况下,server在90s之内没有收到client⼼跳,将我踢出掉。为了让服务快速响应,可以适当地把这个时间改的⼩⼀点。
eureka: instance: lease-expiration-duration-in-seconds: 90
还有什么问题
Eureka其他问题
在哪些地⽅没实现⼀致性?也就是CAP中的C。
1. ⾃我保护机制,使⽹络不好的情况下还会能拉取到注册表进⾏调⽤。
2. 在缓存同步的时候没实现。上⾯我们在优化缓存的时候发现,ReadOnlyCacheMap和ReadWriteCacheMap之间的数据没实现⼀致
性。
3. 从其他peer拉取注册表。集之间的状态是采⽤异步⽅式同步的,所以不保证节点间的状态⼀定是⼀致的,不过基本能保证最终状态
是⼀致的。
集同步,集并没有扩⼤Eureka并没有扩⼤它的承受能⼒,只是实现了可⽤性。
在什么情况下会同步数据?我们从以下⼏个节点分析。
1. 注册:第⼀个节点注册进来,只同步下⼀个节点。
2. 续约:有新服务续约,⾃动同步到其他Eureka-Server。
3. 下线:⼀直同步所有集。
4. 剔除:不同步,每个Server都有⾃⼰的剔除机制。
估算能承受多少服务量微服务注册中心有哪些
⽐如有20个服务,每个服务部署5个实例。就是20 * 5 = 100实例。
1. ⼀个实例默认30秒发⼀次⼼跳,30秒拉取⼀次注册表。那Service每分钟接收到的请求量就是。100 * 2 * 2 = 400次。那⼀天能承
受的量就是 400 * 60 * 24 = 576000次请求。也就是每天500多万的访问量。
所以通过设置⼀个适当的拉取注册表以及发送⼼跳的频率,可以保证⼤规模系统⾥对Eureka Server的请求压⼒不会太⼤。
⽣产中的问题,当重启服务的时候,还是可以访问,但是返回服务错误
在服务启动时,⼀定要先停服,再⼿动触发下线。
如果不⼿动下线,可能会访问到重启中的服务。⽽这个服务不可⽤。
如果先⼿动下线,可能还会拉取到重启的服务,⼿动下线⽆效。
区域问题
当⽤户量⽐较⼤的时候,我们服务可能布置到不同区域、不同机房。如果我们上线微服务的时候,希望同⼀机房的服务调⽤同⼀机房的服务,当同⼀机房的服务不可⽤在调⽤其他机房的服务。类似CDN吧。这样可以减少⽹络延迟。
eureka提供2个概念来分区。
1. region:相当于地区,⽐如北京地区。
2. zone:是region下属单位,⽐如北京甲机房、⼄机房。
抛砖引⽟,有什么问题⼤家可以讨论。如果您觉得有⽤,请转发点赞。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论