微服务化框架 - Spring Cloud介绍

简介: Spring Cloud 版本众多,组件也在不断扩充中,是一个非常强大的微服务框架,不过也不是万能的,任何框架都不是完美的,需要适当的评估是否适合自己。

1. 微服务简介

如今越来越多的公司使用微服务架构来开发维护自己的业务,微服务技术早已证实它的价值。那什么是微服务?微服务最初是由 Martin Fowler 2014 年发表的论文《MicroServices》 中提出的名词,它一经提出就成为了技术圈的热门话题。如今我们在谈论微服务时常认为是一个庞大且复杂的概念集合,它既是一种架构模式,也是实现这种架构模式时所使用的技术方案的集合,包括服务拆分、数据管理、通讯模式、外部API、服务发现、安全、测试、可靠性、部署模式、可观测性等等。

与常见的单体架构相比,微服务架构有诸多优势,罗列了以下几方面:

不同点

微服务架构

单体架构

团队规模

微服务架构可以将传统模式下的单个应用拆分为多个独立的服务,每个微服务都可以单独开发、部署和维护。每个服务从设计、开发到维护所需的团队规模小,团队管理成本小。

单体架构的应用程序通常需要一个大型团队,围绕一个庞大的应用程序工作,团队管理的成本大。

数据存储方式

不同的微服务可以使用不同的数据存储方式,例如有的用 Redis,有的使用 MySQL。

单一架构的所有模块共享同一个公共数据库,存储方式相对单一。

部署方式

微服务架构中每个服务都可以独立部署,也可以独立于其他服务进行扩展。如果部署得当,基于微服务的架构可以帮助企业提高应用程序的部署效率。

采用单体架构的应用程序的每一次功能更改或 bug修复都必须对整个应用程序重新进行部署。

开发模式

在采用微服务架构的应用程序中,不同模块可以使用不同的技术或语言进行开发,开发模式更加灵活。

在采用单体架构的应用程序中,所有模块使用的技术和语言必须相同,开发模式受限。

故障隔离

在微服务架构中,故障被隔离在单个服务中,避免系统的整体崩溃。

在单体架构中,当一个组件出现故障时,故障很可能会在进程中蔓延,导致系统全局不可用。

项目结构

微服务架构将单个应用程序拆分为多个独立的小型服务,每个服务都可以独立的开发、部署和维护,每个服务都能完成一项特定的业务需求。

单体架构的应用程序,所有的业务逻辑都集中在同一个工程中。

2. Spring Cloud

实现微服务架构有许多方式,本文主要针对Spring Cloud 做了调研。Spring Cloud 中包含了 spring-cloud-configspring-cloud-bus 等近 20 个子项目,提供了服务治理、服务网关、智能路由、负载均衡、断路器、监控跟踪、分布式消息队列、配置管理等领域的解决方案。

Spring Cloud 本身并不是一个拿来即可用的框架,它是一套微服务规范,这套规范有两代实现用的比较广泛。

  •    第一代实现: Spring Cloud Netflix,

  •    第二代实现: Spring Cloud Alibaba。

   下面来介绍以下Spring Cloud一些常用的组件。

3. Eureka: Spring Cloud服务注册与发现组件

Eureka 采用 CSClient/Server,客户端/服务器) 架构,它包括以下两大组件:

Eureka ServerEureka服务注册中心,主要用于提供服务注册功能。当微服务启动时,会将自己的服务注册到 Eureka ServerEureka Server 维护了一个可用服务列表,存储了所有注册到 Eureka Server 的可用服务的信息,这些可用服务可以在 Eureka Server 的管理界面中直观看到。

Eureka ClientEureka 客户端,通常指的是微服务系统中各个微服务,主要用于和 Eureka Server 进行交互。在微服务应用启动后,Eureka Client 会向 Eureka Server 发送心跳(默认周期为 30 秒)。若 Eureka Server 在多个心跳周期内没有接收到某个 Eureka Client 的心跳,Eureka Server 将它从可用服务列表中移除(默认 90 秒)。

