spring cloud中gateway存在的意义是什么?:先让我们看这样一个场景吧,一个电商网站做了服务化,后端服务分别拆成了用户服务、商品服务、支付服务、物流服务(为
先让我们看这样一个场景吧,一个电商网站做了服务化,后端服务分别拆成了用户服务、商品服务、支付服务、物流服务(为了举例,做了简化,实际场景会远比这个复杂);前端有网页版和 APP,前端的所有操作都需要调用后端的各个服务。
在这个过程中,可能会有这样的问题:
问题1.前端应用需要知道后端每个服务的地址,或者必须接入服务中心;但是服务的地址和端口可能会动态变化。
每个服务的技术栈必须相同,遵守相同的接口规范,接口协议必须相同,否则对于前度极度不友好。
网页版和 APP 展示相同的内容时,可能粒度不同,要么服务端提供粗粒度和细粒度两种 API,要么只提供一组最细粒度的 API,前者增加了后端的开发量,后者可能会导致一次前端需要多次调用细粒度的 API,才能得到想要的数据。
不同的客户端设备展示的数据不同,比如网页版能展示的数据更详细一些,APP 展示的数据少,那么也会有“提供一个大而全的接口”还是“为不同的调用方提供不同接口”的问题。
日志、认证和鉴权、计费、监控等等功能,需要各个后端来完善,或者接入到对应的公共组件中(接入也是需要开发的),这就多多少少增加了后端服务的工作。
API Gateway 就是为了解决以上种种问题的;API Gateway 是系统的唯一入口,它屏蔽掉了系统的内部架构,为调用方定制了统一的 API。
单节点网关把后端各个服务的 API 聚合起来,提供统一且唯一规范的入口,这样使得内部的架构对于调用方透明,客户端和服务端的耦合度降低;各个后端服务之间,可以采用不同的实现方案,而 API Gateway 会屏蔽掉这些差异;
后端的每个服务也都是在不断迭代和升级的,API Gateway 可以将请求路由到不同的接口版本上,可以实现灰度发布;
API Gateway 可以进行服务编排,实现数据聚合,也就是调用方一次请求,API Gateway 调用多个服务拿到数据后返回;
API Gateway 知道所有服务实例的地址,可以对不同的服务采用不同的路由策略;
日志、认证和鉴权、计费、监控等等功能都可以在 API Gateway 上实现;
API Gateway 还可以对流量进行控制,通过熔断、降级、限流等方式,保护后端服务。
Java开发者都知道大名鼎鼎的Spring,可以这样说,目前市面上所需要的功能Spring全家桶(Spring、Spring Boot、Spring Cloud)都提供了完美的解决方案。
Spring Cloud它是基于Spring Boot的一款微服务开发框架,它提供了配置管理、服务发现、熔断器、路由、服务跟踪及治理等微服务开发一整套的解决方案。
微服务技术中的网关(Gateway)技术网关(Gateway)是任何微服务架构中最为重要的一部分,网关就好比是一个门卫,严格把关外来访客与内部微服务之间的沟通联系。其实,网关是微服务对外的唯一入口!外部发起的所有请求都是要经过网关的,由网关来决定不同的请求到不同的微服务程序去处理。
Spring Cloud中的网关不止一种,Spring Cloud中最早期的网关采用的是Zuul,后来改用了Spring Cloud Gateway。
1、Zuul不是Spring Cloud官方推出的
Zuul网关其实是Netflix开发的,它是阻塞式API,而且不支持长连接和Websocket,所以是有一定缺陷的。
2、Spring Cloud Gateway是用来替代Zuul网关的
Spring 5起就推出了自己的网关:Spring Cloud Gateway。它是基于Spring Boot开发的,性能上比Zuul要好,而且在配置及使用上都要比Zuul更方便。
总结Spring Cloud Gateway是用来替代Zuul网关的,是由Spring官方开发维护的,无论在性能还是操作上都优于Zuul。在新一代Spring Cloud项目中推荐使用。
3一、微服务和Spring Cloud介绍
微服务,关键其实不仅仅是微服务本身,而是系统要提供一套基础的架构,这种架构使得微服务可以独立的部署、运行、升级,不仅如此,这个系统架构还让微服务与微服务之间在结构上“松耦合”,而在功能上则表现为一个统一的整体。这种所谓的“统一的整体”表现出来的是统一风格的界面,统一的权限管理,统一的安全策略,统一的上线过程,统一的日志和审计方法,统一的调度方式,统一的访问入口等。微服务的目的是有效的拆分应用,实现敏捷开发和部署 。
Spring Cloud是一系列框架的有序集合。它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等,都可以用Spring Boot的开发风格做到一键启动和部署。Spring Cloud并没有重复制造轮子,它只是将各家公司开发的比较成熟、经得起实际考验的服务框架组合起来,通过Spring Boot风格进行再封装屏蔽掉了复杂的配置和实现原理,最终给开发者留出了一套简单易懂、易部署和易维护的分布式系统开发工具包。
二、API网关在微服务架构体系中作用采用API网关,实现一个API网关接管所有的入口流量,是系统的唯一入口,将所有用户的请求转发给后端的服务器,但网关做的不仅仅只是简单的转发,也会针对流量做一些扩展。从面向对象设计的角度看,它与外观模式类似。API网关封装了系统内部架构,为每个客户端提供一个定制的API。
比如鉴权、限流、权限、熔断、协议转换、错误码统一、缓存、日志、监控、告警等,这样将通用的逻辑抽出来,由网关统一去做,业务方也能够更专注于业务逻辑,提升迭代的效率。
通过引入API网关,客户端只需要与API网关交互,而不用与各个业务方的接口分别通讯,但多引入一个组件就多引入了一个潜在的故障点,因此要实现一个高性能、稳定的网关,也会涉及到很多点。
API网关方式的核心要点是,所有的客户端和消费端都通过统一的网关接入微服务,在网关层处理所有的非业务功能。通常,网关也是提供REST/HTTP的访问API。服务端通过API-GW注册和管理服务。
三、当前各种API网关技术方案对比使用一个组件时,尤其是这种比较流行的架构,组件肯定存在开源的,我们不必自己去从零开始去实现一个网关,自己开发一个网关的工作量是相当可观的,现在比较流行的开源 API:
Spring Cloud Gateway
Spring Cloud Gateway是一款非常实用的微服务网关,在Spring Cloud微服务架构体系中发挥非常大的作用。Spring Cloud Gateway 是 Spring Cloud 微服务平台的一个子项目,属于 Spring 开源社区,依赖名叫:spring-cloud-starter-gateway。
https://spring.io/projects/spring-cloud-gateway
Spring Cloud Gateway构建于 Spring 5+,基于 Spring Boot 2.x 响应式的、非阻塞式的 API。同时,它支持 websockets,和 Spring 框架紧密集成,开发体验相对来说十分不错。
Zuul
Zuul 是 Netflix 公司的开源项目,Spring Cloud 在 Netflix 项目中也已经集成了 Zuul,依赖名叫:spring-cloud-starter-netflix-zuul。
https://github.com/Netflix/zuul
Spring Cloud Gateway网关和Zuul网关对比
四、Spring Cloud Gateway核心要点网关提供API全托管服务,丰富的API管理功能,辅助企业管理大规模的API,以降低管理成本和安全风险,包括协议适配、协议转发、安全策略、防刷、流量、监控日志等贡呢。一般来说网关对外暴露的URL或者接口信息,我们统称为路由信息。如果研发过网关中间件或者使用过Zuul的人,会知道网关的核心是Filter以及Filter Chain(Filter责任链)。Sprig Cloud Gateway也具有路由和Filter的概念。
Spring Cloud Gateway主要特性:
基于Spring framework 5、Project Reactor和Spring Boot 2.0构建
能够在任意请求属性上匹配路由
predicates(谓词) 和 filters(过滤器)是特定于路由的
集成了Hystrix断路器
集成了Spring Cloud DiscoveryClient
易于编写谓词和过滤器
请求速率限制
路径重写
下面介绍一下Spring Cloud Gateway中几个重要的概念。
路由。路由是网关最基础的部分,路由信息有一个ID、一个目的URL、一组断言和一组Filter组成。如果断言路由为真,则说明请求的URL和配置匹配
断言。Java8中的断言函数。Spring Cloud Gateway中的断言函数输入类型是Spring5.0框架中的ServerWebExchange。Spring Cloud Gateway中的断言函数允许开发者去定义匹配来自于http request中的任何信息,比如请求头和参数等。
过滤器。一个标准的Spring webFilter。Spring cloud gateway中的filter分为两种类型的Filter,分别是Gateway Filter和Global Filter。过滤器Filter将会对请求和响应进行修改处理。
如上图所示,Spring Cloud Gateway发出请求。然后再由Gateway Handler Mapping中找到与请求相匹配的路由,将其发送到Gateway web handler。Handler再通过指定的过滤器链将请求发送到我们实际的服务执行业务逻辑,然后返回。
4网关网关,一夫当关万夫莫开。最重要的意义就是为软件系统提供安全保障了,人们往往把API鉴权放到网关上来做,因为这样处理简单高效,而且能够很好的保护后端应用。这样能够很好的控制网络请求,而不必将所有后端服务暴露在外部环境中从而有潜在的安全风险。
其次就是为前端提供了统一的API入口,相当于规范了API路径,这为前后端API对接提供了很大的便利。使得团队开发变得高效。所以说这个网关还是非常重要滴。
5这个要理解为什么做网关。简单扼要来讲,就是为了处理每个服务都要做的事情。你可以认为是切面变成了服务。
路由,协议转换,鉴权认证,熔断,限流。这些逻辑和你实际的业务代码没太大关系,但是每个业务服务都要搞一个,显得很累赘重复。那怎么办呢?
两种解决思路。
一,使用gateway服务,所有的服务均接入和调用这个gateway,由gateway把这些通用问题处理了,再去请求实际的业务逻辑。gateway是关键节点,瓶颈节点。spring cloud gateway也是这样。它连接了系统的所有方方面面,是个大管家。除了spring cloud gateway,其他的代表还有netty,kong,zuul等
图侵删
二,集成到本地,可以用sidecar,类似一个代理服务器。sidecar就是那种有拖斗的三轮摩托车,旁边的那个人辅助给你观察。下面是sidecar的架构。
图侵删
啊不对,放错了。应该是下面这个。
图侵删
其实万变不离其宗。首先,你确认有一些逻辑是通用的(鉴权,限流,路由),再是你提取了出来(变成了AOP切面逻辑),然后你把他写成一个单独的服务给这个服务用(sidecar),最后,你把这个服务给所有服务用(gateway)。
浅显的理解就是这样。
6SpringCloudGateway和SpringCloudZuul一样是微服务网关,不过Gateway是SpringCloud官方推出的,而Zuul是Netflix推出的。
看其他人的一些文章说是Gateway是用于取代Zuul的第二代网关,这个我在官方找不到资料说明。
主要术语
default-filters: 里面可以定义一些共同的filter,对所有路由都起作用
routes:具体的路由信息,是一个数组,每一个路由基本包含部分:
id:这个路由的唯一id,不定义的话为一个uuid
uri:http请求为lb://前缀 + 服务id;ws请求为lb:ws://前缀 + 服务id;表示将请求负载到哪一个服务上
predicates:表示这个路由的请求匹配规则,只有符合这个规则的请求才会走这个路由。为一个数组,每个规则为并且的关系。
filters:请求转发前的filter,为一个数组。
order:这个路由的执行order
网关请求
SpringCloudGateway限流原理与实践
缓存、降级和限流是开发高并发系统的三把利器。缓存的目的是提升系统访问速度和增大系统能处理的容量,可谓是抗高并发流量的银弹;降级是当服务出现问题或者影响到核心流程的性能则需要暂时屏蔽,待高峰或者问题解决后再打开;而有些场景并不能用缓存和降级来解决,比如稀缺资源、写服务、频繁的复杂查询,因此需有一种手段来限制这些场景的并发/请求量,即限流。
限流的目的是通过对并发访问/请求进行限速,或对一个时间窗口内的请求进行限速来保护系统。一旦达到限制速率则可以拒绝服务、排队或等待、降级。
一般开发高并发系统常见的限流有:限制总并发数、限制瞬时并发数、限制时间窗口内的平均速率、限制远程接口的调用速率、限制MQ的消费速率,或根据网络连接数、网络流量、CPU或内存负载等来限流。
本文主要就分布式限流方法,对Spring Cloud Gateway的限流原理进行分析。
分布式限流最关键的是要将限流服务做成原子化,常见的限流算法有:令牌桶、漏桶等,Spring Cloud Gateway使用Redis+Lua技术实现高并发和高性能的限流方案。
令牌桶算法
令牌桶算法是一个存放固定容量令牌的桶,按照固定速率往桶里添加令牌。令牌桶算法的描述如下:
假如用户配置的平均速率为r,则每隔1/r秒一个令牌被加入到桶中;
假设桶最多可以存发b个令牌。如果令牌到达时令牌桶已经满了,那么这个令牌会被丢弃;
当一个n个字节大小的数据包到达,将从桶中删除n个令牌,接着数据包被发送到网络上;
如果令牌桶中少于n个令牌,那么不会删除令牌,并且认为这个数据包在流量限制之外;
算法允许最长b个字节的突发,但从长期运行结果看,数据包的速率被限制成常量r。对于在流量限制外的数据包可以以不同的方式处理:
它们可以被丢弃;
它们可以排放在队列中以便当令牌桶中累积了足够多的令牌时再传输;
它们可以继续发送,但需要做特殊标记,网络过载的时候将这些特殊标记的包丢弃。
漏桶算法
漏桶作为计量工具(The Leaky Bucket Algorithm as a Meter)时,可以用于流量整形(Traffic Shaping)和流量控制(Traffic Policing),漏桶算法的描述如下:
一个固定容量的漏桶,按照常量固定速率流出水滴;
如果桶是空的,则不需流出水滴;
可以以任意速率流入水滴到漏桶;
如果流入水滴超出了桶的容量,则流入的水滴溢出了(被丢弃),而漏桶容量是不变的。
实践
SpringCloudGateway限流方案
Spring Cloud Gateway 默认实现 Redis限流,如果扩展只需要实现Ratelimter接口即可,同时也可以通过自定义KeyResolver来指定限流的Key,比如我们需要根据用户、IP、URI来做限流等等,通过exchange对象可以获取到请求信息,比如:
用户限流
@Bean
public KeyResolver ipKeyResolver() {
return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getHostName());
}
SpringCloudGateway默认提供的RedisRateLimter 的核心逻辑为判断是否取到令牌的实现,通过调用 meta-INF/scripts/request_rate_limiter.lua 脚本实现基于令牌桶算法限流