Spring Cloud升级之路 - Hoxton - 1.背景介绍与要实现的功能

本系列示例与胶水代码地址: https://github.com/HashZhang/spring-cloud-scaffoldreact

Spring Cloud仍是比较活跃的,更新一直很快。我通常考虑最新版本SR2发布以后,再考虑升级(通常SR1还有SR2会有一些新老框架的兼容性升级)。并且因为须要咱们线上稳定,结合咱们的发布周期来看,跳一个大版本升级是一个更好的选择(也就是一年作一次大版本升级)。例如咱们以前的升级路线就是:Brixton -> Daltson -> Finchley -> 当前的Hoxtongit

作了这么屡次升级,感受能够出这个系列,来分享咱们项目使用Spring cloud框架实现的框架功能,在升级中遇到的坑,以及如何升级等等。每一个版本都会有实例代码,并在上一版本实现的功能基础上,实现更多更实用的功能。全部示例代码都在开头提到的项目中,每一个版本系列的最后,还会附上功能测试流程。github

在Hoxton版本Release的同时,Spring Cloud也宣布,其中的这些项目,已经进入维护模式(再也不开发新功能),用户最好作以下的替换:web

  • Spring Cloud Netflix Ribbon -> Spring Cloud Load Balancer
  • Spring Cloud NetFlix Zuul -> Spring Cloud Gateway
  • Spring Cloud Hystrix -> Spring Cloud Circuit Breaker + Resilience4J
  • Spring Cloud Netflix Turbine -> Micrometer + Promethus
  • Spring Cloud Netflix Archaius -> Spring Cloud Config Server

能够看出,Spring Cloud netflix中的zuul, ribbon, hystrix都基本上算是废了,咱们也能够抛弃掉Sprnig Cloud Netflix了。还有一个体系也在官方中,就是Spring Cloud Alibaba,可是经过Spring Cloud netflix这件事,我我的感受这种依赖性质的胶水项目,最好仍是咱们架构组本身维护,这块是比较容易有坑的,本身维护本身用更新起来更高效,并且不会有粘合的项目都不更新了替换起来要人命的代价。算法

Spring Cloud Hoxton,至少对于官方文档来讲,是一个里程碑式的变化。官方文档终于将全部项目的文档分开了,而且作了比较多的整理,能够看出,这个Hoxton必定是有人下定决心要作一个变革了。而且,Spring Cloud在这个版本引入了更多的虚拟化,云原生依赖,例如Spring-Cloud-kubernetes,确实,有些服务发现,调用策略什么的,Spring Cloud和k8s体系重复了,这个依赖可使咱们灵活地切换这些功能到底交给谁来作,期待这个项目的完善成熟。spring

这篇文章,会主要列出升级步骤与详细说明,以及对应的源代码,和实现的功能。以及如何替换Spring Cloud Netflix体系为新的组件。apache

原有的功能以及以前的实现

1. 微服务

之前的体系:api

  1. 注册中心:Eureka
  2. 客户端封装:OpenFeign
  3. 客户端负载均衡:Ribbon
  4. 断路器与隔离: Hystrix

实现的功能:缓存

  1. 全部集群公用同一个公共Eureka集群,集群之间不互相调用,经过实例的metamap中的zone配置,来区分不一样集群的实例。以前经过Ribbon的配置ServerListFilter实现,使用com.netflix.loadbalancer.ZoneAffinityServerListFilter做为ServerListFilter,参考:Spring cloud实现FeignClient指定Zone调用
  2. 微服务之间调用,有重试,只对GET请求进行重试,链接超时,读取超时还有 4xx 和 5xx 的状态码都会重试。这个以前是经过加入spring-retry重试经过ribbon配置实现的。参考:Spring Cloud Finchley OpenFeign的重试配置相关的坑
  3. 微服务调用有线程隔离,例如微服务1调用微服务2和微服务3,调用微服务2的线程和微服务3的线程不同。以前是经过Hystrix配置实现hystrix.threadpool.default.coreSize=50
  4. 实现了实例级别的熔断,而不是微服务级别的。当调用微服务的两个实例的时候,当一个实例一直异常,则将这个实例断路器打开一段时间,而不是整个微服务都不能工做。以前经过Ribbon的配置LoadBalancerRule实现,使用com.netflix.loadbalancer.AvailabilityFilteringRule做为LoadBalancerRule。参考:Ribbon的AvailabilityFilteringRule的坑