Eureka 实现服务注册与发现的流程如下:

  1.    搭建一个 Eureka Server 作为服务注册中心;

  2.    服务提供者 Eureka Client 启动时,会把当前服务器的信息以服务名(spring.application.name)的方式注册到服务注册中心;

  3.    服务消费者 Eureka Client 启动时,也会向服务注册中心注册;

  4.    服务消费者还会获取一份可用服务列表,该列表中包含了所有注册到服务注册中心的服务信息(包括服务提供者和自身的信息);

  5.    在获得了可用服务列表后,服务消费者通过 HTTP 或消息中间件远程调用服务提供者提供的服务。 

实现一个Eureka Server配置如下:

# 服务注册中心 (单节点)
server:
  port: 7001
eureka:
  instance:
    hostname: eureka7001.com
  client:
    fetch-registry: false # 表示是否从Eureka Server获取注册信息,默认为true.因为这是一个单点的Eureka Server,不需要同步其他的Eureka Server节点的数据,这里设置为false
    register-with-eureka: false # 表示是否将自己注册到Eureka Server,默认为true.由于当前应用就是Eureka Server,故而设置为false.
    service-url:
      # 设置与Eureka Server的地址,查询服务和注册服务都需要依赖这个地址.默认是http://localhost:8761/eureka/;多个地址可使用','风格.
      #defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
      defaultZone: http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/ #集群版 将当前的 Eureka Server 注册到 7001 和 7003 上,形成一组互相注册的 Eureka Server 集群

同时在Spring Boot 启动类上添加注解@EnableEurekaServer,就可以成为一个单节点Eureka Server,如果要成为一个集群,只需要将自身注册到其他Eureka Server中即可。

实现一个服务提供者配置如下:

server:
  port: 8002

spring:
  application:
    name: eureka-producer

eureka:
  client:
    service-url:
      #defaultZone: http://localhost:7001/eureka # 指定服务注册中心
      defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/  #将服务注册到 Eureka Server 集群

实现一个服务消费者配置如下:

server:
  port: 9001

spring:
  application:
    name: eureka-consumer

eureka:
  client:
    service-url:
      register-with-eureka: false #本微服务为服务消费者,不需要将自己注册到服务注册中心
      fetch-registry: true  #本微服务为服务消费者,需要到服务注册中心搜索服务
      #defaultZone: http://localhost:7001/eureka
      defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/  #将服务注册到 Eureka Server 集群

同时在Spring Boot 启动类上添加注解@EnableDiscoveryClient,就可以成为一个服务提供者或提供消费者。

下图是启动了3台Eureka Server,1个服务提供者,一个服务消费者的视图,DS REplicas表示Eureka Server集群中另外两台机器,而Application是注册在这个集群上的具体应用。

4. Ribbon: Spring Cloud负载均衡与服务调用组件

Ribbon 是一个基于 HTTP 和 TCP 的客户端负载均衡器,当我们将 Ribbon 和 Eureka 一起使用时,Ribbon 会从 Eureka Server(服务注册中心)中获取服务端列表,然后通过负载均衡策略将请求分摊给多个服务提供者,从而达到负载均衡的目的。

5. OpenFeign: Spring Cloud声明式服务调用组件

Feign Ribbon 进行了集成,利用 Ribbon 维护了一份可用服务清单,并通过 Ribbon 实现了客户端的负载均衡。Feign 是一种声明式服务调用组件,它在 RestTemplate 的基础上做了进一步的封装。通过 Feign,我们可以像调用本地方法一样来调用远程服务,而完全感觉不到这是在进行远程调用。而OpenFeign Spring Cloud Feign 的二次封装,它具有 Feign 的所有功能,并在 Feign 的基础上增加了对 Spring MVC 注解的支持,例如 @RequestMapping@GetMapping @PostMapping 等。

利用OpenFeign 实现远程服务调用只需要申明@FeignClient,代码如下:

//添加为容器内的一个组件
@Component
// 服务提供者提供的服务名称,即 eureka-producer
//@FeignClient(value = "EUREKA-PRODUCER")
@FeignClient(value = "EUREKA-PRODUCER")
public interface FeignService {
    @RequestMapping(value = "/sayHello", method = RequestMethod.GET)
    String sayHello(@RequestParam String param);
}

在调用的时候注入FeignService bean即可:

@RestController
public class TestController {
    @Resource
    private FeignService feignService;

