Eureka源码解析之Eureka Cilent

在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请求,根据返回状态来判断是否注册成功。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值