springcloud中gateway存在的意义

SpringCloudGateway和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),漏桶算法的描述如下:
【springcloud中gateway存在的意义】一个固定容量的漏桶,按照常量固定速率流出水滴;
如果桶是空的,则不需流出水滴;
可以以任意速率流入水滴到漏桶;
如果流入水滴超出了桶的容量,则流入的水滴溢出了(被丢弃),而漏桶容量是不变的 。
实践
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 脚本实现基于令牌桶算法限流
这个要理解为什么做网关 。简单扼要来讲,就是为了处理每个服务都要做的事情 。你可以认为是切面变成了服务 。
路由,协议转换,鉴权认证,熔断,限流 。这些逻辑和你实际的业务代码没太大关系,但是每个业务服务都要搞一个,显得很累赘重复 。那怎么办呢?
两种解决思路 。
一,使用gateway服务,所有的服务均接入和调用这个gateway,由gateway把这些通用问题处理了,再去请求实际的业务逻辑 。gateway是关键节点,瓶颈节点 。spring cloud gateway也是这样 。它连接了系统的所有方方面面,是个大管家 。除了spring cloud gateway,其他的代表还有netty,kong,zuul等

springcloud中gateway存在的意义


图侵删

二,集成到本地,可以用sidecar,类似一个代理服务器 。sidecar就是那种有拖斗的三轮摩托车,旁边的那个人辅助给你观察 。下面是sidecar的架构 。
springcloud中gateway存在的意义


图侵删
啊不对,放错了 。应该是下面这个 。
springcloud中gateway存在的意义


图侵删
其实万变不离其宗 。首先,你确认有一些逻辑是通用的(鉴权,限流,路由),再是你提取了出来(变成了AOP切面逻辑),然后你把他写成一个单独的服务给这个服务用(sidecar),最后,你把这个服务给所有服务用(gateway) 。
浅显的理解就是这样 。

    推荐阅读