    @RequestMapping("sayHello")
    public String sayHello(@RequestParam String name) {
        return feignService.sayHello(name);
    }
}

6. Hystrix: Spring Cloud服务熔断与降级组件

Hystrix 是一款优秀的服务容错与保护组件,在微服务系统中,Hystrix 能够帮助我们实现以下目标:

  •    保护线程资源:防止单个服务的故障耗尽系统中的所有线程资源。

  •    快速失败机制:当某个服务发生了故障,不让服务调用方一直等待,而是直接返回请求失败。

  •    提供降级(FallBack)方案:在请求失败后,提供一个设计好的降级方案,通常是一个兜底方法,当请求失败后即调用该方法。

  •    防止故障扩散:使用熔断机制,防止故障扩散到其他服务。

  •    监控功能:提供熔断器故障监控组件 Hystrix Dashboard,随时监控熔断器的状态。

   概括的讲,Hystrix主要提供两种功能,一个服务降级,一个服务熔断。

6.1 服务降级

当程序运行异常、服务超时线程池资源耗尽时,Hystrix可以提供一种能力,让服务快速返回一个降级逻辑结果,使这个服务不堵塞其他正常服务,保障主题业务不受影响,从而减少影响面。

可以配置Hystrix超时时间:

feign:
#  client:
#    config:
#      default:
#        # 指的是建立连接所用的时间,适用于网络状态正常的情况下,两端连接所用的时间,默认10s
#        ConnectTimeOut: 5000
#        # 指的是建立连接后从服务器读取可用资源所用的时间,默认60s
#        ReadTimeOut: 5000
  hystrix:
    enabled: true

######################配置请求超时时间##########################
hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 3000

通过@HystrixCommand添加方法专属的回退方法:

    @RequestMapping("hystrixClientTimeout")
    @HystrixCommand(fallbackMethod = "timeoutHandler") //为该请求指定专属的回退方法
    public String hystrixClientTimeout(Integer second) {
        return feignService.hystrixClientTimeout(second);
    }
    
    // hystrixClientTimeout方法的 专用 fallback 方法
    public String timeoutHandler(Integer second) {
        return "服务端系统繁忙,请稍后再试!(客户端 timeout 专属的回退方法触发)";
    }

也可以通过@DefaultProperties添加全局回退方法:

@RestController
@DefaultProperties(defaultFallback = "globalTimeoutHandler")
public class TestController {
    /**
     * 全局的 fallback 方法,
     * 回退方法必须和 hystrix 的执行方法在相同类中
     */
    public String globalTimeoutHandler() {
        return "服务端系统繁忙,请稍后再试!(客户端 timeout 全局回退方法触发)";
    }
}

6.2 服务熔断

熔断机制是为了应对雪崩效应而出现的一种微服务链路保护机制。当微服务系统中的某个微服务不可用或响应时间太长时,为了保护系统的整体可用性,熔断器会暂时切断请求对该服务的调用,并快速返回一个友好的错误响应。这种熔断状态不是永久的,在经历了一定的时间后,熔断器会再次检测该微服务是否恢复正常,若服务恢复正常则恢复其调用链路。

在熔断机制中涉及了三种熔断状态:

  •    熔断关闭状态(Closed):当务访问正常时,熔断器处于关闭状态,服务调用方可以正常地对服务进行调用。

  •    熔断开启状态(Open):默认情况下,在固定时间内接口调用出错比率达到一个阈值(例如 50%),熔断器会进入熔断开启状态。进入熔断状态后,后续对该服务的调用都会被切断,熔断器会执行本地的降级(FallBack)方法。

  •    半熔断状态(Half-Open): 在熔断开启一段时间之后,熔断器会进入半熔断状态。在半熔断状态下,熔断器会尝试恢复服务调用方对服务的调用,允许部分请求调用该服务,并监控其调用成功率。如果成功率达到预期,则说明服务已恢复正常,熔断器进入关闭状态;如果成功率仍旧很低,则重新进入熔断开启状态。

