官方文档:https://docs.spring.io/spring-cloud-gateway/docs/2.2.6.RELEASE/reference/html/
简介
背景
大项目被拆成许多个微服务,各个微服务又可能有多台机器并行服务,如何准确的找到这些具体的服务品去访问资源,就成了一个问题。现在
概述
网关本质上要提供一个各种服务访问的入口,并提供服务接收并转发所有内外部的客户端调用,还有就是权限认证,限流控制等等。Spring Cloud Gateway是Spring公司基于Spring 5.0,Spring Boot 2.0 和 等技术开发的一个网关组件,它旨在为微服务架构提供一种简单有效的统一的 API入口,负责服务请求路由、组合及协议转换,并且基于 Filter 链的方式提供了权限认证,监控、限流等功能。
- 优点:
性能强劲:是第一代网关Zuul的1.6倍。
功能强大:内置了很多实用的功能,例如转发、监控、限流等
设计优雅,容易扩展。 - 缺点:
依赖Netty与WebFlux(Spring5.0),不是传统的Servlet编程模型(Spring MVC就是基于此模型实现),学习成本高。
需要Spring Boot 2.0及以上的版本,才支持
使用
- 添加依赖,添加此依赖后,就不要再添加
starter-web
的依赖了,因为gateway里面自带一个web服务的,两两者同时存在的话可能会有冲突
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
- 在
src/main/resource
文件夹下(如果不存在可自己创建一个文件夹,然后右键Mark Directory as
->Resources Root
,即可看到正常的资源文件夹了),添加application.yml
文件
server:
port: 9000
spring:
application:
name: sca-gateway
cloud:
gateway:
routes:
- id: rout01
uri: http://localhost:8081
predicates:
- Path=/nacos/provider/echo/**
filters:
- StripPrefix=1
- id: rout02
uri: http://localhost:8081
predicates:
- Path=/nacose/user #这里必须是等号,冒号的话,启动就会报错
filters:#局部过滤器,路径规则匹配后,按这里的指示从前边去掉使用/分融出来的n个元素
-StripPrefix=1 #这里也必须是等号,冒号的话,启动就会报错
- Tips:在这里按住
Ctrl
点击routes
可以看到它调用的地方,并据此猜测可设置的属性有哪些
- 创建启动类,并启动即可。这里需要注意的是我们在
pom.xml
里面配置的uri: http://localhost:8081
所以要先把8081的对应的服务程序启动起来,到目前为止gateway
实际起到了类似反向代理的作用。
package com.jt;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class MyGateWaySpringApplication {
public static void main(String[] args) {
SpringApplication.run(MyGateWaySpringApplication.class, args);
}
}
Gateway通过Nacos实现负责均衡
- 导入依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
- 修改配置文件
server:
port: 9000
spring:
application:
name: sca-gateway
cloud:
gateway:
routes:
- id: rout01
uri: lb://sca-provider #lb:为服务前缀(负载均衡单词的缩写),不能随意写
predicates:
- Path=/nacos/provider/echo/**
filters:
- StripPrefix=1
- id: rout02
uri: lb://sca-provider
predicates:
- Path=/nacose/user
filters:
- StripPrefix=1
nacos:
discovery:
server-addr: localhost:8848
执行流程
根据官方的说明,其Gateway具体工作流程,如图所示:
客户端向Spring Cloud Gateway发出请求。 如果Gateway Handler Mapping 通过断言predicates(predicates)的集合确定请求与路由(Routers)匹配,则将其发送到Gateway Web Handler。 Gateway Web Handler 通过确定的路由中所配置的过滤器集合链式调用过滤器(也就是所谓的责任链模式)。 Filter由虚线分隔的原因是, Filter可以在发送代理请求之前和之后运行逻辑。处理的逻辑是 在处理请求时 排在前面的过滤器先执行,而处理返回相应的时候,排在后面的过滤器先执行。
断言(Predicate)增强分析(了解)
5. Route Predicate Factories:https://docs.spring.io/spring-cloud-gateway/docs/2.2.6.RELEASE/reference/html/#gateway-request-predicates-factories
Predicate 简介
Predicate(断言)又称谓词,用于条件判断,只有断言结果都为真,才会真正的执行路由。断言其本质就是定义路由转发的条件。
Predicate 内置工厂
Datetime类型的断言工厂
- AfterRoutePredicateFactory:判断请求日期是否晚于指定日期
- BeforeRoutePredicateFactory:判断请求日期是否早于指定日期
- BetweenRoutePredicateFactory:判断请求日期是否在指定时间段内
header的断言工厂HeaderRoutePredicateFactory
需要两个参数,请求Header的名称和一个正则表达式(java语法).求匹配Header name
且满足正则校验
spring:
cloud:
gateway:
routes:
- id: header_route
uri: https://example.org
predicates:
- Header=X-Request-Id, \d+
The Query Route Predicate Factory
需要两个参数: 一个参数和一个正则表达式(可选).
spring:
cloud:
gateway:
routes:
- id: query_route
uri: https://example.org
predicates:
- Query=green
The RemoteAddr Route Predicate Factory
需要一个远端地址的列表,至少有一个,必须是IPv4或IPv6的网段, such as 192.168.0.1/16 (where 192.168.0.1 is an IP address and 16 is a subnet mask).
spring:
cloud:
gateway:
routes:
- id: remoteaddr_route
uri: https://example.org
predicates:
- RemoteAddr=192.168.1.1/24
The Weight Route Predicate Factory
需要两个参数: 组别和整数型的权重.权重按组计算.
spring:
cloud:
gateway:
routes:
- id: weight_high
uri: https://weighthigh.org
predicates:
- Weight=group1, 8
- id: weight_low
uri: https://weightlow.org
predicates:
- Weight=group1, 2
过滤器(Filter)增强分析(了解)
6. GatewayFilter Factories:https://docs.spring.io/spring-cloud-gateway/docs/2.2.6.RELEASE/reference/html/#gatewayfilter-factories
6.1. The AddRequestHeader
GatewayFilter
Factory
AddRequestHeader GatewayFilter factory
需要一个name
参数和一个value
参数
spring:
cloud:
gateway:
routes:
- id: add_request_header_route
uri: https://example.org
filters:
- AddRequestHeader=X-Request-red, blue
此过滤器会添加 X-Request-red:blue
到所有匹配的请求的Header
里面
spring:
cloud:
gateway:
routes:
- id: add_request_header_route
uri: https://example.org
predicates:
- Path=/red/{segment}
filters:
- AddRequestHeader=X-Request-Red, Blue-{segment}
6.2. The AddRequestParameter GatewayFilter Factory
需要一个name
参数和一个value
参数
spring:
cloud:
gateway:
routes:
- id: add_request_parameter_route
uri: https://example.org
filters:
- AddRequestParameter=red, blue
此过滤器会添加red=blue
到所有匹配的请求的QueryString
里面
spring:
cloud:
gateway:
routes:
- id: add_request_parameter_route
uri: https://example.org
predicates:
- Host: {segment}.myhost.org
filters:
- AddRequestParameter=foo, bar-{segment}
6.3. The AddResponseHeader GatewayFilter Factory
需要一个name
参数和一个value
参数
spring:
cloud:
gateway:
routes:
- id: add_response_header_route
uri: https://example.org
filters:
- AddResponseHeader=X-Response-Red, Blue
此过滤器会向所有匹配的请求的响应头中添加X-Response-Foo:Bar
网关层面的限流
- 添加依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
</dependency>
- 添加sentinel及路由规则(假如已有则无需设置)
routes:
- id: route01
uri: lb://sca-provider
predicates: ###匹配规则
- Path=/provider/echo/**
sentinel:
transport:
dashboard: localhost:8180 #Sentinel 控制台地址
eager: true #取消Sentinel控制台懒加载,即项目启动即连接
- 启动网关项目,检测sentinel控制台的网关菜单。
启动时,添加sentinel的jvm参数,通过此菜单可以让网关服务在sentinel控制台显示不一样的菜单,代码如下。注意,这里是在idea里面的网关的项目的启动类启动时加的参数
-Dcsp.sentinel.app.type=1
4. Sentinel 控制台启动以后,界面如图所示:
5. 在sentinel面板中设置限流策略,如图所示:
6. 通过url进行访问检测是否实现了限流操作