在Springcloud中,注册中心是一个不可缺少的组件,eureka便是一个比较经典的注册组件。虽然现在eureka已经停止了维护,在实际项目中仍然会有不少应用,对其源码进行了解,能够更好的理解整个注册中心的功能。
eureka根据功能的不同,分为客户端和服务端。本文主要探究的是客户端。
对于客户端来说,想要把微服务注册到注册中心,一般来说都要引入如下pom文件:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
ctlr+鼠标左键点击,可以看到其是一个组合依赖,其依赖主体为:
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-netflix-eureka-client</artifactId> <version>2.2.6.RELEASE</version> <scope>compile</scope> </dependency> <dependency> <groupId>com.netflix.eureka</groupId> <artifactId>eureka-client</artifactId> <version>1.10.7</version> ......
找到相关依赖jar包,在META-INF下面的spring.factories文件,可以看到其自动装配的配置:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.cloud.netflix.eureka.config.EurekaClientConfigServerAutoConfiguration,\
org.springframework.cloud.netflix.eureka.config.DiscoveryClientOptionalArgsConfiguration,\
org.springframework.cloud.netflix.eureka.EurekaClientAutoConfiguration,\
org.springframework.cloud.netflix.ribbon.eureka.RibbonEurekaAutoConfiguration,\
org.springframework.cloud.netflix.eureka.EurekaDiscoveryClientConfiguration,\
org.springframework.cloud.netflix.eureka.reactive.EurekaReactiveDiscoveryClientConfiguration,\
org.springframework.cloud.netflix.eureka.loadbalancer.LoadBalancerEurekaAutoConfiguration
可以看到,红色标记的全类名便是eureka客户端自动装配的启动类。点击进去,我们可以看到其对eureka客户端的配置:
@Bean( destroyMethod = "shutdown" ) @ConditionalOnMissingBean( value = {EurekaClient.class}, search = SearchStrategy.CURRENT ) @org.springframework.cloud.context.config.annotation.RefreshScope @Lazy public EurekaClient eurekaClient(ApplicationInfoManager manager, EurekaClientConfig config, EurekaInstanceConfig instance, @Autowired(required = false) HealthCheckHandler healthCheckHandler) { ApplicationInfoManager appManager; if (AopUtils.isAopProxy(manager)) { appManager = (ApplicationInfoManager)ProxyUtils.getTargetObject(manager); } else { appManager = manager; } CloudEurekaClient cloudEurekaClient = new CloudEurekaClient(appManager, config, this.optionalArgs, this.context); //客户端向服务端注册 cloudEurekaClient.registerHealthCheck(healthCheckHandler); return cloudEurekaClient; }
通过红色代码可以看出,这是实现eureka客户端向服务端注册中心注册的源码实现。
一路追踪,再结合上文引入的eureka-client的jar包,可以看到最终的注册实现是由
com.netflix.discovery.DiscoveryClient这个类的register方法实现,其过程为:
public boolean onDemandUpdate() {
if (this.rateLimiter.acquire(this.burstSize, (long)this.allowedRatePerMinute)) {
if (!this.scheduler.isShutdown()) {
this.scheduler.submit(new Runnable() {
public void run() {
InstanceInfoReplicator.logger.debug("Executing on-demand update of local InstanceInfo");
Future latestPeriodic = (Future)InstanceInfoReplicator.this.scheduledPeriodicRef.get();
if (latestPeriodic != null && !latestPeriodic.isDone()) {
InstanceInfoReplicator.logger.debug("Canceling the latest scheduled update, it will be rescheduled at the end of on demand update");
latestPeriodic.cancel(false);
}
InstanceInfoReplicator.this.run();
}
......
}
public void run() {
boolean var6 = false;
ScheduledFuture next;
label53: {
try {
var6 = true;
this.discoveryClient.refreshInstanceInfo();
Long dirtyTimestamp = this.instanceInfo.isDirtyWithTime();
if (dirtyTimestamp != null) {
this.discoveryClient.register();
最后进入具体执行的方法:
boolean register() throws Throwable {
logger.info("DiscoveryClient_{}: registering service...", this.appPathIdentifier);
EurekaHttpResponse httpResponse;
try {
httpResponse = this.eurekaTransport.registrationClient.register(this.instanceInfo);
} catch (Exception var3) {
logger.warn("DiscoveryClient_{} - registration failed {}", new Object[]{this.appPathIdentifier, var3.getMessage(), var3});
throw var3;
}
if (logger.isInfoEnabled()) {
logger.info("DiscoveryClient_{} - registration status: {}", this.appPathIdentifier, httpResponse.getStatusCode());
}
return httpResponse.getStatusCode() == Status.NO_CONTENT.getStatusCode();
}
通过源码的字面意思,可以看到这就是一个http请求,给eureka服务端发送http请求来实现对其注册,并通过状态码来判断是否注册成功。
其核心方法为抽象类EurekaHttpClientDecorator及其四个继承类及其作用如下:
RetryableEurekaHttpClient(Http请求失败进行重试),
RedirectingEurekaHttpClient(重定向到不同的EurekaServer)
MetricsCollectingEurekaHttpClient(统计执行指标)
AbstractJerseyEurekaHttpClient(使用jersey发起注册)
最后,会调用AbstractJerseyEurekaHttpClient的register方法注册:
public abstract class EurekaHttpClientDecorator implements EurekaHttpClient {
public EurekaHttpClientDecorator() {}
protected abstract <R> EurekaHttpResponse<R> execute(EurekaHttpClientDecorator.RequestExecutor<R> var1);
public EurekaHttpResponse<Void> register(final InstanceInfo info) {
return this.execute(new EurekaHttpClientDecorator.RequestExecutor<Void>() {
public EurekaHttpResponse<Void> execute(EurekaHttpClient delegate) {
return delegate.register(info);
}
public EurekaHttpClientDecorator.RequestType getRequestType() {
return EurekaHttpClientDecorator.RequestType.Register;
}
});
}....
public EurekaHttpResponse<Void> register(InstanceInfo info) {
String urlPath = "apps/" + info.getAppName();
ClientResponse response = null;
EurekaHttpResponse var5;
try {
Builder resourceBuilder = this.jerseyClient.resource(this.serviceUrl).path(urlPath).getRequestBuilder();
this.addExtraHeaders(resourceBuilder);
response = (ClientResponse)((Builder)((Builder)((Builder)resourceBuilder.header("Accept-Encoding", "gzip")).type(MediaType.APPLICATION_JSON_TYPE)).accept(new String[]{"application/json"})).post(ClientResponse.class, info);
var5 = EurekaHttpResponse.anEurekaHttpResponse(response.getStatus()).headers(headersOf(response)).build();
} finally {
......
return var5;
}
可以看到,其最终就是一个http请求,根据返回状态来判断是否注册成功。
本文详细解析了Spring Cloud中Eureka客户端如何通过HTTP请求向Eureka服务端注册微服务的过程,包括依赖引入、自动配置及核心类的具体实现。
1049

被折叠的 条评论
为什么被折叠?