通过@HystrixCommand设置是否开启熔断器、统计时间窗、统计时间窗内请求次数、休眠时间窗口期、请求失败率阈值,同时可以指定熔断后执行方法。

    //Hystrix 熔断案例
    @Override
    @HystrixCommand(fallbackMethod = "deptCircuitBreaker_fallback", commandProperties = {
            //以下参数在 HystrixCommandProperties 类中有默认配置
            @HystrixProperty(name = "circuitBreaker.enabled", value = "true"), //是否开启熔断器
            @HystrixProperty(name = "metrics.rollingStats.timeInMilliseconds",value = "1000"), //统计时间窗
            @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "10"), //统计时间窗内请求次数
            @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "10000"), //休眠时间窗口期
            @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "60"), //在统计时间窗口期以内,请求失败率达到 60% 时进入熔断状态
    })
    public String circuitBreaker(int id) {
        if (id < 0) {
            //当传入的 id 为负数时,抛出异常,调用降级方法
            throw new RuntimeException("id 不能是负数!");
        }
        return Thread.currentThread().getName() + "\t" + "调用成功,流水号为:" + id;
    }
    //deptCircuitBreaker 的降级方法
    public String deptCircuitBreaker_fallback(int id) {
        return "id 不能是负数,请稍后重试!\t id:" + id;
    }

7. Gateway: Spring Cloud API网关组件

API 网关是一个搭建在客户端和微服务之间的服务,我们可以在 API 网关中处理一些非业务功能的逻辑,例如权限验证、监控、缓存、请求路由等。API 网关就像整个微服务系统的门面一样,是系统对外的唯一入口。有了它,客户端会先将请求发送到 API 网关,然后由 API 网关根据请求的标识信息将请求转发到微服务实例。

Spring Cloud GateWay 最主要的功能就是路由转发,而在定义转发规则时主要涉及了以下三个核心概念,如下表。

核心概念

描述

Route(路由)

网关最基本的模块。它由一个 ID、一个目标 URI、一组断言(Predicate)和一组过滤器(Filter)组成。

Predicate(断言)

路由转发的判断条件,我们可以通过 Predicate 对 HTTP 请求进行匹配,例如请求方式、请求路径、请求头、参数等,如果请求与断言匹配成功,则将请求转发到相应的服务。

Filter(过滤器)

过滤器,我们可以使用它对请求进行拦截和修改,还可以使用它对上文的响应进行再处理。

成为一个网关配置如下:

