一、gateway概念
spring cloud gateway(简称 gateway)是一个基于 spring webflux 的 api 网关解决方案,旨在为微服务架构中的客户端提供路由、负载均衡、认证、限流、监控等功能。
它作为微服务架构中的流量入口,通常位于客户端和后端微服务之间,处理来自客户端的请求并将其路由到相应的服务。
主要特性:
- 路由功能:spring cloud gateway 可以根据请求的不同特征(如路径、方法、头部、参数等)将请求路由到不同的微服务。
- 负载均衡:支持与服务注册中心(如 eureka)集成,能够将流量分发到多个实例,以实现负载均衡。
- 过滤器:提供了丰富的过滤器功能,可以在请求和响应的生命周期中进行定制化处理。例如,身份认证、日志记录、限流等。
- 反向代理:可以将请求转发给后端服务,实现反向代理功能。
- 高可用和可扩展性:通过与 spring cloud 配合使用,spring cloud gateway 能够在微服务架构中提供高可用和扩展性支持。
- 监控:可以与 spring boot actuator 集成,提供请求和响应的监控功能,帮助开发人员监控系统的健康状况和性能。
二、基本路由
路由是将客户端请求发送到后端服务的主要组件。它定义了请求的匹配规则以及请求将被转发到的目标(即uri)。每个路由都具有一个id、uri以及predicates。
id:每个路由的唯一标识符。uri:路由转发的目标uri。对于lb://协议,它指向服务注册中心(如eureka)中的服务,表示请求将被转发到注册的服务。predicates:定义了路由的匹配条件,决定哪些请求将被此路由处理。
spring:
cloud:
gateway:
routes:
- id: order-route
uri: lb://service-order
predicates:
- path=/api/order/**三、断言
断言(predicates) 用于根据请求的各种属性来匹配路由,它们是路由的核心部分。
断言支持不同的匹配条件,如路径、请求方法、请求头等。通过不同的请求模式来匹配对应的微服务。
3.1在spring cloud gateway的配置中,断言有两种写法
- 长写法:指定完整的断言语法,明确标明断言的类型。
spring:
cloud:
gateway:
routes:
- id: order-route
uri: lb://service-order
predicates:
- name: path
args:
pattern: /api/order/**- 短写法:是断言的简化写法,直接使用断言类型的简洁形式。
spring:
cloud:
gateway:
routes:
- id: order-route
uri: lb://service-order
predicates:
- path=/api/order/**系统内置断言(predicates)
spring cloud gateway 提供了很多内置的断言类型,用来处理各种请求匹配需求。常用的断言类型包括:

这张图展示了spring cloud gateway中常用的路由断言(predicates)及其相关参数说明。断言是路由配置的重要组成部分,它们用来判断请求是否满足特定条件,以决定是否将请求转发到目标服务。
每种断言都允许通过指定参数来对请求进行详细匹配。
3.2自定义断言
我们通过继承 abstractroutepredicatefactory 类,创建了一个名为 viproutepredicatefactory 的类,实现了自定义的路由断言逻辑,示例代码如下:
import org.springframework.cloud.gateway.handler.predicate.abstractroutepredicatefactory;
import org.springframework.stereotype.component;
import org.springframework.web.server.serverwebexchange;
import org.springframework.http.server.reactive.serverhttprequest;
import org.apache.commons.lang3.stringutils;
import java.util.arrays;
import java.util.list;
import java.util.function.predicate;
/**
* 自定义路由断言工厂
*/
@component
public class viproutepredicatefactory extends abstractroutepredicatefactory<viproutepredicatefactory.config> {
public viproutepredicatefactory() {
super(config.class); // 传入config类
}
@override
public list<string> shortcutfieldorder() {
// 返回配置类中的字段顺序
return arrays.aslist("param", "value");
}
@override
public predicate<serverwebexchange> apply(config config) {
return new gatewaypredicate() {
@override
public boolean test(serverwebexchange serverwebexchange) {
// 获取请求
serverhttprequest request = serverwebexchange.getrequest();
// 从请求的查询参数中获取 'param' 对应的值
string first = request.getqueryparams().getfirst(config.param);
// 比较查询参数的值与配置中的 'value' 是否匹配
return stringutils.isnotblank(first) && first.equals(config.value);
}
};
}
// 配置类
public static class config {
private string param; // 查询参数名称
private string value; // 查询参数期望的值
// getter和setter方法
public string getparam() {
return param;
}
public void setparam(string param) {
this.param = param;
}
public string getvalue() {
return value;
}
public void setvalue(string value) {
this.value = value;
}
}
}viproutepredicatefactory 类
- 该类继承自
abstractroutepredicatefactory,实现了自定义断言工厂的功能。 abstractroutepredicatefactory是 spring cloud gateway 提供的基础类,用于创建自定义的路由断言。- 我们将
config.class作为构造函数的参数传递给父类,表示我们会用config类来存储断言所需的配置参数。
shortcutfieldorder() 方法
- 这个方法返回一个
list<string>,用于定义配置类中字段的顺序。 - 在这个例子中,
param和value的顺序决定了用户在配置时,param和value应该以这个顺序出现。 - spring cloud gateway 使用
shortcutfieldorder()方法来生成简洁的 yaml 配置。
spring:
cloud:
gateway:
routes:
- id: vip-route
uri: https://example.com
predicates:
- name: vip(routepredicatefactory)//vip是断言工厂名前缀
args:
param: q
value: testapply(config config) 方法
- 这个方法用于应用自定义断言的逻辑,接收
config类的实例作为参数。 config类包含了路由断言所需的参数(param和value)。- 该方法返回一个
predicate<serverwebexchange>,用于对每个请求进行断言判断。
这里的 predicate<serverwebexchange> 表示一个函数,它接收一个 serverwebexchange(表示当前请求),并返回一个布尔值,表示该请求是否匹配该断言。
test(serverwebexchange serverwebexchange) 方法
- 在这个方法中,我们实际执行请求的匹配逻辑。首先通过
serverwebexchange.getrequest()获取当前请求对象。接着,我们从请求的查询参数中获取与config.param对应的值,存储在first变量中。 - 然后,我们检查
first是否为空,并与config.value进行比较。如果它们相等,并且查询参数不为空,我们返回true,表示路由匹配成功;否则返回false,表示路由不匹配。
config 类
config类是一个静态类,用来存储自定义断言需要的配置参数。这里有两个字段:param表示查询参数的名称,value表示查询参数的期望值。用户通过配置文件传入这两个参数。config类的作用是封装从配置文件中读取的参数,并通过@validated等注解进行验证
四、过滤器
过滤器(filters) 是用于在请求和响应过程中执行特定操作的机制。它们是在路由决策之前或之后执行的,可以对请求进行修改(如添加头部、修改请求体)或响应进行处理(如修改响应内容、记录日志等)。
过滤器的使用大致可以分为两种类型:前置过滤器(pre-filter)和后置过滤器(post-filter)。前置过滤器在请求到达目标服务之前执行,后置过滤器则在响应返回客户端之前执行。
过滤器主要用于以下目的:
- 请求和响应的修改。
- 安全性(如身份验证)。
- 负载均衡和限流。
- 请求日志和性能监控。
4.1基本的过滤器使用步骤
添加依赖: 需要在pom.xml文件中加入spring cloud gateway的依赖:
<dependency>
<groupid>org.springframework.cloud</groupid>
<artifactid>spring-cloud-starter-gateway</artifactid>
</dependency>创建过滤器: 可以通过实现gatewayfilter接口来创建自定义过滤器。spring cloud gateway提供了gatewayfilter接口和globalfilter接口,分别用于处理特定路由和全局的请求过滤。
import org.springframework.cloud.gateway.filter.gatewayfilter;
import org.springframework.cloud.gateway.filter.gatewayfilterchain;
import org.springframework.stereotype.component;
import org.springframework.web.server.serverwebexchange;
import reactor.core.publisher.mono;
@component
public class mycustomfilter implements gatewayfilter {
@override
public mono<void> filter(serverwebexchange exchange, gatewayfilterchain chain) {
// 在请求处理之前执行的逻辑
system.out.println("请求被过滤: " + exchange.getrequest().geturi());
// 执行后续过滤器链
return chain.filter(exchange);
}
}注册过滤器: 自定义过滤器可以通过注入gatewayfilter的方式注册到spring的上下文中。可以将过滤器注入到@configuration中,或者直接使用@component注解让其自动注册。
配置路由过滤器: 在路由配置中,可以为某个特定的路由设置过滤器。
spring:
cloud:
gateway:
routes:
- id: my_route
uri: http://httpbin.org:80
predicates:
- path=/get
filters:
- name: requestheadertorequesturi
args:
name: x-request-id4.2全局过滤器使用步骤
全局过滤器是应用于所有路由请求的过滤器,它们在请求到达目标服务之前和响应返回时都会被执行。全局过滤器对于记录日志、身份验证等场景非常有用。
import org.springframework.cloud.gateway.filter.globalfilter;
import org.springframework.cloud.gateway.filter.gatewayfilterchain;
import org.springframework.web.server.serverwebexchange;
import reactor.core.publisher.mono;
@component
public class loggingglobalfilter implements globalfilter {
@override
public mono<void> filter(serverwebexchange exchange, gatewayfilterchain chain) {
// 记录请求的url
string path = exchange.getrequest().geturi().getpath();
system.out.println("request path: " + path);
// 继续处理链中的下一个过滤器
return chain.filter(exchange);
}
}4.3自定义过滤器使用步骤
spring cloud gateway允许开发者创建自定义过滤器。
自定义过滤器有两种类型:
gatewayfilter:只能作用于单个路由。globalfilter:作用于所有路由。
import org.springframework.cloud.gateway.filter.globalfilter;
import org.springframework.cloud.gateway.filter.gatewayfilterchain;
import org.springframework.web.server.serverwebexchange;
import org.springframework.http.httpstatus;
import reactor.core.publisher.mono;
@component
public class loggingglobalfilter implements globalfilter {
@override
public mono<void> filter(serverwebexchange exchange, gatewayfilterchain chain) {
// 获取请求的路径
string path = exchange.getrequest().geturi().getpath();
// 记录请求的路径
system.out.println("request path: " + path);
// 向请求中添加一个自定义的请求头
exchange.getrequest().mutate()
.header("x-request-id", "request-" + system.currenttimemillis()) // 设置一个自定义请求头
.build();
// 继续处理请求
return chain.filter(exchange)
.doonterminate(() -> {
// 记录响应结束时的日志
system.out.println("request " + path + " processed.");
});
}
}loggingglobalfilter 实现了 globalfilter 接口:
该过滤器会应用于所有的请求,不管是哪个路由请求都会执行这个过滤器的逻辑。
filter() 方法:
- 在这个方法中,首先我们通过
exchange.getrequest().geturi().getpath()获取当前请求的路径。 - 然后,我们通过
system.out.println()打印日志,记录下请求的路径。 - 接着,我们使用
mutate()方法修改请求,添加了一个自定义的请求头x-request-id,其值为当前时间戳(这样可以在日志中唯一标识每个请求)。 - 最后,通过
chain.filter(exchange)将请求继续传递给下一个过滤器链
4.4过滤器的执行顺序
spring cloud gateway的过滤器按以下顺序执行:
- 请求过滤器:请求从客户端进入网关后,过滤器链会逐个执行请求过滤器。
- 过滤器执行顺序是链式的:
globalfilter->gatewayfilter
- 过滤器执行顺序是链式的:
- 响应过滤器:请求被转发到目标服务,响应返回时,再次按链式执行响应过滤器。
4.5常用过滤器
spring cloud gateway提供了一些内置的过滤器,可以直接使用。例如:
addrequestheader:添加请求头部。addresponseheader:添加响应头部。removerequestheader:删除请求头部。removeresponseheader:删除响应头部。setpath:修改请求路径。rewritepath:重写路径。
添加请求头的过滤器举例:
spring:
cloud:
gateway:
routes:
- id: add-header-route
uri: http://localhost:8081
predicates:
- path=/add-header/**
filters:
- addrequestheader=x-custom-header, value总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。
发表评论