eureka server集群部署的情况下,eureka-client通信的时候是如何选择的?
当eureka-server是集群部署的场景下,eureka-client注册的时候,到底会选择那一个节点进行注册呢,看图:
源码在这个类里边com.netflix.discovery.shared.transport.decorator.RetryableEurekaHttpClient#execute
protected <R> EurekaHttpResponse<R> execute(RequestExecutor<R> requestExecutor) {
List<EurekaEndpoint> candidateHosts = null;//注册中心地址列表
int endpointIdx = 0;
for (int retry = 0; retry < numberOfRetries; retry++) {
EurekaHttpClient currentHttpClient = delegate.get();//获取上次保存的注册中心的地址
EurekaEndpoint currentEndpoint = null;
if (currentHttpClient == null) {
if (candidateHosts == null) {
candidateHosts = getHostCandidates();
if (candidateHosts.isEmpty()) {
throw new TransportException("There is no known eureka server; cluster server list is empty");
}
}
if (endpointIdx >= candidateHosts.size()) {
throw new TransportException("Cannot execute request on any known server");
}
currentEndpoint = candidateHosts.get(endpointIdx++);//获取第endpointIdx个注册中心的地址
currentHttpClient = clientFactory.newClient(currentEndpoint);
}
try {
EurekaHttpResponse<R> response = requestExecutor.execute(currentHttpClient);
if (serverStatusEvaluator.accept(response.getStatusCode(), requestExecutor.getRequestType())) {
delegate.set(currentHttpClient);//请求成功将这此次的通讯的注册中心存储到AtomicReference
if (retry > 0) {
logger.info("Request execution succeeded on retry #{}", retry);
}
return response;//返回
}
logger.warn("Request execution failure with status code {}; retrying on another server if available", response.getStatusCode());
} catch (Exception e) {
logger.warn("Request execution failed with message: {}", e.getMessage()); // just log message as the underlying client should log the
}
// Connection error or 5xx from the server that must be retried on another server
delegate.compareAndSet(currentHttpClient, null);//请求失败会通过cas将上次保存的注册中心地址给置null,然后进行重试
if (currentEndpoint != null) {
quarantineSet.add(currentEndpoint);
}
}
throw new TransportException("Retry limit reached; giving up on completing the request");//达到重试上限还没有请求成功就抛出异常
}
1.从delegate里边获取上次保存的注册中心的地址
2.当获取不到是,从candidateHosts获取第endpointIdx个注册中心的地址
3.进行通信
4.请求成功会将此次通信的注册中心的地址保存到delegate里边,方便下次直接使用
5.完成后返回
6.如果再第4步的时候报错了,就会把delegate保存的数据置空,继续进行重试。继续走一下 1,2,3,4,5。
7.达到重试上限就会抛出异常