一、概要
上一篇文章大致分析了eureka的整體流程。eureka client通過(guò)一個(gè)定時(shí)器定時(shí)上報(bào)心跳信息到eureka server。并且會(huì)定時(shí)拉取eureka server的服務(wù)列表到本地。
這里存在幾個(gè)問(wèn)題。
- eureka server之間的數(shù)據(jù)一致性如何保證?
eureka server是要cp,還是ap? - eureka client和eureka server之間的一致性如何保證?
獲取服務(wù)列表存在時(shí)延,有可能一個(gè)已經(jīng)失效的結(jié)點(diǎn)還會(huì)在client中保留一段時(shí)間,或者一個(gè)新加入的結(jié)點(diǎn)還沒(méi)有同步到client。如何解決這種問(wèn)題?
這篇文章先對(duì)eureka client的源碼做了解。
二、源碼分析
客戶端核心的代碼在DiscoveryClient。

類關(guān)系圖
eureka實(shí)例在初始化的時(shí)候會(huì)調(diào)用initScheduledTasks的方法,初始化定時(shí)任務(wù),這里面就包含定時(shí)向eureka server上報(bào)心跳的任務(wù)。
/**
* Initializes all scheduled tasks.
*/
private void initScheduledTasks() {
...
// Heartbeat timer
scheduler.schedule(
new TimedSupervisorTask(
"heartbeat",
scheduler,
heartbeatExecutor,
renewalIntervalInSecs,
TimeUnit.SECONDS,
expBackOffBound,
new HeartbeatThread()
),
renewalIntervalInSecs, TimeUnit.SECONDS);
...
我們接下來(lái)看下心跳告警線程的代碼
/**
* The heartbeat task that renews the lease in the given intervals.
*/
private class HeartbeatThread implements Runnable {
public void run() {
if (renew()) {
lastSuccessfulHeartbeatTimestamp = System.currentTimeMillis();
}
}
}
/**
* Renew with the eureka service by making the appropriate REST call
*/
boolean renew() {
EurekaHttpResponse<InstanceInfo> httpResponse;
try {
httpResponse = eurekaTransport.registrationClient.sendHeartBeat(instanceInfo.getAppName(), instanceInfo.getId(), instanceInfo, null);
logger.info("{} - Heartbeat status: {}", PREFIX + appPathIdentifier, httpResponse.getStatusCode());
if (httpResponse.getStatusCode() == 404) {
REREGISTER_COUNTER.increment();
logger.info("{} - Re-registering apps/{}", PREFIX + appPathIdentifier, instanceInfo.getAppName());
return register();
}
return httpResponse.getStatusCode() == 200;
} catch (Throwable e) {
logger.error("{} - was unable to send heartbeat!", PREFIX + appPathIdentifier, e);
return false;
}
}
eureka采用的也是http協(xié)議,如果返回404返回碼,客戶端會(huì)選擇重新注冊(cè)信息到eureka server。
http協(xié)議報(bào)文如下:
Hypertext Transfer Protocol
PUT /eureka/v2/apps/SAMPLEREGISTERINGSERVICE/201709-07262?status=UP&lastDirtyTimestamp=1552742035025 HTTP/1.1\r\n
DiscoveryIdentity-Name: DefaultClient\r\n
DiscoveryIdentity-Version: 1.4\r\n
DiscoveryIdentity-Id: 172.19.10.230\r\n
Accept-Encoding: gzip\r\n
Content-Length: 0\r\n
Host: localhost:8080\r\n
Connection: Keep-Alive\r\n
User-Agent: Java-EurekaClient/v<version_unknown>\r\n
\r\n
[Full request URI: http://localhost:8080/eureka/v2/apps/SAMPLEREGISTERINGSERVICE/201709-07262?status=UP&lastDirtyTimestamp=1552742035025]
[HTTP request 1/1]
[Response in frame: 7296]
。。。to be continued