一、先搭建好springcloud+nacos项目
地址:https://javazhong.blog.csdn.net/article/details/128899999
二、spring cloud gateway简述
Spring Cloud Gateway 是Spring Cloud家族中的一款API网关。Gateway 建立在 Spring Webflux上,目标是提供一个简洁、高效的API网关,同时也可以快速的拼装上Spring Cloud全家桶的API网关。
Spring Cloud Gateway的通信框架使用的是Netty。
2.1 spring cloud gateway特征
基于Spring Framework 5, Project Reactor, Spring Boot 2.0构建
能够自由设置任何请求属性的路由
路由可以自由设置断言(Predicates)和过滤器(Filter)
可集成熔断器
流量限速
路径重写(rewrite)
三、spring cloud gateway网关作用
3.1 访问示意图
3.2 解释
增加了API网关以后(gateway),在API网关层可以把后端的多个服务进行整合,然后提供一个唯一的业务接口,客户端只需要调用这个接口就可以完成数据的获取和展示。而且,官网不只是做请求转发和服务整合。有了统一的网关入口以后,它还可以提供统一鉴权、限流、日志、熔断,以及统一错误码处理,针对后端多种不同协议,还可以进行协议转化。
四、spring cloud流程介绍
4.1 spring cloud流程图
4.2 流程介绍
客户端发送请求给gateway
请求首先被HttpWebHandlerAdapter进行提取组装成网关上下文,
然后网关的上下文会传递到DispatcherHandler进行请求处理(DispatcherHandler是所有请求的处理分发器)
DispatcherHandler负责将所有的请求分发给对应的处理器
比如分发给RoutePredicateHandlerMapping(路由断言处理映射器),路由断言映射器主要作用是进行路由查找,以及找到路由以后返回给对应的FilterWebHandler
FilterWebHandler主要负责组装Filter链,并调用Filter执行一系列的Filter操作
然后再把请求转到后端对应的代理服务处理
处理完毕之后将Response返回到Gateway客户端
4.3 核心介绍
4.3.1 Filter过滤器
使用过滤器,可以在请求被路由之前或者之后对请求进行修改
过滤器按照请求和响应可以分为两种:Pre类型和Post类型
Pre类型:在请求转发到微服务之前,对请求进行拦截和修改,例如参数校验、权限校验、流量监控、日志输出、协议转换等操作
Post类型:微服务处理完请求后,返回响应给网关,网关可以再次进行处理,例如可以修改响应内容、响应头、日志输出、流量监控等
按照过滤器Filter作用范围划分
GlobaFilter:全局过滤器,应用在所有路由上的过滤器
GatewayFilter:局部过滤器,应用在单个路由或一组路由上的过滤器
4.3.2 Route(路由)
构建网关的基础模块,由ID,目标URL,过滤器等组成
4.3.3 Predicate(断言)
开发人员可以匹配HTTP请求中的内容(请求头和请求参数),如果请求断言则进行路由
4.4 核心思想
路由转发+执行过滤器链
当用户发送请求达到Gateway之后,会通过一些匹配条件,定位到真正的服务节点,并且在这个过程的转发前后,进行一些细粒度控制,其中Predicate(断言)是我们的匹配条件,Filter是一个拦截器,有了这两点,再加上URL,就可以实现一个具体的路由。
五、源码实现
按照上一篇springcloud+nacos项目,创建一个gateway模块
https://javazhong.blog.csdn.net/article/details/128899999
5.1 pom代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>obwt-cloud</artifactId>
<groupId>com.obwt</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<groupId>com.gateway</groupId>
<artifactId>gateway-cloud</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>gateway-cloud</name>
<description>gateway-cloud</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
</dependency>
<!--mysql-connector-java-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!--jdbc-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--nacos-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--bootstrap 启动器-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
<!-- mybatis-plus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-core</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-extension</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>
<!--openfeign-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!-- SpringCloud Lo
adbalancer -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
<!--gateway-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!-- SpringCloud Alibaba Sentinel Gateway -->
<!-- <dependency>-->
<!-- <groupId>com.alibaba.cloud</groupId>-->
<!-- <artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>-->
<!-- </dependency>-->
</dependencies>
<build>
</build>
</project>
5.2 bootstrap代码
server:
port: 8005
spring:
main:
web-application-type: reactive #用于显示请求特定类型的Web应用程序标志,如果未设置,就会根据路径自行检测
application:
name: gateway-cloud-service
profiles:
active: dev
cloud:
nacos:
discovery:
server-addr: 192.168.139.128:8848
group: LOCAL_GROUP
service: ${spring.application.name}
config:
file-extension: yaml
group: LOCAL_GROUP
server-addr: 192.168.139.128:8848
#网关配置
gateway:
routes:
- id: baidu
uri: http://www.baidu.com
predicates: #当请求的路径包含url=baidu的时候,指向http://www.baidu.com
- Query=url,baidu
- id: userInfo #这个id只要保证唯一就好
uri: lb://bms-cloud-service #负载均衡 lb 是负载均衡的缩写,在注册中心找叫做bms-cloud-service服务
predicates: #设置路由断言
- Path=/user/** #设置路由断言,当请求包含了/user开头的接口时进行转发,比如/user/Info的时候,这条路由会生效,会去找bms-cloud-service服务上的/user/info接口
- id: copeInfo #这个id只要保证唯一就好
uri: http://localhost:8001 #这种方式是直接定死的静态路由,当请求localhost:8005/test的时候会转发给localhost:8001/test
predicates:
- Path=/test
- id: testBms #这个id只要保证唯一就好
uri: lb://bms-cloud-service
predicates:
- Path=/api/test/**
filters:
#将跳转路径中包含的"api"替换成空,在请求的时候必须带上api,但是在对应的服务(bms-cloud-service)转接口的时候不需要有api
- RewritePath=/api/(?<segment>.*),/$\{segment}
- id: bms #这个id只要保证唯一就好
uri: lb://bms-cloud-service
predicates:
- Path=/bms/**
5.3 controller测试代码
bms-cloud-service服务上对应的controller层测试代码
测试的时候要启动gateway-cloud-service模块和bms-cloud-service模块,但是入口就是gateway模块
@RestController
public class TestController {
@GetMapping("/api/test")
public String test() {
return "bms的api的test";
}
@GetMapping("/api/test/22")
public String test22() {
return "bms的api的test22";
}
@GetMapping("/test")
public String test1() {
return "bms的test1";
}
@GetMapping("/test/test2")
public String testTest() {
return "bms的test2";
}
@GetMapping("/userInfo")
public String userInfo() {
return "bms的userInfo";
}
@GetMapping("/userInfo/user")
public String userInfoUser() {
return "bms的userInfo2";
}
@GetMapping("/user/userInfo")
public String user() {
return "bms的userInfo3";
}
@GetMapping("/user/userInfo2")
public String user2() {
return "bms的userInfo4";
}
}
六、配置拓展
- id: bms #这个id只要保证唯一就好
uri: lb://bms-cloud-service
断言 | 实例 | 说明 |
Path | - Path=/api/bms/** | 请求路径于/api/bms/**匹配时,该请求才能转发到bms-cloud-service服务上,比如localhost:8005/api/bms/user,那么会自动去寻找bms-cloud-service服务上的/api/bms/user接口 |
Before | - Before=2023-01-01T08:29:59.100+08:00[Asia/Shanghai] | 在2023年01月01日08是29分59.100秒之前请求,才会转发到bms-cloud-service服务上 |
After | - After=2023-01-01T08:29:59.100+08:00[Asia/Shanghai] | 在2023年01月01日08是29分59.100秒之后请求,才会转发到bms-cloud-service服务上 |
Between | - Between=2023-01-01T08:29:59.100+08:00[Asia/Shanghai], 2023-02-01T08:29:59.100+08:00[Asia/Shanghai] | 在2023年01月01日08是29分59.100秒至在2023年02月01日08是29分59.100秒之间请求,才会转发到bms-cloud-service服务上 |
Cookie | - Cookie=name,bmsservice.cc | 携带Cookie且Cookie内容为name=bmsservice.cc的请求,才会转发到bms-cloud-service服务上 |
Header | - Header=X-Request-ld,\d+ | 请求头上携带属性X-request-ld,且属性值为整数的请求,才会转发到bms-cloud-service服务上 |
Method | - Method=GET | 只有GET请求才会被转发到bms-cloud-service服务上 |