成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

我也是醉了,Eureka 延遲注冊還有這個坑!

開發 架構
即便我們把所有途徑都封死了,但是發送心跳的線程仍然會去注冊,所以這個延遲注冊的時間最多也不會超過 30 秒,即便配置的延遲時間超過 30 秒。

Eureka 有個延遲注冊的功能,也就是在服務啟動成功之后不立刻注冊到 Eureka Server,而是延遲一段時間再去注冊,這樣做的主要目的是因為雖然服務啟動成功了,可能還有一些框架或者業務的代碼沒有初始化完成,可能會導致調用的報錯,所以需要延遲注冊。

但是發現,然并卵啊,好像這個延遲注冊并沒有生效,也是開始了排查之路。

延遲注冊

首先,延遲注冊的功能主要依賴這兩個參數,eureka.client.initial-instance-info-replication-interval-seconds?代表第一次初始化延遲注冊的時間間隔,eureka.client.instance-info-replication-interval-seconds則代表后續同步注冊的時間間隔。

eureka.client.initial-instance-info-replication-interval-seconds=40 //默認40秒
eureka.client.instance-info-replication-interval-seconds=30 //默認30秒

我們從源碼先來看是怎么做到延遲注冊的,先看 DiscoveryClient? 的 initScheduledTasks ,這里創建了同步注冊到 Eureka Server 的定時任務。

圖片

之后調用 start 方法創建定時任務,并且延遲 40 秒執行,也就是我們達到的延遲注冊的效果。

圖片

圖片

默認的第一次注冊,也就是延遲注冊的時間是 40 秒,之后每 30 秒會同步注冊信息。

圖片

但是,即便我們配置了這倆屬性,發現好像沒什么卵用,接下來我們要排查下到底是為啥捏?

第一個問題

我發現在 InstanceInfoReplica 中存在這樣一段終止當前線程池任務,并且直接調用 run 方法的存在,猜測失效就是他直接調用導致延遲任務沒有生效,因為這個方法的直接調用導致延遲注冊壓根就沒效果嘛。

圖片

看起來他存在兩個調用,第一個是registerHealthCheck?,當存在這個健康檢查什么玩意兒的時候就會去調用onDemandUpdate。

圖片

經過排查我們發現,只要配置了eureka.client.healthcheck.enabled=true?,就會創建 HealthCheckHandler?的實例出來,默認情況下他是false的,所以應該是對我們沒有影響的。

圖片

這里需要特別說明一下 eureka.client.healthcheck.enabled ?的作用,默認 Eureka 根據心跳來決定應用的狀態,如果是這個屬性配置成 true的話,則是會根據 Spring Boot Actuator 來決定,而不是心跳了。

比如我們可以實現 HealthIndicator?接口,自己寫一個Controller來動態改變服務的狀態

@RestController
public class ControllerTest {
@Autowired
private HealthChecker healthChecker;

@RequestMapping("/change")
public String test(Boolean flag) {
healthChecker.setUp(new AtomicBoolean(flag));
return "success";
}

}

實現HealthChecker,這樣會發現啟動、下線服務 Eureka Server 的狀態不會變成 Down,只有通過調用接口手動改變應用狀態 Server 的狀態才會發生改變,大家可以自行測試。