2. 网关

之前的体系:tomcat

  1. API网关:Zuul

实现的功能:

  1. 重试,只对GET请求进行重试,链接超时,读取超时还有 4xx 和 5xx 的状态码都会重试。这个以前是经过加入spring-retry重试经过ribbon配置实现的。
  2. 微服务调用有线程隔离,例如微服务1调用微服务2和微服务3,调用微服务2的线程和微服务3的线程不同。以前是经过Hystrix配置实现hystrix.threadpool.default.coreSize=50
  3. 实现了实例级别的熔断,而不是微服务级别的。当调用微服务的两个实例的时候,当一个实例一直异常,则将这个实例断路器打开一段时间,而不是整个微服务都不能工做。以前经过Ribbon的配置LoadBalancerRule实现,使用com.netflix.loadbalancer.AvailabilityFilteringRule做为LoadBalancerRule。参考:Ribbon的AvailabilityFilteringRule的坑
  4. 特定接口 request body 解密与特定接口 response body 的加密。

3. Eureka-Server

实现的功能:

  1. 实例的快速上线下线,参考:Eureka 服务实例实现快速下线快速感知快速刷新配置解析

如今要实现的功能

1. 微服务

  1. 微服务之间调用依然基于利用 open-feign 的方式,有重试,仅对GET请求而且状态码为4xx和5xx进行重试(对4xx重试是由于滚动升级的时候,老的实例没有新的 api,重试能够将请求发到新的实例上)
  2. 某个微服务调用其余的微服务 A 和微服务 B, 调用 A 和调用 B 的线程池不同。而且调用不一样实例的线程池也不同。也就是实例级别的线程隔离
  3. 实现实例级别的熔断。
  4. 使用 zone 隔离,不一样 zone 之间不能互相调用
  5. 负载均衡的轮询算法,须要请求与请求之间隔离,不能共用同一个 position 致使某个请求失败以后的重试仍是原来失败的实例

2. 网关

  1. 转发请求,有重试,仅对GET请求而且状态码为4xx和5xx进行重试
  2. 不一样微服务的不一样实例线程隔离
  3. 实现实例级别的熔断。
  4. 使用 zone 隔离,仅转发请求到同 zone 的实例
  5. 负载均衡的轮询算法,须要请求与请求之间隔离,不能共用同一个 position 致使某个请求失败以后的重试仍是原来失败的实例

3. Eureka

  1. 实现服务实例快速上下线

新的pom依赖

1. 微服务

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.7.RELEASE</version>
    </parent>

    <properties>
        <disruptor.version>3.4.2</disruptor.version>
        <resilience4j-spring-cloud2.version>1.1.0</resilience4j-spring-cloud2.version>
    </properties>

    <dependencies>
        <!--内部缓存框架统一采用caffeine-->
        <!--这样Spring cloud loadbalancer用的本地实例缓存也是基于Caffeine-->
        <dependency>
            <groupId>com.github.ben-manes.caffeine</groupId>
            <artifactId>caffeine</artifactId>
        </dependency>

        <!--日志须要用log4j2-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-log4j2</artifactId>
        </dependency>

        <!--lombok简化代码-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

        <!--注册到eureka-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

        <!--spring cloud rpc相关-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <!--调用路径记录-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-sleuth</artifactId>
        </dependency>
        <!--暴露actuator相关端口-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!--暴露http接口, servlet框架采用nio的undertow,注意直接内存使用,减小GC-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-tomcat</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-undertow</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
        </dependency>
        <dependency>
            <groupId>io.github.resilience4j</groupId>
            <artifactId>resilience4j-spring-cloud2</artifactId>
            <version>${resilience4j-spring-cloud2.version}</version>
        </dependency>
        <!--log4j2异步日志须要的依赖,全部项目都必须用log4j2和异步日志配置-->
        <dependency>
            <groupId>com.lmax</groupId>
            <artifactId>disruptor</artifactId>
            <version>${disruptor.version}</version>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Hoxton.SR4</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.6.1</version>
                <configuration>
                    <!--最好用JDK 12版本及以上编译,11.0.7对于spring-cloud-gateway有时候编译会有bug-->
                    <!--虽然官网说已解决,可是11.0.7仍是偶尔会出现-->
                    <source>11</source>
                    <target>11</target>
                </configuration>
            </plugin>
        </plugins>
    </build>

