Gateway 入门教程 - 高级篇
大纲
Gateway 的流量控制
Gateway 的限流概述
在开发高并发系统时可以用三把利器来保护系统:缓存、降级和限流。缓存的目的是提升系统访问速度和增大系统处理的容量,是抗高并发流量的 “银弹”;而降级是当服务出现问题或者影响到核心流程时,需要暂时将其屏蔽掉,待高峰过去之后或者问题解决后再打开;而有些场景并不能用缓存和降级来解决,比如稀缺资源(秒杀、抢购)、写服务(如评论、下单)、频繁的复杂查询等,因此需要有一种手段来限制这些场景的并发 / 请求量,即限流。限流的目的是通过对并发访问 / 请求进行限速或者对一个时间窗口内的请求进行限速来保护系统,一旦达到限制速率则可以拒绝服务(定向到错误页或友好的展示页)、排队或等待(比如秒杀、评论、下单等场景)、降级(返回兜底数据或默认数据)。主流的中间件都会有单机限流框架,一般支持两种限流模式:控制速率和控制并发。Spring Cloud Zuul 通过第三方扩展 spring-cloud-zuul-ratelimit 也可以支持限流。Spring Cloud Gateway 是一个 API 网关中间件,网关是所有请求流量的入口;特别是像天猫双十一、双十二等高并发场景下,当流量迅速剧增,网关除了要保护自身之外,还要限流保护后端应用。常见的限流算法有漏桶和令牌桶,计数器也可以进行粗暴限流实现。对于限流算法,可以参考 Guava 中的 RateLimiter、Bucket4j、RateLimitJ 等项目的具体实现。下面将介绍如何基于 Bucket4j、Gateway 内置的限流过滤器工厂(RequestRateLimiterGatewayFilterFactory
)、CPU 使用率实现限流,点击下载完整的案例代码。
Gateway 入门教程 - 中级篇
大纲
前言
版本说明
在本文中,默认使用的 Spring Cloud 版本是 Finchley.RELEASE,对应的 Spring Boot 版本是 2.0.3,特别声明除外。
Gateway 基于服务发现的路由规则
Gateway 服务发现路由的概述
Spring Cloud 对 Zuul 进行封装处理之后,当通过 Zuul 访问后端微服务时,基于服务发现的默认路由规则是:http://zuul_host:zuul_port/微服务在Eureka上的ServiceId/**
。Spring Cloud Gateway 在设计的时候考虑了从 Zuul 迁移到 Gateway 的兼容性和迁移成本等,Gateway 基于服务发现的路由规则和 Zuul 的设计类似,但是也有很大差别。Spring Cloud Gateway 基于服务发现的路由规则,在不同注册中心下其差异如下:
- 如果把 Gateway 注册到 Consul 上,通过网关转发服务调用,服务名称默认小写,不需要做任何处理
- 如果把 Gateway 注册到 Zookeeper 上,通过网关转发服务调用,服务名称默认小写,不需要做任何处理
- 如果把 Gateway 注册到 Eureka 上,通过网关转发服务调用,访问网关的 URL 是
http://Gateway_HOST:Gateway_PORT/大写的ServiceId/**
,其中服务名称默认必须是大写,否则会抛 404 错误;如果服务名要用小写访问,可以在属性配置文件里面加spring.cloud.gateway.discovery.locator.lowerCaseServiceId=true
配置解决
特别注意
- 将 Gateway 注册到服务注册中心后,为了在外部可以通过服务名称让 Gateway 转发服务调用,需要在配置文件中设置
spring.cloud.gateway.discovery.locator.enabled
为true
,表示 Gateway 需要与服务发现组件进行结合使用。 - 配置之后就可以通过服务名称(
serviceId
)将请求转发到具体的服务实例。比如http://localhost:8080/cloud-payment-service/pay/list
,其中http://localhost:8080
是 Gateway 的访问地址,cloud-payment-service
是服务名称。
Gateway 入门教程 - 基础篇
大纲
Reactor 与 WebFlux 介绍
Reactor 是什么
为了应对高并发的服务器端开发,在 2009 年 的时候,微软提出了一个更优雅地实现异步编程的方式 - Reactive Programming,中文名是响应式编程或者叫反应式编程。随后,其它技术也迅速地跟上了脚步,像 ES6 通过 Promise 引入了类似的异步编程方式。Netflix 和 TypeSafe 公司也提供了 RxJava、Scala、Akka 技术,让 Java 平台也有了能够实现响应式编程的框架,现在比较熟知的 Hystrix 就是以 RxJava 为基础开发的。到了 2017 年,虽然已经有不少公司在实践响应式编程,但整体来说应用范围依旧不大,主要原因在于缺少简单易用的技术将响应式编程推广普及,诸如 MVC 框架、HTTP 客户端、数据库技术等整合。终于,在 2017 年 9 月 28 日,Spring 5 正式发布,而 Spring 5 其最大的意义就是将响应式编程技术的普及向前推进一大步。在背后支持 Spring 5 响应式编程的框架正是 Reactor,它是由 Pivotal 公司(开发 Spring 等技术的公司)开发的,实现了 Reactive Programming 思想,符合 Reactive Streams 规范(Reactive Streams 是由 Netflix、TypeSafe、Pivotal 等公司发起的)的一项技术。Reactive 与 Servlet 的技术栈对比图如下:
Consul 入门教程 - 基础篇(2018 年)
大纲
Consul 的介绍
Consul 是什么
作为集群系统的灵魂,服务治理框架一直都受架构师的青睐。随着微服务思想的普及,越来越多的服务治理框架如雨后春笋般冒了出来。除了 Eureka,HashiCorp 公司的 Consul 也让诸多架构师青睐有加。Consul 是一个分布式高可用的服务网格(Service Mesh)解决方案,提供包括服务发现、配置和分段功能在内的全功能控制平面。这些功能中的每一个都可以根据需要单独使用,也可以一起使用以构建完整的服务网格。简单来说,Consul 是一个分布式高可用的系统服务发现与配置工具,它跟 Eureka 的核心功能一样,但略有不同:
- Consul 使用 Go 语言编写,以 HTTP 方式对外提供服务
- Consul 支持多数据中心,这是它的一大特色
- Consul 提供了可视化的 Web 界面
- Consul 的一致性协议是 CP(Raft)
- Consul 除了服务发现之外,还有一些别的功能,例如配置功能
Config 入门教程 - 高级篇
大纲
大纲
前言
版本说明
在下面的的教程中,使用的 Spring Cloud 版本是 Finchley.RELEASE,对应的 Spring Boot 版本是 2.0.3,特别声明除外。
Config 高可用
对于线上的生产环境,通常对其都是有很高的要求,其中高可用是不可或缺的一部分,必须要保证服务是可用状态,才能保证系统更好地运行,这是业务稳定的保证。
Config 客户端高可用
对于客户端的高可用,这里的方案主要还是用 File 的形式,本质与 “客户端回退” 的思路大体一致。客户端高可用主要是解决当服务端不可用的情况下,客户端依然可以正常启动。从客户端的角度出发,不是增加配置中心的高可用性,而是降低客户端对配置中心的依赖程度,从而提高整个分布式架构的健壮性。客户端加载配置的高可用流程图如下,点击下载完整的案例代码。
Config 入门教程 - 中级篇
大纲
前言
版本说明
在下面的的教程中,使用的 Spring Cloud 版本是 Finchley.RELEASE,对应的 Spring Boot 版本是 2.0.3,特别声明除外。
Config 使用技巧
本地参数覆盖远程参数
在某些时候需要使用当前系统的环境变量或者是应用本身设置的参数而不是使用远程拉取的参数,此时 Config Client 可以使用如下配置:
官方 Bug 解决方案:
- https://github.com/spring-cloud/sprmg-cloud-config/issues/651
- https://github.com/spring-cloud/spring-cloud-config/issues/359
1 | spring: |
- overrideNone:当 allowOverride 为 true 时,overrideNone 设置为 true,代表外部配置的优先级更低,而且不能覆盖任何已存在的属性源,默认为 false
- allowOverride:标识 overrideSystemProperties 属性是否启用,默认为 true,设置为 false 表示禁止用户的个性化设置
- overrideSystemProperties:用来标识外部配置是否能够覆盖系统属性,默认为 true
Config 入门教程 - 基础篇
Zuul 入门教程 - 高级篇
大纲
前言
版本说明
在本文中,默认使用的 Spring Cloud 版本是 Finchley.RELEASE,对应的 Spring Boot 版本是 2.0.3,Zuul 版本是 1.x,特别声明除外。
Zuul 多层负载
痛点场景
在 Spring Cloud 微服务架构体系中,所有请求的前门的网关 Zuul 承担着请求转发的主要功能,对后端服务起着举足轻重的作用。当业务体量猛增之后,得益于 Spring Cloud 的横向扩展能力,往往加节点、加机器就可以使得系统支撑性获得大大提升,但是仅仅加服务而不加网关是会有性能瓶颈的,单一 Zuul 节点的处理能力十分有限。因此扩张节点往往是微服务连带 Zuul 一起扩张,一般会部署一个 Zuul 集群来横向扩展微服务应用,然后再在请求上层加一层软负载,通常是使用 Nginx 均分请求到 Zuul 集群(如下图)。此时若其中一台 Zuul 服务挂掉了,由于从 Nginx 到 Zuul 其实是没有什么关联性,如果 Zuul 服务宕掉,Nginx 还是会把请求导向到 Zuul 服务,导致从 Nginx 到这 Zuul 节点的请求会全部失效,在 Nginx 没有采取相关应对措施的情况下,这是十分严重的问题。
Zuul 入门教程 - 中级篇
大纲
前言
版本说明
在本文中,默认使用的 Spring Cloud 版本是 Finchley.RELEASE,对应的 Spring Boot 版本是 2.0.3,Zuul 版本是 1.x,特别声明除外。
Zuul Filter 链
工作原理
Zuul 的核心逻辑是由一系列紧密配合工作的 Filter 来实现的,它们能够在进行 HTTP 请求或者响应的时候执行相关操作。可以说,没有 Filter 责任链,就没有如今的 Zuul,更不可能构成功能丰富的” 网关 “,Zuul Filter 的主要特性有以下几点:
- Filter 的类型:Filter 的类型决定了此 Filter 在 Filter 链中的执行顺序,可能是路由动作发生前,可能是路由动作发生时,可能是路由动作发生后,也可能是路由过程发生异常时
- Filter 的执行顺序:同一种类型的 Filter 可以通过
filterOrder()
方法来设定执行顺序,一般会根据业务的执行顺序需求,来设定自定义 Filter 的执行顺序 - Filter 的执行条件:Filter 运行所需要的标准或条件
- Filter 的执行效果:符合某个 Filter 执行条件,产生的执行效果