SpringCloud Gateway路由组件详解
目录
- 简介
- 核心概念
- 具体示例
- GlobalFilter
简介
Gateway是SpringCloud Alibaba中的路由组件(前身是Zuul),作为浏览器端请求的统一入口。当项目采用微服务模式时,若包含了路由模块,浏览器端的请求都不会直接请求含有业务逻辑的各个业务模块,而是请求这个路由模块,然后再由它来转发到各个业务模块去。
核心概念
Gateway中的三个核心概念:路由、断言(Predicate)、过滤器。
路由:由唯一id、目的url、断言和过滤组成
断言:即路由规则,用来判断哪些请求符合规则,符合的请求进行转发
过滤器:分为GatewayFilter和GlobalFilter,前者作用于单一路由,后者作用于所有路由。过滤器可以对请求或者返回进行处理,如增加请求头、删除请求头
配置文件如下:
spring:
cloud:
gateway:
# 网关路由配置
routes:
# 路由id,自定义,只要唯一即可
- id: user-service
# uri: http://127.0.0.1:8081 # 路由的目标地址 http就是固定地址
# 路由的目标地址 lb就是负载均衡,后面跟服务名称,要和nacos的注册中心结合
uri: lb://userservice
# 断言
predicates:
# 这个是按照路径匹配,只要以/user/开头就符合要求
- Path=/user/**
# 过滤器
filters:
# 添加请求头
- AddRequestHeader=sign, xn2001.com is eternal
上面写到了根据路径匹配的断言,Gateway提供了十几种内置的断言:
名称 | 说明 | 示例 |
---|---|---|
After | 是某个时间点之后的请求 | - After=2022-08-26T18:34:10.475+08:00[Asia/Shanghai] |
Before | 是某个时间点之前的请求 | - Before=2022-11-26T18:34:10.475+08:00[Asia/Shanghai] |
Between | 是某两个时间点之前的请求 | - Between=2022-10-26T18:35:15.093+08:00[Asia/Shanghai], 2022-11-26T18:35:15.093+08:00[Asia/Shanghai] |
Cookie | 请求必须包含某些cookie | - Cookie=chocolate, ch.p |
Header | 请求必须包含某些header | - Header=sign, internal |
Host | 请求必须是访问某个host(域名) | - Host=**.somehost.org, **.anotherhost.org |
Method | 请求方式必须是指定方式 | - Method=GET,POST |
Path | 请求路径必须符合指定规则 | - Path=/blue/** |
Query | 请求参数必须包含指定参数 | - Query=name, Jack或- Query=name |
RemoteAddr | 请求者的ip必须是指定范围 | - RemoteAddr=192.168.1.1/24 |
Weight | 权重处理 |
配置中的AddRequestHeader就是其中一种Gateway Filter,还有其余的内置的:
名称 | 说明 |
---|---|
AddRequestHeader | 给当前请求添加一个请求头 |
RemoveRequestHeader | 移除请求中的一个请求头 |
AddResponseHeader | 给响应结果中添加一个响应头 |
RemoveResponseHeader | 从响应结果中移除一个响应头 |
RequestRateLimiter | 限制请求的流量 |
全局过滤器,后面的示例给出具体用法
具体示例
这里新建2个模块,路由模块和用户模块
用户模块,引入依赖spring-boot-starter-web、spring-cloud-starter-alibaba-nacos-discovery,bootstrap.yml配置端口号、nacos注册中心的地址,并提供接口:
import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestHeader; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; @Controller @RequestMapping("/user") public class UserController { @ResponseBody @RequestMapping("/sayHello") public String sayHello(@RequestHeader(value = "sign", required = false) String sign) { return "这是好吃的:" + sign; } }
路由模块,引入依赖:
<dependencies> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config </artifactId> <version>2.2.0.RELEASE</version> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery </artifactId> <version>2.2.0.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> <version>2.2.0.RELEASE</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> </dependencies>
bootstrap.yml的配置:
server:
port: 8086
servlet:
context-path: /gatewayspring:
application:
name: gateway
profiles:
active: dev
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848
file-extension: yml
discovery:
server-addr: 127.0.0.1:8848
2个模块都启动后,nacos的服务列表显示:
nacos中新建名为gateway-dev.yml的配置,内容为:
spring:
cloud:
gateway:
discovery:
locator:
# 通过服务名称转发,默认false
enabled: true
# 服务名称不用大写
lower-case-service-id: true
# routes:
# - id: user-service
# uri: lb://supplier
# predicates:
# - Path=/provider/**
# filters:
# - AddRequestHeader=sign, big JavaCoder
此时,请求路径:http://localhost:8086/supplier/provider/user/sayHello
注:supplier是服务名称,provider是模块访问路径(server.servlet.context-path)
但这种配置不是很推荐
把spring.cloud.gateway.discovery及子配置注释掉,把spring.cloud.gateway.routes及子配置取消注释,重启路由模块,这时访问路径:
http://localhost:8086/provider/user/sayHello。
注:这是访问的路径,经过gateway处理后,实际访问的是lb://supplier/provider/user/sayHello(见RouteToRequestUrlFilter的filter方法);provider是模块访问路径(server.servlet.context-path),如果用户模块没有设置的话,filters下添加- StripPrefix=1,这时访问路径不变,实际的访问路径是lb://supplier/user/sayHello。
GlobalFilter
处理一切进入网关的请求和响应,并且也是可以编写代码自定义逻辑;在执行顺序上,GatewayFilter先执行,GlobalFilter后执行。
import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.cloud.gateway.filter.GlobalFilter; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.http.server.reactive.ServerHttpResponse; import org.springframework.stereotype.Component; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; import java.util.List; @Component public class AuthorizeFilter implements GlobalFilter { @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { ServerHttpRequest request = exchange.getRequest(); HttpHeaders headers = request.getHeaders(); List<String> sign = headers.get("sign"); if(sign.size() < 1) { ServerHttpResponse response = exchange.getResponse(); response.setStatusCode(HttpStatus.BAD_REQUEST); //被拦截,请求不到对应模块了 return exchange.getResponse().setComplete(); } headers = HttpHeaders.writableHttpHeaders(headers); headers.set("sign1", "bigAAA"); //放行 return chain.filter(exchange); } }
到此这篇关于SpringCloud Gateway路由组件详解的文章就介绍到这了,更多相关SpringCloud Gateway内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!