摘要:服務續(xù)約在服務注冊完成之后,服務提供者需要維護一個心跳來告知注冊中心服務實例處于正常運行狀態(tài)中,防止注冊中心將正常的服務實例剔除出注冊中心。
Spring Cloud Eureka 目錄
前言
構建服務注冊中心
服務注冊與發(fā)現(xiàn)
Eureka的基礎架構
Eureka的服務治理機制
Eureka的配置
代碼地址
前言 服務治理?隨著微服務應用的不斷增加,靜態(tài)配置會越來越難以維護,并且隨著業(yè)務的不斷發(fā)展,集群規(guī)模、服務位置、服務命名都會發(fā)生變化,手動維護的方式極易發(fā)生錯誤或是命名沖突問題。因此需要服務治理框架對微服務實例進行管理,服務治理是微服務架構中最核心的功能和模塊,主要用來各個微服務實例的自動化注冊和發(fā)現(xiàn)。
服務注冊?在服務治理框架中,通常都會有一個服務注冊中心。
?每一個微服務實例向注冊中心登記自己提供的服務,將主機、端口號、版本號、通信協(xié)議等一些信息告知注冊中心。
?注冊中心按服務名分類組織服務清單。
?服務注冊中心需要以心跳的方式監(jiān)測服務清單中的服務是否可用,如果不可用,需要將不可用的服務實例進行剔除。
服務發(fā)現(xiàn)?服務間的調(diào)用通過向服務名發(fā)起請求調(diào)用實現(xiàn)。 服務調(diào)用方在調(diào)用提供方的接口時,并不知道提供方的具體地址。
?服務調(diào)用方需要從注冊中心獲取所有服務的實例清單,才可以實現(xiàn)對具體服務實例的訪問。
?服務調(diào)用方在發(fā)起調(diào)用時,會以某種策略取出一個具體的服務實例進行服務調(diào)用(客戶端負載均衡)。
?在實際的環(huán)境中,為了提供性能,并不會采用每次都向服務注冊中心獲取服務的方式進行服務的調(diào)用,并且不同的應用場景在緩存和服務剔除等機制上可以采用不同的實現(xiàn)策略。
Netflix Eureka?Spring Cloud Eureka采用Netflix Eureka來實現(xiàn)服務注冊與發(fā)現(xiàn),包含客戶端和服務端組件。
?支持高可用配置。
?依托于強一致性提供良好的服務實例可用性。
?服務注冊中心之間可以通過異步模式互相復制各自的狀態(tài)。
?主要用于服務的注冊和發(fā)現(xiàn)。
?客戶端可以通過注解和參數(shù)配置的方式實現(xiàn)注冊與發(fā)現(xiàn)。
?Eureka客戶端向注冊中心注冊自身提供的服務并周期性地發(fā)送心跳來更新它的服務租約。
?Eureka客戶端從服務端查詢當前注冊的服務信息并把它們緩存到本地并周期性的刷新服務狀態(tài)。
構建服務注冊中心 構建注冊中心(位于spring-eureka-server的Module下)package cn.sh.eureka.server; //代碼位于該包下
1.準備pom.xml
org.springframework.boot spring-boot-starter-parent 2.0.3.RELEASE org.springframework.cloud spring-cloud-starter-eureka-server 1.2.7.RELEASE org.springframework.cloud spring-cloud-dependencies Finchley.RELEASE pom import
2.準備配置文件application.properties
#端口號 server.port=9000 eureka.instance.hostname=localhost #禁止注冊中心注冊自己 eureka.client.register-with-eureka=false #禁止注冊中心搜索服務 eureka.client.fetch-registry=false eureka.client.serviceUrl.defaultZone=http://${eureka.instance.hostname}:${server.port}/eureka/
3.編寫注冊中心代碼(@EnableEurekaServer)
package cn.sh.eureka.server; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; /** * @author sh * @EnableEurekaServer 啟動一個注冊中心 */ @EnableEurekaServer @SpringBootApplication public class EurekaServer { public static void main(String[] args) { SpringApplication.run(EurekaServer.class, args); } }構建微服務應用(服務提供者)
1.準備pom.xml
org.springframework.boot spring-boot-starter-parent 2.0.3.RELEASE org.springframework.boot spring-boot-starter-web org.springframework.cloud spring-cloud-starter-eureka 1.2.5.RELEASE org.springframework.cloud spring-cloud-dependencies Finchley.RELEASE pom import
2.準備配置文件application.properties
#端口號 server.port=8000 #服務名稱 spring.application.name=produce-service #服務注冊中心地址 eureka.client.serviceUrl.defaultZone=http://localhost:9000/eureka/
3.編寫produce-service服務的代碼
代碼位于spring-cloud-eureka-client模塊下
package cn.sh.eureka.produce; //代碼包位置高可用注冊中心搭建
?Eureka Server的高可用實際上就是講自己作為服務向其他服務注冊中心注冊自己,這樣可以形成一組互相注冊的服務注冊中心,以實現(xiàn)服務清單的互相同步,達到高可用的效果。
?相關實現(xiàn)在spring-cloud-eureka-server模塊下,注意在host配置文件中配置peer1和peer2的轉換
?將代碼通過maven編譯成jar包
?通過java命令啟動兩個注冊中心
java -jar spring-cloud-eureka-server-1.0.jar --spring.profiles.active=peer1 java -jar spring-cloud-eureka-server-1.0.jar --spring.profiles.active=peer2
?啟動之后,會發(fā)現(xiàn)在注冊中心peer1的面板上的available-replicas中出現(xiàn)http://peer2:9002/eureka/,同樣,在注冊中心peer2面板上的available-replicas中出現(xiàn)http://peer1:9001/eureka/
eureka.instance.prefer-ip-address=true, 使用IP地址的方式指定注冊中心的地址,默認false,以主機名定義注冊中心地址
服務發(fā)現(xiàn)與消費?服務消費者的主要目標是發(fā)現(xiàn)和消費服務。其中服務發(fā)現(xiàn)由Eureka客戶端完成,服務消費由Ribbon完成。
Ribbon簡單介紹?Ribbon是一個基于HTTP和TCP的客戶端負載均衡器,它可以通過在客戶端中配置的ribbonServerList服務實例列表去輪詢訪問以達到負載均衡的作用。
?Ribbon與Eureka結合使用時,ribbonServerList服務實例列表會被DiscoveryEnabledNIWSServerList重寫,擴展成從Eureka注冊中心中獲取服務列表。
?Ribbon與Eureka結合使用時,采用NIWSDiscoveryPing取代IPing,它將職責委托給Eureka來確定服務實例是否啟動。
構建消費者1.pom.xml
?增加對Ribbon的支持
org.springframework.cloud spring-cloud-starter-ribbon 1.2.7.RELEASE
2.相關代碼在spring-cloud-eureka-consumer模塊下
Eureka詳解 基礎結構服務注冊中心:Eureka服務端,提供服務注冊和發(fā)現(xiàn)的功能
服務提供者:提供服務的應用,將自己提供的服務注冊到Eureka,供其他應用發(fā)現(xiàn)
服務消費者:消費者從注冊中心發(fā)現(xiàn)服務列表,然后調(diào)用對應的服務(Ribbon或Feign)
備注: 一般一個應用既是服務提供者也是服務消費者。
服務治理機制?Eureka服務體系圖
?服務提供者會以Rest請求的方式注冊到注冊中心上,在請求過程中會攜帶自身的一些元數(shù)據(jù)信息。注冊中心在收到請求后,會將元數(shù)據(jù)信息保存到一個雙層Map結構中,外層的key是服務名稱,內(nèi)層的key是具體的服務實例名稱。
?eureka.client.register-with-eureka,如果該參數(shù)的值等于false,不會進行注冊。
?如果兩個服務注冊在兩個不同的注冊中心上,兩個注冊中心互相注冊成為服務(集群),此時,當服務提供者向其中一個注冊中心發(fā)起請求時,該注冊中心會將請求準發(fā)給集群中的其他注冊中心,從而實現(xiàn)注冊中心之間的服務同步。
?由于服務同步的存在,服務提供者的信息可以在任意一臺注冊中心上獲取。
?在服務注冊完成之后,服務提供者需要維護一個心跳來告知注冊中心服務實例處于正常運行狀態(tài)中,防止注冊中心將正常的服務實例剔除出注冊中心。上述操作就成為服務續(xù)約。
屬性 | 含義 |
---|---|
eureka.instance.lease-renewal-interval-in-seconds | 服務續(xù)約任務調(diào)用的間隔時間,默認時間30s |
eureka.instance.lease-expiration-duration-in-seconds | 服務失效時間(表示注冊中心至上一次收到客戶端的心跳之后,等待下一次心跳的超時時間,在這個時間內(nèi)若沒收到下一次心跳,則將移除該客戶端實例),默認90s |
?啟動服務消費者時,服務消費者會向注冊中心發(fā)起一個Rest請求,來獲取注冊中心維護的服務實例清單。但是為了提高性能,注冊中心會維護一份只讀的服務清單返回給客戶端,該緩存的服務清單會每隔30s刷新一次。
?eureka.client.fetch-registry,如果該參數(shù)被設置為false,無法向注冊中心獲取服務清單。
?eureka.client.registry-fetch-interval-seconds,緩存清單的刷新時間,默認30s。
?服務消費者獲得服務清單后,可以根據(jù)服務名獲取具體服務實例列表(元數(shù)據(jù)信息),根據(jù)自己的策略選擇具體的服務實例進行調(diào)用。
?Eureka有Region和Zone的概念,一個Region中會有多個Zone,每個客戶端都需要注冊到一個Zone中,所以客戶端對應一個Region和一個Zone。在服務進行調(diào)用時,優(yōu)先訪問同一個Zone中的服務提供方,若訪問不到,再訪問其他Zone。
?當服務實例正常關閉時,服務實例會發(fā)送一個服務下線的Rest請求給注冊中心。注冊中心在收到請求后,會將該服務實例的狀態(tài)置為DOWN,并且將下線時間廣播出去。
服務注冊中心?當服務實例未正常下線時(內(nèi)存溢出、網(wǎng)絡故障),服務注冊中心未能收到服務下線的Rest請求。注冊中心在啟動時會創(chuàng)建一個定時任務,默認每隔一段時間(60s)將當前清單中超時(服務失效時間,默認90s)沒有續(xù)約的服務進行剔除。
?注冊中心在運行期間,會統(tǒng)計心跳失敗比例在15分鐘內(nèi)是否低于85%,如果出現(xiàn)低于的情況,注冊中心會將當前服務實例的注冊信息保護起來,讓這些實例不會過期。但是,在保護期時間內(nèi),如果實例出現(xiàn)問題,那么服務調(diào)用者很容易拿到該實例調(diào)用失敗,所以服務調(diào)用者必須要有容錯機制(請求重試、斷路由器等)。
?eureka.server.enable-self-preservation,如果該值設置為false,則不啟用自我保護機制,默認值為true
源碼分析?分析源碼,可以以Eureka客戶端和Eureka服務端作為切入點。
Eureka客戶端在應用獲取服務列表和向注冊中心注冊成為服務時只做了兩件事:
在啟動類上使用@EnableEurekaClient或者@EnableDiscoveryClient注解
在application.properties中添加eureka.client.serviceUrl.defaultZone
@EurekaDiscoveryClient?該注解的主要作用是用來開啟一個DiscoveryClient的實例。
org.springframework.cloud.client.discovery.DiscoveryClient類?類圖以后補充
類 | 作用 |
---|---|
org.springframework.cloud.client.discovery.DiscoveryClient | Spring Cloud的接口,定義了發(fā)現(xiàn)服務的常用抽象方法,這樣做的好處是可以屏蔽服務治理的細節(jié),可以方便的切換不同的服務治理框架,不需要改動程序代碼,只需要添加一些針對服務治理框架的配置 |
com.netflix.appinfo.InstanceInfo.LookupService | 定義了Eureka發(fā)現(xiàn)服務的抽象方法 |
com.netflix.discovery.EurekaClient | 定義了Eureka發(fā)現(xiàn)服務的抽象方法,繼承LookupService |
org.springframework.cloud.netflix.eureka.EurekaDiscoveryClient | Spring中的DiscoveryClient接口的實現(xiàn),對Eureka發(fā)現(xiàn)服務的封裝,實現(xiàn)EurekaClient接口,Eureka接口繼承LookupService接口 |
com.netflix.discovery.DiscoveryClient | 實現(xiàn)EurekaClient接口,真正的服務發(fā)現(xiàn)實現(xiàn)類 |
通過頭部的注釋信息,我們可以得到以下信息:
1.DiscoveryClient類主要用于幫助客戶端和注冊中心互相協(xié)作。
2.Eureka客戶端主要負責的任務:
向注冊中心注冊服務實例
向注冊中心進行服務租約
當服務關閉期間,向注冊中心取消租約
查詢注冊中心的服務實例列表
3.Eureka客戶端需要配置一個注冊中心的URL列表
Eureka客戶端注冊中心URL列表進行配置?關鍵類:com.netflix.discovery.endpoint.EndpointUtils
?關鍵方法:Map
/** * Get the list of all eureka service urls from properties file for the eureka client to talk to. * * @param clientConfig the clientConfig to use * @param instanceZone The zone in which the client resides * @param preferSameZone true if we have to prefer the same zone as the client, false otherwise * @return an (ordered) map of zone -> list of urls mappings, with the preferred zone first in iteration order */ public static Map> getServiceUrlsMapFromConfig(EurekaClientConfig clientConfig, String instanceZone, boolean preferSameZone) { Map > orderedUrls = new LinkedHashMap<>(); String region = getRegion(clientConfig); String[] availZones = clientConfig.getAvailabilityZones(clientConfig.getRegion()); if (availZones == null || availZones.length == 0) { availZones = new String[1]; availZones[0] = DEFAULT_ZONE; } logger.debug("The availability zone for the given region {} are {}", region, availZones); int myZoneOffset = getZoneOffset(instanceZone, preferSameZone, availZones); String zone = availZones[myZoneOffset]; List serviceUrls = clientConfig.getEurekaServerServiceUrls(zone); if (serviceUrls != null) { orderedUrls.put(zone, serviceUrls); } int currentOffset = myZoneOffset == (availZones.length - 1) ? 0 : (myZoneOffset + 1); while (currentOffset != myZoneOffset) { zone = availZones[currentOffset]; serviceUrls = clientConfig.getEurekaServerServiceUrls(zone); if (serviceUrls != null) { orderedUrls.put(zone, serviceUrls); } if (currentOffset == (availZones.length - 1)) { currentOffset = 0; } else { currentOffset++; } } if (orderedUrls.size() < 1) { throw new IllegalArgumentException("DiscoveryClient: invalid serviceUrl specified!"); } return orderedUrls; }
1.加載Region、Zone
?通過getRegion函數(shù),從配置文件中讀取一個Region返回,所以一個微服務應用只能屬于一個Region,如果不進行配置,默認值default,eureka.client.region該屬性可以配置Region
?通過getAvailabilityZones函數(shù),如果沒有為Region配置Zone,默認值是defaultZone,因此注冊中心URL列表的默認配置參數(shù)為eureka.client.serviceUrl.defaultZone。eureka.client.availability-zone.
2.加載serviceUrls
?按照一定的方法以此加載每個Zone中的urls,存放在一個Map
?當使用Ribbon來調(diào)用服務時,Ribbon的默認策略是優(yōu)先訪問和客戶端處于同一個Zone的微服務實例。
?在獲取到客戶端配置的serviceUrls之后,就可以進行服務的注冊,詳情請看下面。
向注冊中心注冊服務(服務注冊)?關鍵類:com.netflix.discovery.DiscoveryClient
?關鍵方法:void initScheduledTasks(),DiscoveryClient的構造函數(shù)會對此方法進行調(diào)用
?該方法主要用來啟用定時任務,主要包括獲取服務Task、服務注冊、服務續(xù)約(心跳),本次先著重看服務注冊的邏輯
/** * Initializes all scheduled tasks. */ private void initScheduledTasks() { //此處是該方法的其他邏輯 if (clientConfig.shouldRegisterWithEureka()) { int renewalIntervalInSecs = instanceInfo.getLeaseInfo().getRenewalIntervalInSecs(); int expBackOffBound = clientConfig.getHeartbeatExecutorExponentialBackOffBound(); logger.info("Starting heartbeat executor: " + "renew interval is: {}", renewalIntervalInSecs); // Heartbeat timer // InstanceInfo replicator instanceInfoReplicator = new InstanceInfoReplicator( this, instanceInfo, clientConfig.getInstanceInfoReplicationIntervalSeconds(), 2); // burstSize 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); } instanceInfoReplicator.onDemandUpdate(); } }; if (clientConfig.shouldOnDemandUpdateStatusChange()) { applicationInfoManager.registerStatusChangeListener(statusChangeListener); } instanceInfoReplicator.start(clientConfig.getInitialInstanceInfoReplicationIntervalSeconds()); } else { logger.info("Not registering with Eureka server per configuration"); } }
1.判斷是否允許客戶端向注冊中心注冊
?eureka.client.register-with-eureka 該參數(shù)要設置成true,默認值為true
?如果上述參數(shù)值為true,則執(zhí)行注冊任務
2.新建InstanceInfoReplicator,利用其來進行注冊
?該類實現(xiàn)了Runnable接口,觀察run方法,在進行注冊時實際調(diào)用的是com.netflix.discovery.DiscoveryClient類的register()方法,下面是run方法的源碼
public void run() { try { discoveryClient.refreshInstanceInfo(); Long dirtyTimestamp = instanceInfo.isDirtyWithTime(); if (dirtyTimestamp != null) { discoveryClient.register(); instanceInfo.unsetIsDirty(dirtyTimestamp); } } catch (Throwable t) { logger.warn("There was a problem with the instance info replicator", t); } finally { Future next = scheduler.schedule(this, replicationIntervalSeconds, TimeUnit.SECONDS); scheduledPeriodicRef.set(next); } }
3.看一下DiscoveryClient.register()做了什么
?在該方法中,通過發(fā)送Rest請求進行注冊操作,在發(fā)送請求時會傳入一個InstanceInfo,該對象就是客戶端的元數(shù)據(jù)信息。
服務獲取?服務獲取任務也是在initScheduledTasks方法中啟動,由于客戶端需要不斷獲取服務端維護的服務實例清單,因此該任務會以定時任務啟動,在啟動過程會首先獲取配置文件中eureka.client.registry-fetch-interval-seconds參數(shù)配置的值(默認是30s),
然后根據(jù)配置的參數(shù)每30s(按照實際配置的值)獲取一次服務。實際獲取服務列表的時候也是發(fā)送Rest請求。
/** * Initializes all scheduled tasks. */ private void initScheduledTasks() { if (clientConfig.shouldFetchRegistry()) { // registry cache refresh timer int registryFetchIntervalSeconds = clientConfig.getRegistryFetchIntervalSeconds(); int expBackOffBound = clientConfig.getCacheRefreshExecutorExponentialBackOffBound(); scheduler.schedule( new TimedSupervisorTask( "cacheRefresh", scheduler, cacheRefreshExecutor, registryFetchIntervalSeconds, TimeUnit.SECONDS, expBackOffBound, new CacheRefreshThread() ), registryFetchIntervalSeconds, TimeUnit.SECONDS); } }服務續(xù)約
?服務在注冊到注冊中心后,需要維持一個心跳去續(xù)約,防止被剔除,因此服務續(xù)約和服務注冊是成對存在,在同一個if條件里。首先會獲取配置文件參數(shù)中eureka.instance.lease-renewal-interval-in-seconds的值,該值默認30s,隨后啟動定時任務,每隔30s(根據(jù)實際配置的值)向注冊中心發(fā)一次Rest請求,表明自己還活著。
/** * Initializes all scheduled tasks. */ private void initScheduledTasks() { if (clientConfig.shouldRegisterWithEureka()) { int renewalIntervalInSecs = instanceInfo.getLeaseInfo().getRenewalIntervalInSecs(); int expBackOffBound = clientConfig.getHeartbeatExecutorExponentialBackOffBound(); logger.info("Starting heartbeat executor: " + "renew interval is: {}", renewalIntervalInSecs); // Heartbeat timer scheduler.schedule( new TimedSupervisorTask( "heartbeat", scheduler, heartbeatExecutor, renewalIntervalInSecs, TimeUnit.SECONDS, expBackOffBound, new HeartbeatThread() ), renewalIntervalInSecs, TimeUnit.SECONDS); } }服務注冊中心處理
?注冊中心處理Rest請求的類位于com.netflix.eureka.resources包下
?比如com.netflix.eureka.resources.ApplicationResource類中的addInstance()方法主要用來處理客戶端的注冊事件。
?注冊中心在收到客戶端發(fā)送注冊請求以后,會首先對客戶端的信息進行校驗,校驗過后會調(diào)用org.springframework.cloud.netflix.eureka.server.InstanceRegistry的register()方法來進行服務注冊。
?register()方法會調(diào)用publishEvent()方法將服務注冊的事件傳播出去,緊接著調(diào)用父類com.netflix.eureka.registry.AbstractInstanceRegistry中的register()實現(xiàn),該方法會將InstanceInfo中的元數(shù)據(jù)信息保存到一個ConcurrentHashMap中。
?該HashMap有兩層數(shù)據(jù)結構,正如我們之前所說,第一層的Key存儲服務名(InstanceInfo中的appName屬性),第二層Key存儲服務實例名稱(InstanceInfo中的instanceId屬性)
配置詳解Eureka客戶端的配置主要有以下兩個方面:
服務注冊相關的配置信息,包括注冊中心的地址、服務獲取的時間間隔、可用區(qū)域(Zone)等;
服務實例相關的配置信息,包括服務實例的名稱、IP地址、端口號、健康檢查路徑等。
?客戶端的配置類可以參考org.springframework.cloud.netflix.eureka.EurekaClientConfigBean
?服務端的配置類可以參考org.springframework.cloud.netflix.eureka.server.EurekaServerConfigBean
服務注冊相關的配置?這些配置信息都以eureka.client作為前綴
指定注冊中心?指定注冊中心主要靠eureka.client.serviceUrl參數(shù),該參數(shù)的配置值值存儲在HashMap中,并且會有一組默認值,默認值的Key是defaultZone,value為http://localhost:8761/eureka/。
?當構建了高可用的服務注冊中心集群時,參數(shù)的value可以配置多個注冊中心(通過,分隔)。
?為了注冊中心的安全考慮,需要為服務注冊中心加入安全校驗。因此客戶端在配置注冊中心serviceUrl中時需要加入相應的安全校驗信息。比如http://
參數(shù)名 | 說明 | 默認值 |
---|---|---|
enabled | 啟用Eureka客戶端 | true |
registryFetchIntervalSeconds | 從服務注冊中心獲取注冊信息(服務實例清單)的間隔時間,單位s | 30 |
instanceInfoReplicationIntervalSeconds | 更新實例信息的變化到Eureka服務端的間隔時間,單位s | 30 |
initialInstanceInfoReplicationIntervalSeconds | 最初更新實例信息到Eureka服務端的間隔時間,單位s | 40 |
eurekaServiceUrlPollIntervalSeconds | 輪詢Eureka服務端地址更改的間隔時間,單位s。當我們與Spring Cloud Config配合,動態(tài)刷新Eureka的serviceUrl地址時需要關注該參數(shù) | 300 |
eurekaServerReadTimeoutSeconds | 讀取注冊中心信息的超時時間,單位s | 8 |
eurekaServerConnectTimeoutSeconds | 連接注冊中心的超時時間,單位s | 5 |
eurekaServerTotalConnections | 從Eureka客戶端到所有Eureka服務端的連接總數(shù) | 200 |
eurekaServerTotalConnectionsPerHost | 從Eureka客戶端到每個Eureka服務端主機的連接總數(shù) | 50 |
eurekaConnectionIdleTimeoutSeconds | Eureka服務端連接的空閑關閉時間 | 30 |
heartbeatExecutorThreadPoolSize | 心跳連接池的初始化線程數(shù) | 2 |
heartbeatExecutorExponentialBackOffBound | 心跳超時重試延遲時間的最大乘數(shù)值 | 10 |
cacheRefreshExecutorThreadPoolSize | 緩存刷新線程池的初始化線程池數(shù) | 2 |
cacheRefreshExecutorExponentialBackOffBound | 緩存刷新重試延遲時間的最大乘數(shù)值 | 10 |
useDnsForFetchingServiceUrls | 使用DNS來獲取Eureka服務端的serviceUrl | false |
registerWithEureka | 是否要將自身的實例信息注冊到Eureka服務端 | true |
preferSameZoneEureka | 是否偏好使用處于相同Zone的Eureka服務端 | true |
filterOnlyUpInstances | 獲取實例時是否過濾,僅保留UP狀態(tài)的實例 | true |
fetchRegistry | 是否從Eureka服務端獲取注冊信息 | true |
?該配置可以參考org.springframework.cloud.netflix.eureka.EurekaInstanceConfigBean類,這些配置都以eureka.instance開頭
元數(shù)據(jù)?在EurekaInstanceConfigBean類中有一大部分內(nèi)容是對服務實例元數(shù)據(jù)的配置,它是Eureka客戶端在向注冊中心發(fā)送注冊請求時,用來描述自身服務信息的對象。
?在使用Spring Cloud Eureka時,所有的配置信息都是通過EurekaInstanceConfigBean對象進行加載,但真正進行服務注冊的時候,會包裝成com.netflix.appinfo.InstanceInfo對象發(fā)送給Eureka服務端。
?在InstanceInfo類中,Map
?在配置文件可以通過eureka.instance.
?實例名,即InstanceInfo中的instanceId,它是區(qū)別同一服務中不同實例的唯一標識。
?在原生的Netflix Eureka中,實例名稱采用主機名作為默認值,這樣的弊端就是無法在同一主機上啟動多個相同的服務實例。
?在Spring Cloud Eureka中,對實例名的默認值做了更合理的擴展,它采用了${spring.cloud.client.hostname}:${spring.application.name}:${spring.application.instance_id:${server.port}}
?實例名的命名規(guī)則,可以通過eureka.instance.instance-id進行配置,比如在客戶端進行負載均衡調(diào)用時,需要啟動多個端口進行調(diào)試,此時就可以修改eureka.instance.instance-id=${spring.application.name}:${random.int}
端點配置?在InstanceInfo中,可以看到一些URL的配置信息,如:homePageUrl、statusPageUrl、healthCheckUrl等,它分別代表了應用主頁的URL、狀態(tài)頁的URL、健康檢查的URL。
?狀態(tài)頁和健康檢查的URL默認使用了spring-boot-actuator模塊提供的/actuator/info和/actuator/health端點(2.0版本之前不帶/actuator前綴)。
?為了服務的正常運作,必須確保/actuator/health端點是一個能夠被注冊中心可以訪問的地址,否則注冊中心不會根據(jù)應用的健康檢查來更新狀態(tài)(只有eureka.client.healthcheck.enabled=true時才會以該端點對服務進行健康監(jiān)測,否則會以客戶端心跳的方式。)。
?/info端點如果不正確,會導致在注冊中心點擊服務實例鏈接,會無法獲取到服務實例提供的信息接口。
?在大多數(shù)情況下,并不需要修改URL的配置,但是不排除特殊情況需要對這些URL做配置。比如:為應用設置context-path,這時,所有spring-boot-actuator模塊的監(jiān)控端點都會增加一個前綴。示例配置如下:
server.servlet.context-path=/produce eureka.instance.status-page-url-path=${server.servlet.context-path}/info eureka.instance.health-check-url-path=${server.servlet.context-path}/health
?eureka.instance.status-page-url-path和eureka.instance.health-check-url-path兩個參數(shù)均使用相對路徑來配置。
?eureka.instance.status-page-url和eureka.instance.health-check-url兩個配置參數(shù)使用絕對路徑進行配置。對比上面可以發(fā)現(xiàn),如果使用相對路徑后面參數(shù)后綴都會跟著path
健康檢測?默認情況下,Eureka中各個服務實例的健康檢測并不是通過spring-cloud-actuator模塊的/actuator/health節(jié)點,而是依靠客戶端的心跳來保持服務的存活。
?默認的客戶端心跳方式無法保證客戶端提供正常的服務。比如微服務一般會有依賴的外部資源(如數(shù)據(jù)庫、緩存、消息代理等),假如與這些外部資源無法聯(lián)通,但是客戶端心跳依舊存在,這就會導致調(diào)用出現(xiàn)問題。
?使用spring-boot-actuator模塊的/actuator/health端點,只需要兩部曲:
在pom.xml文件中引入spring-boot-actuator依賴
在配置文件中加入eureka.client.healthcheck.enabled=true
其他配置參數(shù) | 說明 | 默認值 |
---|---|---|
preferIpAddress | 是否優(yōu)先以使用IP地址作為主機名的標識 | false |
leaseRenewalIntervalInSeconds | 客戶端向注冊中心發(fā)送心跳的間隔時間,單位s | 30 |
leaseExpirationDurationInSeconds | 服務端在收到最后一次心跳后的等待時間上限,單位s。超過該時間會對服務進行剔除。 | 90 |
nonSecurePort | 非安全的通信端口號 | 80 |
securePort | 安全的通信端口號 443 | |
nonSecurePortEnabled | 是否啟用非安全的通信端口號 | true |
securePortEnabled | 是否啟用安全的通信端口號 | true |
appname | 服務名,默認會取spring.application.name的值 | unknown |
hostname | 主機名 | 根據(jù)計算操作系統(tǒng)的主機名進行取值 |
spring-cloud-eureka代碼
文章版權歸作者所有,未經(jīng)允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/76494.html
摘要:下一篇介紹基于的服務注冊與調(diào)用。服務提供者工程配置這里服務提供者是使用之前進階教程第三篇整合連接池以及監(jiān)控改造而來,這里一樣的部分就不再重復說明,下面將說明新增的部分。 Spring Cloud簡介 Spring Cloud是一個基于Spring Boot實現(xiàn)的云應用開發(fā)工具,它為基于JVM的云應用開發(fā)中涉及的配置管理、服務發(fā)現(xiàn)、斷路器、智能路由、微代理、控制總線、全局鎖、決策競選、分...
摘要:筆者也是初學者,本文從創(chuàng)建項目工程開始,一步一步開始講解如何創(chuàng)建服務端和客戶端,一起學習,共同進步。下面我們使用工具創(chuàng)建相關項目。配置其中兩個屬性表明這個應用是端,而不是端。至此,端和端已經(jīng)部署成功。 前言 spring cloud為互聯(lián)企業(yè)構建微服務提供了一整套的技術組件,其中Eureka是Spring Cloud體系中的核心。Netfix不是一個技術概念,它原本是國外一個視頻網(wǎng)站的...
摘要:授權框架使第三方應用程序來獲取對服務的有限訪問機會。無論是通過編排資源所有者和服務之間的交互批準的資源所有者,或通過允許第三方應用程序來獲取自己的訪問權限。 SpringCloud打造微服務平臺--概覽 簡述 SpringCloud是什么 Spring Boot和SpringCloud是什么關系 Spring Boot是Spring的一套快速WEB開發(fā)的腳手架,可建立獨立的Sprin...
摘要:本例中介紹如何使用來完成服務調(diào)用并實現(xiàn)負載均衡。即,對于注冊中心而言,生產(chǎn)者和調(diào)用者都是端。文件配置如下在文件中,我們將應用命名為,端口為,表示注冊中心地址。 前言 Ribbon是Spring Cloud體系中完成負載均衡的重要組件。Spring Cloud體系中有兩種完成服務調(diào)用的組件,一種是Ribbon+RestTemplate,另一種Feign。Feign默認使用的也是Ribbo...
閱讀 2189·2021-11-15 11:38
閱讀 1151·2021-09-06 15:02
閱讀 3380·2021-08-27 13:12
閱讀 1353·2019-08-30 14:20
閱讀 2389·2019-08-29 15:08
閱讀 636·2019-08-29 14:08
閱讀 1723·2019-08-29 13:43
閱讀 1464·2019-08-26 12:11