引入:通过Eureka, Nacos解决了服务注册, 服务发现的问题, 使⽤Spring Cloud LoadBalance解决了负载均衡的问题, 使⽤OpenFeign解决了远程调⽤的问题.
但是当前所有微服务的接⼝都是直接对外暴露的, 可以直接通过外部访问. 为了保证对外服务的安全性,服务端实现的微服务接⼝通常都带有⼀定的权限校验机制. 由于使⽤了微服务, 原本⼀个应⽤的的多个模块拆分成了多个应⽤, 我们不得不实现多次校验逻辑. 当这套逻辑需要修改时, 我们需要修改多个应⽤, 加重了开发⼈员的负担.
因此就出了一个解决方案 就是使用API网关
一、什么是API 网关
API⽹关(简称⽹关)也是⼀个服务, 通常是后端服务的唯⼀⼊⼝. 它的定义类似设计模式中的Facade模式(⻔⾯模式, 也称外观模式). 它就类似整个微服务架构的⻔⾯, 所有的外部客⼾端访问, 都需要经过它来进⾏调度和过滤.
二、网关的核心功能
权限控制: 作为微服务的⼊⼝, 对⽤⼾进⾏权限校验, 如果校验失败则进⾏拦截
动态路由: ⼀切请求先经过⽹关, 但⽹关不处理业务, ⽽是根据某种规则, 把请求转发到某个微服务
负载均衡: 当路由的⽬标服务有多个时, 还需要做负载均衡
限流: 请求流量过⾼时, 按照⽹关中配置微服务能够接受的流量进⾏放⾏, 避免服务压⼒过⼤.
三、gateway项目
①创建⽹关项⽬
②引入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!--基于nacos实现服务发现依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--负载均衡-->
<dependency> <groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
③编写启动类
④添加Gateway的路由配置
1、id : ⾃定义路由ID, 保持唯⼀
2、uri: ⽬标服务地址, ⽀持普通URI 及 lb://应⽤注册服务名称 . lb表⽰负载均衡, 使⽤ lb:// ⽅
式表⽰从注册中⼼获取服务地址.
3、 predicates: 路由条件, 根据匹配结果决定是否执⾏该请求路由, 上述代码中, 我们把符合Path规则的⼀切请求, 都代理到uri参数指定的地址.
⑤测试
四、Route Predicate Factories
Route Predicate Factories (路由断⾔⼯⼚, 也称为路由谓词⼯⼚, 此处谓词表⽰⼀个函数), 在Spring
Cloud Gateway中, Predicate提供了路由规则的匹配机制.
注:
①我们在配置⽂件中写的断⾔规则只是字符串, 这些字符串会被Route Predicate Factory读取并处理, 转变为路由判断的条件.
②Spring Cloud Gateway 默认提供了很多Route Predicate Factory, 这些Predicate会分别匹配HTTP请求的不同属性, 并且多个Predicate可以通过and逻辑进⾏组合.
predicate的值:
①After:这个⼯⼚需要⼀个⽇期时间(Java的 ZonedDateTime对象), 匹配指定⽇期之后的请求(比如:predicates: - After=2017-01-20T17:42:47.789-07:00[America/Denver])
②Before:匹配指定⽇期之前的请求(比如:predicates:
- Before=2017-01-20T17:42:47.789-07:00[America/Denver])
③Between:匹配两个指定时间之间的请求datetime2 的参数必须在datetime1 之后(比如:
predicates:
- Between=2017-01-20T17:42:47.789-07:00[America/Denver], 2017-01-21T17:42:47.789-07:00[America/Denver])
④Cookie:请求中包含指定Cookie, 且该Cookie值符合指定的正则表达式(比如:
predicates:
- Cookie=chocolate, ch.p)
⑤Header:请求中包含指定Header, 且该Header值符合指定的正则表达式(比如:
predicates:
- Header=X-Request-Id, \d+)
⑥Host:请求必须是访问某个host(根据请求中的Host字段进⾏匹配)(比如:
predicates:
- Host=**.somehost.org,**.anotherhost.org)
五、Gateway Filter Factories(⽹关过滤器⼯⼚)
Predicate决定了请求由哪⼀个路由处理, 如果在请求处理前后需要加⼀些逻辑, 这就是Filter(过滤器)的作⽤范围了.
Filter分为两种类型: Pre类型和Post类型
Pre类型过滤器: 路由处理之前执⾏(请求转发到后端服务之前执⾏), 在Pre 类型过滤器中可以做鉴权, 限流等。
Post类型过滤器: 请求执⾏完成后, 将结果返回给客⼾端之前执⾏.
Spring Cloud Gateway从作⽤范围上, 把Filter可分为GatewayFilter 和GlobalFilter.
GatewayFilter : 应⽤到单个路由或者⼀个分组的路由上.
GlobalFilter: 应⽤到所有的路由上, 也就是对所有的请求⽣效.
Spring Cloud Gateway提供了的Filter⾮常多, 下⾯列出⼀些常⻅过滤器:
①AddRequestHeader:为当前请求添加Header (比如:- AddRequestHeader=X-Request-red, blue 参数: Header的名称及值)
②AddRequestParameter:为当前请求添加请求参数(比如:- AddRequestParameter=red, blue
参数: 参数的名称及值)
③AddResponseHeader为响应结果添加Header(比如:- AddResponseHeader=X-Response-Red, Blue 参数: Header的名称及值)
④RemoveRequestHeader从当前请求删除某个Header (比如:- RemoveRequestHeader=X-Request-Foo 参数: Header的名称)
⑤RemoveResponseHeader:从响应结果删除某个Header(比如:RemoveResponseHeader=X-Response-Foo 参数: Header的名称)
⑥RequestRateLimiter为当前⽹关的所有请求执⾏限流过滤, 如果被限流, 默认会响应HTTP429-TooManyRequests默认提供了RedisRateLimiter的限流实现, 采⽤令牌桶算法实现限流功能. 此处不做具体介绍(比如:
filters:
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 10
redis-rate-limiter.burstCapacity: 20
redis-rate-limiter.requestedTokens: 1
redis-rate-limiter.replenishRate : 令牌填充速度, 即每秒钟允许多少个请求(不丢弃任何请求)
redis-rate-limiter.burstCapacity : 令牌桶容量, 即每秒⽤⼾最⼤能够执⾏的请求数量(不丢弃任何请求). 将此值设置为零将阻⽌所有请求
)
限流 -限制流量
限流算法
限流实现
限流算法:
1、固定窗口:(假设 流量限制:每分钟1000次)
若在第59秒的时候收到了1000次的请求,在第61秒的时候又收到1000次请求,就会导致1分钟内收到了多于1000的请求,就会导致服务器的损坏
2、滑动窗口:
3、漏铜算法:
这个算法对应激流量处理不好
4、令牌桶算法
过滤器的执行顺序:
既有GatewayFilter, ⼜有 GlobalFilter时, 执⾏的先后顺序:
请求路由后, ⽹关会把当前项⽬中的GatewayFilter和GlobalFilter合并到⼀个过滤器链(集合)中, 并进⾏排序, 依次执⾏过滤器
每⼀个过滤器都必须指定⼀个int类型的order值, 默认值为0, 表⽰该过滤的优先级. order值越⼩,优先级越⾼,执⾏顺序越靠前.
①Filter通过实现Order接⼝或者添加@Order注解来指定order值.
②Spring Cloud Gateway提供的Filter由Spring指定. ⽤⼾也可以⾃定义Filter, 由⽤⼾指定.
③当过滤器的order值⼀样时, 会按照 defaultFilter > GatewayFilter > GlobalFilter的顺序执⾏.