spring:
  application:
    name: cloud-gateway
  cloud:
    gateway: #网关路由配置
      discovery:
        locator:
          enabled: true #默认值为 true,即默认开启从注册中心动态创建路由的功能,利用微服务名进行路由
      routes:
        #将 micro-service-cloud-provider-dept-8001 提供的服务隐藏起来,不暴露给客户端,只给客户端暴露 API 网关的地址 9527
        - id: provider_hystrix_route   #路由 id,没有固定规则,但唯一,建议与服务名对应
          #uri: http://localhost:8004          #匹配后提供服务的路由地址
          uri: lb://EUREKA-PRODUCER          #匹配后提供服务的路由地址
          predicates:
            #以下是断言条件,必选全部符合条件
            - Path=/gateway/**               #断言,路径匹配 注意:Path 中 P 为大写
            - Method=GET #只能时 GET 请求时,才能访问
          filters:
            - AddResponseHeader=X-Request-Id,hello #过滤器工厂会在匹配的请求头加上一对请求头,名称为 X-Request-Id 值为 hello

其中Predicate表示一组断言,常见的配置如下:

断言

示例

说明

Path

- Path=/dept/list/**

当请求路径与 /dept/list/** 匹配时,该请求才能被转发

Before

- Before=2021-10-20T11:47:34.255+08:00[Asia/Shanghai]

在 2021 年 10 月 20 日 11 时 47 分 34.255 秒之前的请求,才会被转发

After

- After=2021-10-20T11:47:34.255+08:00[Asia/Shanghai]

在 2021 年 10 月 20 日 11 时 47 分 34.255 秒之后的请求,才会被转发

Between

- Between=2021-10-20T15:18:33.226+08:00[Asia/Shanghai],2021-10-20T15:23:33.226+08:00[Asia/Shanghai]

在 2021 年 10 月 20 日 15 时 18 分 33.226 秒 到 2021 年 10 月 20 日 15 时 23 分 33.226 秒之间的请求,才会被转发

Cookie

- Cookie=name,c.biancheng.net

携带 Cookie 且 Cookie 的内容为 name=c.biancheng.net 的请求,才会被转发

Header

- Header=X-Request-Id,\d+

请求头上携带属性 X-Request-Id 且属性值为整数的请求,才会被转发到 h

Method

- Method=GET

只有 GET 请求才会被转发

filters是过滤器,Spring Cloud Gateway 内置了多达 31 种 GatewayFilter,下表中列举了几种常用的网关过滤器及其使用示例。

路由过滤器

描述

参数

使用示例

AddRequestHeader

拦截传入的请求,并在请求上添加一个指定的请求头参数。

name:需要添加的请求头参数的 key;

value:需要添加的请求头参数的 value。

- AddRequestHeader=my-request-header,1024

AddRequestParameter

拦截传入的请求,并在请求上添加一个指定的请求参数。

name:需要添加的请求参数的 key;

value:需要添加的请求参数的 value。

- AddRequestParameter=my-request-param,c.biancheng.net

AddResponseHeader

拦截响应,并在响应上添加一个指定的响应头参数。

name:需要添加的响应头的 key;

value:需要添加的响应头的 value。

- AddResponseHeader=my-response-header,c.biancheng.net

PrefixPath

拦截传入的请求,并在请求路径增加一个指定的前缀。

prefix:需要增加的路径前缀。

- PrefixPath=/consumer

PreserveHostHeader

转发请求时,保持客户端的 Host 信息不变,然后将它传递到提供具体服务的微服务中。

- PreserveHostHeader

RemoveRequestHeader

移除请求头中指定的参数。

name:需要移除的请求头的 key。

- RemoveRequestHeader=my-request-header

RemoveResponseHeader

移除响应头中指定的参数。

name:需要移除的响应头。

- RemoveResponseHeader=my-response-header

RemoveRequestParameter

移除指定的请求参数。

name:需要移除的请求参数。

- RemoveRequestParameter=my-request-param

RequestSize

配置请求体的大小,当请求体过大时,将会返回 413 Payload Too Large。

maxSize:请求体的大小。

- name: RequestSize

  args:

    maxSize: 5000000

当然也可以自定义全局过滤器GlobalFilter:

@Component
@Slf4j
public class MyGlobalFilter implements GlobalFilter, Ordered {
    @Override
    public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        log.info("进入自定义的全局过滤器 MyGlobalFilter" + new Date());
        String path = exchange.getRequest().getPath().toString();
        if (path.startsWith("/gateway/timeout")) {
            log.info("path 不能以 /gateway/timeout 开头!");
            exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);
            return exchange.getResponse().setComplete();
        }
        return chain.filter(exchange);
    }
    @Override
    public int getOrder() {
        //过滤器的顺序,0 表示第一个
        return 0;
    }
}

8. Spring Cloud Alibaba

Spring Cloud Alibaba是对Spring Cloud的标准实现,Spring Cloud Alibaba 从19 年初开始提交代码就获得了业界的广泛关注,如今已经成为流行的微服务框架。

   Spring Cloud Alibaba主要包含以下几个模块:

  •    Sentinel:把流量作为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。

  •    Nacos:一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。

  •    RocketMQ:一款开源的分布式消息系统,基于高可用分布式集群技术,提供低延时的、高可靠的消息发布与订阅服务。

  •    Dubbo:Apache Dubbo 是一款高性能Java RPC 框架。

  •    Seata:阿里巴巴开源产品,一个易于使用的高性能微服务分布式事务解决方案。

  •    Alibaba Cloud OSS: 阿里云对象存储服务(Object Storage Service,简称OSS),是阿里云提供的海量、安全、低成本、高可靠的云存储服务。您可以在任何应用、任何时间、任何地点存储和访问任意类型的数据。

  •    Alibaba Cloud SchedulerX: 阿里中间件团队开发的一款分布式任务调度产品,提供秒级、精准、高可靠、高可用的定时(基于Cron 表达式)任务调度服务。

  •    Alibaba Cloud SMS: 覆盖全球的短信服务,友好、高效、智能的互联化通讯能力,帮助企业迅速搭建客户触达通道。

9. Nacos: Spring Cloud Alibaba服务注册与配置中心

Nacos 提供了一系列简单易用的特性,能够帮助我们快速地实现动态服务发现、服务配置等功能。

与 Eureka 类似,Nacos 也采用 CS(Client/Server,客户端/服务器)架构。Nacos Server由阿里巴巴团队使用 Java 语言编写并将 下载地址给用户,用户只需要直接下载并运行即可。Nacos Server可作为服务注册中心或配置中心。Nacos 客户端需要用户自己搭建。

9.1 注册中心

Nacos服务端配置如下:

# 应用名称
spring.application.name=nacos-discoveryprovider-sample

# Nacos帮助文档: https://nacos.io/zh-cn/docs/concepts.html
# Nacos认证信息
spring.cloud.nacos.discovery.username=nacos
spring.cloud.nacos.discovery.password=nacos
# Nacos 服务发现与注册配置,其中子属性 server-addr 指定 Nacos 服务器主机和端口
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
# 注册到 nacos 的指定 namespace,默认为 public
spring.cloud.nacos.discovery.namespace=public

# 应用服务 WEB 访问端口
server.port=8089

# Actuator Web 访问端口
management.server.port=8081
management.endpoints.jmx.exposure.include=*
management.endpoints.web.exposure.include=*
management.endpoint.health.show-details=always

Nacos消费端配置和服务端一致,区分应用名称、端口号即可。启动成功后,可以在Nacos Server中查看管理服务列表:

9.2 配置中心

使用Nacos配置中心配置如下:

# Nacos帮助文档: https://nacos.io/zh-cn/docs/concepts.html
# Nacos认证信息
spring.cloud.nacos.config.username=nacos
spring.cloud.nacos.config.password=nacos
spring.cloud.nacos.config.contextPath=/nacos
# 设置配置中心服务端地址
spring.cloud.nacos.config.server-addr=127.0.0.1:8848
# Nacos 配置中心的namespace。需要注意,如果使用 public 的 namcespace ,请不要填写这个值,直接留空即可
# spring.cloud.nacos.config.namespace=

启动成功后,可以在Nacos Server中查看管理配置列表:

10. Sentinel: Spring Cloud Alibaba高可用流量控制组件

Sentinel 是阿里巴巴开源的,面向分布式服务架构的高可用防护组件,主要以流量为切入点,从流量控制、流量整形、熔断降级、系统自适应保护、热点防护等多个维度来帮助开发者保障微服务的稳定性。从功能上来说,Sentinel Spring Cloud Netfilx Hystrix 类似,但 Sentinel 要比 Hystrix 更加强大,例如Sentinel 提供了流量控制功能、比 Hystrix 更加完善的实时监控功能等等。

同Nacos一样,Sentinel也有自己的控制台,可以在控制台操作流控规则、熔断规则等等。

Sentinel可实现流量控制和熔断降级,主要通过注解@SentinelResource实现,blockHandler实现流量控制方法,表示限流后执行的逻辑,fallback实现熔断降级方法,表示熔断后执行的方法。Sentinel熔断状态与Hystrix一致,也是熔断关闭状态、熔断开启状态、半熔断状态。另外Sentinel 提供了 3 种熔断策略:慢调用比例、异常比例、异常数,强于Hystrix。

			@SentinelResource(value = "/sentinel/timeout", fallback = "fallBackTime", blockHandler = "blockHandlerTestTime")
      @RequestMapping("/timeout")
      public String timeout(@RequestParam int second) {
          return feignService.timeout(second);
      }

      public String fallBackTime(int second) {
          return "熔断降级了:" + second;
      }

      public String blockHandlerTestTime(@RequestParam int second, BlockException exception) {
          return "您已被限流,请稍后重试! second:" + second;
      }

11. 写在最后

Spring Cloud 版本众多,组件也在不断扩充中,是一个非常强大的微服务框架,不过也不是万能的,首先带来的是微服务化后服务过多,治理成本变高的问题,同时对整个团队分布式系统开发的能力要求也会变高,再者Java语言的限制也是Spring Cloud的一大掣肘,任何框架都不是完美的,需要适当的评估是否适合自己。

作者介绍
目录