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

本文涉及的产品
应用型负载均衡 ALB,每月750个小时 15LCU
网络型负载均衡 NLB,每月750个小时 15LCU
传统型负载均衡 CLB,每月750个小时 15LCU
简介: Spring Cloud升级之路 - Hoxton - 1.背景介绍与要实现的功能(上)
本系列示例与胶水代码地址: https://github.com/HashZhang/spring-cloud-scaffold

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


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

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

  • 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 Cloud Netflix体系为新的组件。


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


1. 微服务

以前的体系:

  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. 网关

以前的体系:

  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>
相关实践学习
SLB负载均衡实践
本场景通过使用阿里云负载均衡 SLB 以及对负载均衡 SLB 后端服务器 ECS 的权重进行修改,快速解决服务器响应速度慢的问题
负载均衡入门与产品使用指南
负载均衡(Server Load Balancer)是对多台云服务器进行流量分发的负载均衡服务,可以通过流量分发扩展应用系统对外的服务能力,通过消除单点故障提升应用系统的可用性。 本课程主要介绍负载均衡的相关技术以及阿里云负载均衡产品的使用方法。
相关文章
|
1月前
|
XML 安全 Java
|
2月前
|
Java 开发者 微服务
手写模拟Spring Boot自动配置功能
【11月更文挑战第19天】随着微服务架构的兴起,Spring Boot作为一种快速开发框架,因其简化了Spring应用的初始搭建和开发过程,受到了广大开发者的青睐。自动配置作为Spring Boot的核心特性之一,大大减少了手动配置的工作量,提高了开发效率。
70 0
|
3月前
|
Java API 数据库
构建RESTful API已经成为现代Web开发的标准做法之一。Spring Boot框架因其简洁的配置、快速的启动特性及丰富的功能集而备受开发者青睐。
【10月更文挑战第11天】本文介绍如何使用Spring Boot构建在线图书管理系统的RESTful API。通过创建Spring Boot项目,定义`Book`实体类、`BookRepository`接口和`BookService`服务类,最后实现`BookController`控制器来处理HTTP请求,展示了从基础环境搭建到API测试的完整过程。
65 4
|
3月前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 实现动态路由和菜单功能,快速搭建前后端分离的应用框架
本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 实现动态路由和菜单功能,快速搭建前后端分离的应用框架。首先,确保开发环境已安装必要的工具,然后创建并配置 Spring Boot 项目,包括添加依赖和配置 Spring Security。接着,创建后端 API 和前端项目,配置动态路由和菜单。最后,运行项目并分享实践心得,包括版本兼容性、安全性、性能调优等方面。
208 1
|
3月前
|
Java API 数据库
Spring Boot框架因其简洁的配置、快速的启动特性及丰富的功能集而备受开发者青睐
本文通过在线图书管理系统案例,详细介绍如何使用Spring Boot构建RESTful API。从项目基础环境搭建、实体类与数据访问层定义,到业务逻辑实现和控制器编写,逐步展示了Spring Boot的简洁配置和强大功能。最后,通过Postman测试API,并介绍了如何添加安全性和异常处理,确保API的稳定性和安全性。
67 0
|
17天前
|
设计模式 XML Java
【23种设计模式·全精解析 | 自定义Spring框架篇】Spring核心源码分析+自定义Spring的IOC功能,依赖注入功能
本文详细介绍了Spring框架的核心功能,并通过手写自定义Spring框架的方式,深入理解了Spring的IOC(控制反转)和DI(依赖注入)功能,并且学会实际运用设计模式到真实开发中。
【23种设计模式·全精解析 | 自定义Spring框架篇】Spring核心源码分析+自定义Spring的IOC功能,依赖注入功能
|
2月前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个具有动态路由和菜单功能的前后端分离应用。
本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个具有动态路由和菜单功能的前后端分离应用。首先,创建并配置 Spring Boot 项目,实现后端 API;然后,使用 Ant Design Pro Vue 创建前端项目,配置动态路由和菜单。通过具体案例,展示了如何快速搭建高效、易维护的项目框架。
138 62
|
1月前
|
XML Java 数据格式
Spring Core核心类库的功能与应用实践分析
【12月更文挑战第1天】大家好,今天我们来聊聊Spring Core这个强大的核心类库。Spring Core作为Spring框架的基础,提供了控制反转(IOC)和依赖注入(DI)等核心功能,以及企业级功能,如JNDI和定时任务等。通过本文,我们将从概述、功能点、背景、业务点、底层原理等多个方面深入剖析Spring Core,并通过多个Java示例展示其应用实践,同时指出对应实践的优缺点。
57 14
|
1月前
|
消息中间件 监控 Java
如何将Spring Boot + RabbitMQ应用程序部署到Pivotal Cloud Foundry (PCF)
如何将Spring Boot + RabbitMQ应用程序部署到Pivotal Cloud Foundry (PCF)
38 6
|
1月前
|
Java 关系型数据库 MySQL
如何将Spring Boot + MySQL应用程序部署到Pivotal Cloud Foundry (PCF)
如何将Spring Boot + MySQL应用程序部署到Pivotal Cloud Foundry (PCF)
62 5