by shihang.mai
1. 啟動(dòng)
1.1 查看注解注解@EnableEurekaServer
找到類EurekaServerMarkerConfiguration,發(fā)現(xiàn)只是new Marker()類
@Configuration(proxyBeanMethods = false)
public class EurekaServerMarkerConfiguration {
@Bean
public Marker eurekaServerMarkerBean() {
return new Marker();
}
class Marker {
}
}
1.2 查看jar中spring.factories文件
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.cloud.netflix.eureka.server.EurekaServerAutoConfiguration
找到類EurekaServerAutoConfiguration,看到@ConditionalOnBean(EurekaServerMarkerConfiguration.Marker.class)
@Configuration(proxyBeanMethods = false)
@Import(EurekaServerInitializerConfiguration.class)
@ConditionalOnBean(EurekaServerMarkerConfiguration.Marker.class)
@EnableConfigurationProperties({ EurekaDashboardProperties.class,
InstanceRegistryProperties.class })
@PropertySource("classpath:/eureka/server.properties")
public class EurekaServerAutoConfiguration implements WebMvcConfigurer {
.....
}
加載條件是有Maker對(duì)象,再看@Import(EurekaServerInitializerConfiguration.class),這個(gè)類就是初始化核心類
2. eureka的CAP
eureka是典型的AP,原因如下:
2.1 三級(jí)緩存
設(shè)置3級(jí)緩存是為了減少讀寫沖突
#是否讀取3級(jí)緩存,默認(rèn)為true
eureka.server.use-read-only-response-cache=true/false
#2級(jí)緩存到3級(jí)緩存的定時(shí)間隔
eureka.server.response-cache-update-interval-ms=1000
- 在eureka-server啟動(dòng)時(shí),會(huì)初始化三級(jí)緩存。由上向下分別是
- registry
- readWriteCacheMap
- readOnlyCacheMap
- 每次注冊(cè)服務(wù)時(shí),先向registry注冊(cè),然后清除readWriteCacheMap中自己服務(wù)的緩存
- 在eureka-client獲取服務(wù)時(shí),
- 默認(rèn)先從readOnlyCacheMap獲取,獲取不到再向readWriteCacheMap獲取
- 當(dāng)eureka.server.use-read-only-response-cache=false時(shí),直接從readWriteCacheMap獲取
ps:在獲取readWriteCacheMap時(shí),會(huì)從LocalCache加載數(shù)據(jù)到readWriteCacheMap
- 通過定時(shí)任務(wù)每30s,將readWriteCacheMap的數(shù)據(jù)同步到readOnlyCacheMap
2.2 集群同步
場(chǎng)景如下,開啟相互拉取:
現(xiàn)有eureka-server1(es1),微服務(wù)A已注冊(cè)到es1
當(dāng)有eureka-server1(es2)啟動(dòng)做集群,那么會(huì)拉取es1的服務(wù)列表,之后再向es1注冊(cè)微服務(wù)B時(shí),并不會(huì)去同步數(shù)據(jù)到es2.每間一段時(shí)間,es2才會(huì)去拉取es1數(shù)據(jù)
#默認(rèn)拉取服務(wù)列表時(shí)間為30s
eureka.client.registry-fetch-interval-seconds=30
3. eureka-server服務(wù)承受計(jì)算
模擬注冊(cè)和讀取算一個(gè),得出10萬(wàn)/s,除去其他代碼,我算除以100倍,那么1k/s
服務(wù)數(shù):20個(gè)
每個(gè)服務(wù)集群數(shù):5個(gè)
接受心跳:2次/分鐘
接受拉取:2次/分鐘
那么每秒承受訪問:20 * 5 * 2 * 2 =400/s
集群沒提高承受能力,只是做了HA,因?yàn)楣?jié)點(diǎn)間是全量鏡像
4. eureka-server能力
- 提供注冊(cè)
eureka-client向其注冊(cè)時(shí),只會(huì)向一個(gè)節(jié)點(diǎn)注冊(cè)。其他節(jié)點(diǎn)通過定時(shí)任務(wù)拉取服務(wù)列表 - 接受心跳(續(xù)約)
eureka-client向其發(fā)送心跳時(shí),會(huì)觸發(fā)集群同步 - 接受下線
eureka-client向其發(fā)送下線時(shí),會(huì)觸發(fā)集群同步 - 剔除服務(wù)
每個(gè)eureka-server都有自己的剔除,剔除也是定時(shí)任務(wù),配置如下
#剔除服務(wù)的時(shí)間
eureka.server.eviction-interval-timer-in-ms=1000
- 默認(rèn)開啟自我保護(hù)機(jī)制,配置如下。當(dāng)關(guān)閉了自我保護(hù)機(jī)制,那么直接剔除
#是否開啟自我保護(hù)
eureka.server.enable-self-preservation=true/false
- 開啟自我保護(hù),最后一分鐘續(xù)約數(shù)大于閾值(配置如下),剔除,少于閾值,開啟自我保護(hù),不剔除
#自我保護(hù)閾值
eureka.server.renewal-percent-threshold=0.80
- 接受拉取注冊(cè)表
- 每個(gè)eureka-client都會(huì)定時(shí)拉取eureka-server注冊(cè)表,分全量拉取和增量拉取
- eureka-client在注冊(cè)到eureka-server,就會(huì)立刻拉取注冊(cè)表(開啟互相拉取模式的eureka-server集群,它們之間互為eureka-client)
- eureka-client40秒后拉取
集群同步
區(qū)域訪問
eureka-server端http://server1:8080/eureka,http://server2:8081/eureka
eureka.client.region=gz
eureka.client.availability-zones.gz=z1,z2
eureka.client.service-url.z1=http://server1:8080/eureka,http://server2:8081/eureka
eureka.client.service-url.z2=http://server3:8083/eureka,http://server4:8084/eureka
eureka-server端http://server3:8083/eureka,http://server4:8084/eureka
eureka.client.region=gz
eureka.client.availability-zones.gz=z2,z1
eureka.client.service-url.z1=http://server1:8080/eureka,http://server2:8081/eureka
eureka.client.service-url.z2=http://server3:8083/eureka,http://server4:8084/eureka
eureka-client端無(wú)論是provider還是consumer
eureka.client.region=gz
eureka.client.availability-zones.gz=z1,z2
eureka.client.service-url.z1=http://server1:8080/eureka,http://server2:8081/eureka
eureka.client.service-url.z2=http://server3:8083/eureka,http://server4:8084/eureka
eureka.client.prefer-same-zone-eureka=true
#用這個(gè)定位
eureka.instance.metadata-map.zone=z1
eureka-client端無(wú)論是provider還是consumer
eureka.client.region=gz
eureka.client.availability-zones.gz=z2,z1
eureka.client.service-url.z1=http://server1:8080/eureka,http://server2:8081/eureka
eureka.client.service-url.z2=http://server3:8083/eureka,http://server4:8084/eureka
eureka.client.prefer-same-zone-eureka=true
#用這個(gè)定位
eureka.instance.metadata-map.zone=z2
就是就近訪問
5. 吐槽
- 源碼中使用了Timer。在多線程并行處理定時(shí)任務(wù)時(shí),Timer運(yùn)行多個(gè)TimerTask時(shí),只要其中之一沒捕獲異常,其他任務(wù)都會(huì)自動(dòng)終止.使用ScheduleExcutorServer代替
- eureka-client端只會(huì)拉取地址列表的一個(gè)的注冊(cè)表,失敗之后才拉取下一個(gè)。而且代碼中寫死了3個(gè)。所以超過3個(gè)集群是沒用的。