本文基於SpringCloud-Dalston.SR5spring
是的,馬上會。緩存
EurekaClient在每次實例狀態發生改變時,有一個Listener:網絡
statusChangeListener = new ApplicationInfoManager.StatusChangeListener() { @Override public String getId() { return "statusChangeListener"; } @Override public void notify(StatusChangeEvent statusChangeEvent) { if (InstanceStatus.DOWN == statusChangeEvent.getStatus() || InstanceStatus.DOWN == statusChangeEvent.getPreviousStatus()) { // log at warn level if DOWN was involved logger.warn("Saw local status change event {}", statusChangeEvent); } else { logger.info("Saw local status change event {}", statusChangeEvent); } //這個會觸發調用register接口將實例信息註冊上去 instanceInfoReplicator.onDemandUpdate(); } };
實例初始化完畢時,會發送一個狀態爲UP的事件,觸發這個Listener(狀態從STARTING變成UP ):app
@Override public void register(EurekaRegistration reg) { maybeInitializeClient(reg); if (log.isInfoEnabled()) { log.info("Registering application " + reg.getInstanceConfig().getAppname() + " with eureka with status " + reg.getInstanceConfig().getInitialStatus()); } reg.getApplicationInfoManager() .setInstanceStatus(reg.getInstanceConfig().getInitialStatus()); if (reg.getHealthCheckHandler() != null) { reg.getEurekaClient().registerHealthCheck(reg.getHealthCheckHandler()); } }
那麼,官網這兩個配置有啥用: 其實這個Initially是另一個邏輯,就是在應用啓動40s後,檢查實例信息是否老舊,或者第一次註冊是否失敗,若是失敗,就再次註冊。以後每隔30s執行一次這個任務異步
首先,EurekaClient會選擇eureka.client.service-url.defaultZone配置的第一個EurekaServer,以後若是和這個EurekaServer沒有網絡問題,就會一直用這個。 在EurekaClient向EurekaServer發送註冊,下線,心跳,狀態改變等一切事件時,這些會在EurekaServer上面同步到集羣(EurekaServer集羣配置就是eureka.client.service-url.defaultZone,集羣內每一個EurekaServer)的全部Server上ide
這樣的機制有沒有問題?微服務
網絡抖動時,致使訪問到另外一個Eureka,重啓才能恢復。。。url
經過EurekaServer內部定時檢查過時實例任務,掃描Registry裏面過時的實例並刪除,而且使對應的ReadWriteMap緩存失效 注意,ReadOnlyMap裏面的並不會馬上失效,而是經過下一個只讀緩存刷新從ReadWriteMap刷到ReadOnlyMap感知變化。由於EurekaClient獲取實例信息只從ReadOnlyMap讀取,因此EurekaClient感知變化也會有這個延遲設計
SpringCloud環境下,EurekaClient有緩存,Ribbon對於調用的服務列表也有緩存,因此能夠繼續調用,但不會更新服務與實例列表了。 根據Eureka的self-preservation的設計思路,能夠理解這種設計也是符合Eureka初衷的(CAP中的A)code