@Component
public class HealthChecker extends EurekaHealthIndicator implements HealthIndicator {
private AtomicBoolean up = new AtomicBoolean(true);

public HealthChecker(EurekaClient eurekaClient, EurekaInstanceConfig instanceConfig, EurekaClientConfig clientConfig) {
super(eurekaClient, instanceConfig, clientConfig);
}

@Override
public Health health() {
if(up.get()){
return Health.up().build();
}else{
return Health.down().build();
}
}

第二個問題

第一個問題我們找到了,發現他不是導致我們問題的根因,于是繼續排查。

發現第二個調用,在DiscoveryClient注冊了狀態事件變更的監聽,如果狀態發生變更,也會去調用 onDemandUpdate ,影響延遲注冊的效果。

這里存在一個配置項onDemandUpdateStatusChange?,默認是true,所以應該是他沒錯了。

圖片

進入StatusChangeListener,找到了一個調用。

圖片

就是通過setInstanceStatus方法觸發的事件通知。

圖片

這里存在 6 個調用,一一排查,通過源碼找啊找,最終定位到服務啟動自動裝配的地方,在這里去修改服務狀態為 UP?,然后觸發事件通知,啟動 start? 方法調用register方法。

圖片

繼續調用,修改應用為上線UP狀態。

圖片

由此我們知道,只要服務啟動成功,就會觸發事件通知,所以這個基本上是啟動成功立刻就會去注冊到 Eureka Server,這就會導致延遲注冊的失效,從啟動日志也能直觀的看到這個效果。

圖片

驗證

為了驗證我的猜想,我把這兩個配置同時配置成false,并且把延遲注冊的時間調整到非常大。

eureka.client.healthcheck.enabled=false
eureka.client.onDemandUpdateStatusChange=false
eureka.client.initial-instance-info-replication-interval-seconds=9999999 //默認40秒
eureka.client.instance-info-replication-interval-seconds=999999 //默認30秒

但是,但是!!!

發現過了幾十秒之后,還是注冊到 Server 了,真的是醉了。。。

那就繼續看吧。

再看下注冊方法,可能不止一個地方存在調用,我們發現果然如此,有 3 個地方都調用了注冊方法。

圖片

第一個調用在DiscoveryClient?注入的時候,這個看了下,clientConfig.shouldEnforceRegistrationAtInit()?默認是false,方法不會進來,不管他了。

圖片

那么繼續看第二個調用,第二個調用你看renew方法,這一看我們就知道了,這不就是心跳嗎?!

發送心跳如果返回NOT_FOUND,就會去注冊了啊。

圖片

圖片

感覺已經接近真相了,去找下 Server 心跳的源碼,根據調用的路徑找到源碼位于InstanceResource中。

可以看到第一次注冊的時候從注冊表拿到的實例信息是空的,所以直接返回了 false,就會返回 NOT FOUND 了。

圖片

看registry.renew?方法,最終會調用到AbstractInstanceRegistry?中,初始化的時候注冊表registry?肯定沒有當前實例的信息,所以拿到是空的,返回了false,最終就返回了NOT_FOUND。

圖片

因此,雖然我們把這兩個參數都設置成了false,但是由于心跳默認 30 秒一次,所以最終我們發現配置的超級大的延遲注冊的時間并沒有完全生效。

總結

OK,到此,延遲注冊不生效的原因找到了,我們做一個總結。

默認情況下,配置了延遲注冊的時間并不會生效,因為事件監聽默認是true,服務啟動之后就會立刻注冊到 Eureka Server。

如果需要延遲注冊生效,必須 eureka.client.healthcheck.enabled ?、eureka.client.onDemandUpdateStatusChange? 都為false。

即便我們把所有途徑都封死了,但是發送心跳的線程仍然會去注冊,所以這個延遲注冊的時間最多也不會超過 30 秒,即便配置的延遲時間超過 30 秒。

責任編輯:武曉燕 來源: 艾小仙
相關推薦

2023-10-30 08:16:33

數據庫插件Mybatis

2022-03-21 08:55:53

RocketMQ客戶端過濾機制

2025-04-08 08:12:26

Next.js組件ChatGPT

2021-09-03 11:15:18

場景sql配置

2021-08-10 10:48:39

拷貝代碼架構耦合

2022-10-17 08:17:47

位掩碼Java變量

2024-10-06 13:41:25

2022-06-20 10:00:57

Python工具包代碼

2022-01-03 20:13:08

Gointerface 面試

2021-09-30 08:40:28

Oracle數據庫后端開發

2021-02-24 09:43:36

MySQL數據庫雙引號

2013-11-29 13:05:07

程序員工作

2018-07-12 14:59:44

獵網

2022-01-07 13:36:00

MySQL數據庫分頁

2020-03-12 15:00:44

JavaSpring依賴

2017-06-16 16:16:36

庫存扣減查詢

2018-09-13 10:59:30

Redis鍵值存儲

2023-05-31 07:57:12

筆記本電腦信譽度

2025-03-31 08:35:00

Eureka微服務架構

2023-12-01 07:38:33

微服務訂單服務
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 日日噜 | 中文字幕成人免费视频 | 亚洲成人av在线播放 | 国产精品a久久久久 | 国产精品入口久久 | 99色播 | 色视频在线播放 | 亚洲看片网站 | 亚洲精品二区 | 国产一区视频在线 | 免费一区二区三区 | 91精品国产综合久久久久久首页 | 亚洲精品在线看 | 中文字幕亚洲在线 | 欧美日韩久久久久 | 欧美 日韩 在线播放 | 欧美精品久久久久久久久老牛影院 | 波波电影院一区二区三区 | av在线免费观看不卡 | 在线国产一区二区三区 | 亚洲视频在线观看一区二区三区 | 在线不卡视频 | 精品一区电影 | 欧美中文 | 草草视频在线观看 | 国产精品欧美一区二区 | 国产精品国产成人国产三级 | 一级免费视频 | 五月激情婷婷六月 | 日韩欧美电影在线 | 亚洲精品国产成人 | 武道仙尊动漫在线观看 | 日韩中文字幕一区 | 日韩最新网站 | 欧美一级在线观看 | 欧美久久一区二区 | 嫩草懂你的影院入口 | 久久久www成人免费无遮挡大片 | 亚洲精品一区在线观看 | 国产在线观看一区二区 | 成人av观看|