一.spring cloud简介

   spring cloud解决的痛点是微服务落地。它集合了服务治理,智能路由,熔断器,链路监控,网关等功能。其中服务治理现在用的比较多的框架的dubbo。相比dubbo可以看到它拥有更多的功能,不需要重复造轮子。而且spring cloud用http协议进行交互,rest形式的接口,比较轻量,这样不同客户端可以直接调用。性能上默认spring cloud是短连接,因此这个方面比dubbo要差点。但http有长连接功能,因此在想能不能用长连接提升性能,当然具体也要看业务场景业务要求。

  spring cloud中,核心角色,注册中心,服务提供方,服务消费方。注册中心是EurekaServer,服务提供方及消费方均是EurekaClient实例。

  注册中心,服务提供方,服务消费间交互用http。每个注册中心,服务提交方及消费方都可定义region及zone表明是属于哪个区域。这个功能可以结合实际物理结构来实现同机房或同区域结点消费方优先调用同区域服务提供方以此提高性能。

二.生产者注册过程

   

1.启动InstanceInfoReplicator单线程定时任务,

2.执行CloudEurekaClient.register

3.执行SessionEurekaHttpClient.execute

4.RetryableEurekaHttpClient.execute

5.RedirectingEurekaHttpClient.execute ->

6.MetricsCollectingEurekaHttpClient.execute

7.AbstractJerseyEurekaHttpClient.register

上述是生产者注册过程核心调用链。

后续会详细说明每一点的作用.

InstanceInfoReplicator就是一个runable任务,核心职责是定时刷新dataCenterInfo数据中心信息,leaseinfo以及当前结点状态。

其中dataCenterInfo及leaseInfo改变的原因是由于配置的变化。

InstanceInfoReplicator默认30秒,会刷新dataCenter,,leaseInfo以及当前结点的状态。

leaseInfo则记录了两个比较重要的参数:

a.LeaseExpirationDurationInSeconds (默认90秒)

即Server注册中心端默认多少秒没有收到client端心跳就认为client失效了,失效后会将对应client从注册中心移除。

b.LeaseRenewalIntervalInSeconds (默认30秒)

client多少时间发送心跳给server注册中心。

这段刷新的代码:

public void run() {
        try {
            discoveryClient.refreshInstanceInfo();

            Long dirtyTimestamp = instanceInfo.isDirtyWithTime();
            if (dirtyTimestamp != null) {
                discoveryClient.register();
                instanceInfo.unsetIsDirty(dirtyTimestamp);
            }
        } catch (Throwable t) {
            logger.warn("There was a problem with the instance info replicator", t);
        } finally {
            Future next = scheduler.schedule(this, replicationIntervalSeconds, TimeUnit.SECONDS);
            scheduledPeriodicRef.set(next);
        }
    }

这里的核心方法是:discoveryClient.register方法。

这里用了装饰者模式,JerseyApplicationClient是具体被装饰者,

EurekaHttpClientDecorator是抽象装饰者,所以具体装饰者继承它。

具体装饰者有:

SessionEurekaHttpClient,RetryableEurekaHttpClient,RedirectingEurekaHttpClient,MetricsCollectingEurekaHttpClient。

这个方法执行过程如下:

1.SessionEurekaHttpClient.execute

这个装饰者类作用是当上次重连时间与当前时间相比,超过一定时就关闭原有连接,重新创建一个连接。主要目的保证不要永远连在一台EurekaServre上,尽量负载分开点。默认重连时间:1200000毫秒,即20分钟。

2.RetryableEurekaHttpClient

这个类向一个EurekaServer发起一个请求时,如果这个EurekaServer挂了,那么就会重试。默认重试3次。

核心实现逻辑是,请求一个EurekaServer失败后将其加入quarantineSet,下次重试时忽略这台server。

RedirectingEurekaHttpClient

这个类执行重定向逻辑,具体是请求服务器,如果服务器返回302 statusCode则创建与要跳转的目的url的连接(服务端返回)。

4.MetricsCollectingEurekaHttpClient

这个类就是统一总执行数,错误调用数,以及每个http返回statusCode的状态数。

5.最终由JerseyApplicationClient 调用apache httpClient

最终会调用apache httpClient类请求远程server。注意是短连接,创建后一段时间如果客户端卡在某个点超过一定时间,服务端超时会主动关闭。

JerseyApplicationClient执行时还会执行一些过滤器如:

>EurekaIdentityHeaderFilter.handle //过滤链,主要在header上添加一个认证实例信息,如:DiscoveryIdentity-Name 
  

    >GZIPContentEncodingFilter.handle //过滤链,header中content-encoding添加gzip。如果可以压缩则进行gzip压缩。