2. 网关

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.7.RELEASE</version>
    </parent>

    <properties>
        <disruptor.version>3.4.2</disruptor.version>
        <resilience4j-spring-cloud2.version>1.1.0</resilience4j-spring-cloud2.version>
    </properties>

    <dependencies>
        <!--内部缓存框架统一采用caffeine-->
        <!--这样Spring cloud loadbalancer用的本地实例缓存也是基于Caffeine-->
        <dependency>
            <groupId>com.github.ben-manes.caffeine</groupId>
            <artifactId>caffeine</artifactId>
        </dependency>
        <!--日志须要用log4j2-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-log4j2</artifactId>
        </dependency>
        <!--lombok简化代码-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        <!--调用路径记录-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-sleuth</artifactId>
        </dependency>
        <!--暴露actuator相关端口-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>io.github.resilience4j</groupId>
            <artifactId>resilience4j-spring-cloud2</artifactId>
            <version>${resilience4j-spring-cloud2.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-circuitbreaker-reactor-resilience4j</artifactId>
        </dependency>
        <!--log4j2异步日志须要的依赖,全部项目都必须用log4j2和异步日志配置-->
        <dependency>
            <groupId>com.lmax</groupId>
            <artifactId>disruptor</artifactId>
            <version>${disruptor.version}</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.6.1</version>
                <configuration>
                    <!--最好用JDK 12版本及以上编译,11.0.7对于spring-cloud-gateway有时候编译会有bug-->
                    <!--虽然官网说已解决,可是11.0.7仍是偶尔会出现-->
                    <source>11</source>
                    <target>11</target>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Hoxton.SR4</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

3. Eureka-Server

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.7.RELEASE</version>
    </parent>

    <properties>
        <disruptor.version>3.4.2</disruptor.version>
    </properties>

    <dependencies>
        <!--内部缓存框架统一采用caffeine-->
        <!--这样Spring cloud loadbalancer用的本地实例缓存也是基于Caffeine-->
        <dependency>
            <groupId>com.github.ben-manes.caffeine</groupId>
            <artifactId>caffeine</artifactId>
        </dependency>

        <!--日志须要用log4j2-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-log4j2</artifactId>
        </dependency>

        <!--lombok简化代码-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
        <!--调用路径记录-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-sleuth</artifactId>
        </dependency>
        <!--暴露actuator相关端口-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!--暴露http接口, servlet框架采用nio的undertow,注意直接内存使用,减小GC-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-tomcat</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-undertow</artifactId>
        </dependency>
        <!--log4j2异步日志须要的依赖,全部项目都必须用log4j2和异步日志配置-->
        <dependency>
            <groupId>com.lmax</groupId>
            <artifactId>disruptor</artifactId>
            <version>${disruptor.version}</version>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Hoxton.SR4</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.6.1</version>
                <configuration>
                    <!--最好用JDK 12版本及以上编译,11.0.7对于spring-cloud-gateway有时候编译会有bug-->
                    <!--虽然官网说已解决,可是11.0.7仍是偶尔会出现-->
                    <source>11</source>
                    <target>11</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
相关文章
相关标签/搜索