Spring Cloud Gateway
微服务架构中的 API Gateway (网关) 是一个关键组件,它作为所有客户端请求的单一入口点,负责路由请求、聚合结果以及对各个微服务进行各种横切关注点(Cross-Cutting Concerns)的处理。
Gateway最主要功能就是路由转发、鉴权、限流。服务器可能部署在不同的位置,导致IP地址、端口都不同,想要访问就需要知道IP地址、端口,而Gateway帮我们统一进行管理
使用版本
Nacos:2.5.1
快速启动指令:
startup.cmd -m standalone
SpringBoot:3.2.4
<!--版本管理-->
<properties>
<java.version>17</java.version>
<spring-cloud.version>2023.0.1</spring-cloud.version>
<alibaba.version>2023.0.1.0</alibaba.version>
</properties>
Gateway依赖包
使用此依赖包不能和spring-boot-starter-web依赖包一起,会冲突
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
Gateway需要负载均衡
负载均衡依赖包
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
快速使用
Demo1模块
controller代码
@Controller
@RequestMapping("demo")
public class Demo1Controller
{
@GetMapping("get")
@ResponseBody
public String getDemo1()
{
return "getDemo1";
}
}
Demo2模块
controller代码
@Controller
@RequestMapping("demo")
public class Demo2Controller
{
@GetMapping("get")
@ResponseBody
public String getDemo2()
{
return "getDemo2";
}
}
gateway模块
运行
路由配置
它定义了请求应该如何被转发到后端服务。以下是路由的关键属性及其配置方式:
路由过滤器
请求/响应头操作
过滤器 | 作用 | 示例 |
---|---|---|
AddRequestHeader | 添加请求头 | - AddRequestHeader=X-Request-Foo, Bar |
AddResponseHeader | 添加响应头 | - AddResponseHeader=X-Response-Foo, Bar |
RemoveRequestHeader | 移除请求头 | - RemoveRequestHeader=X-Request-Foo |
RemoveResponseHeader | 移除响应头 | - RemoveResponseHeader=X-Response-Foo |
SetRequestHeader | 设置请求头 | - SetRequestHeader=X-Request-Foo, NewBar |
SetResponseHeader | 设置响应头 | - SetResponseHeader=X-Response-Foo, NewBar |
路径操作
过滤器 | 作用 | 示例 |
---|---|---|
PrefixPath | 添加前缀 | - PrefixPath=/api |
StripPrefix | 去除前缀 | - StripPrefix=2 |
RewritePath | 重写路径 | - RewritePath=/old/(?.*), /new/${segment} |
SetPath | 设置路径 | - SetPath=/{segment} |
请求参数操作
过滤器 | 作用 | 示例 |
---|---|---|
AddRequestParameter | 添加参数 | - AddRequestParameter=foo, bar |
RemoveRequestParameter | 移除参数 | - RemoveRequestParameter=foo |
高级功能
过滤器 | 作用 | 示例 |
---|---|---|
RequestRateLimiter | 限流 | - RequestRateLimiter=10, 20, #{@keyResolver} |
Retry | 重试 | - Retry=3 |
CircuitBreaker | 熔断 | - CircuitBreaker=myCircuitBreaker, forward:/fallback |
FallbackHeaders | 熔断头信息 | - FallbackHeaders |
SaveSession | 保存Session | - SaveSession |
GlobalFilter
package com.example.filter;
import org.springframework.boot.autoconfigure.info.ProjectInfoProperties;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
@Configuration
public class MyGlobalFilter implements GlobalFilter , Ordered
{
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
//模拟登录校验逻辑
ServerHttpRequest request = exchange.getRequest();
HttpHeaders headers = request.getHeaders();
System.out.println("模拟登录校验逻辑");
System.out.println(headers);
/**
* title:网关给微服务传消息
* top1:在登录成功后保存用户信息到下游请求头中
* top2:要修改转发到微服务的请求
*/
String userId = "1";//模拟要传递的用户id
exchange.mutate() //mutate对下游请求做出处理
.request(builder -> {builder.header("user-info", userId);})
.build();
//或者
// exchange.getRequest().mutate().header("userId",userId).build();
//放行,返回此过滤链
return chain.filter(exchange);
}
/**
* @return 设置过滤器优先级,值越小,优先级越高
*/
@Override
public int getOrder() {
return 0;
}
}
运行效果:
自定义GatewayFilter
不带参数
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.OrderedGatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
@Component
public class PrintHeaderGatewayFilterFactory extends AbstractGatewayFilterFactory<Object>
{
@Override
public GatewayFilter apply(Object config) {
//OrderedGatewayFilter的参数1为:GatewayFilter(被包装的实际过滤器实例),参数2为:顺序值(数值越小优先级越高)
//优先度设置为1低于MyGlobalFilter的优先度0,能获取到MyGlobalFilter设置的user-info
return new OrderedGatewayFilter(new GatewayFilter(){
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
//截取MyGlobalFilter的user-info数据
ServerHttpRequest request = exchange.getRequest();
HttpHeaders headers = request.getHeaders();
System.out.println(headers.getFirst("user-info"));
return chain.filter(exchange);
}
},1);//顺序值
}
}
yml配置文件
spring:
cloud:
gateway:
default-filters: PrintHeader
补充:
PrintHeaderGatewayFilterFactory的前缀为PrintHeader,后缀是固定的必须为GatewayFilterFactory,前缀与default-filters对应
运行效果:
截取到MyGlobalFilter设置user-info数据
带参数
import lombok.Data;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.OrderedGatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import java.util.List;
@Component
public class PrintHeaderArgsGatewayFilterFactory extends AbstractGatewayFilterFactory<PrintHeaderArgsGatewayFilterFactory.Config>
{
@Override
public GatewayFilter apply(PrintHeaderArgsGatewayFilterFactory.Config config) {
//OrderedGatewayFilter的参数1为:GatewayFilter(被包装的实际过滤器实例),参数2为:顺序值(数值越小优先级越高)
//优先度设置为1低于MyGlobalFilter的优先度0,能获取到MyGlobalFilter设置的user-info
return new OrderedGatewayFilter(new GatewayFilter(){
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
//打印参数
System.out.println(config.a);
System.out.println(config.b);
return chain.filter(exchange);
}
},1);//顺序值
}
//自定义配置属性,成员变量名称很重要,下面需要用到
@Data
public static class Config
{
private String a;
private String b;
}
//将变量名称依次返回,顺序很重要,读取参数是按顺序读取的
@Override
public List<String> shortcutFieldOrder() {
return List.of("a","b");
}
//将Config字节码传递给父类,父类帮我们读取yml配置
public PrintHeaderArgsGatewayFilterFactory()
{
super(Config.class);
}
}
yml配置文件
spring:
cloud:
gateway:
default-filters:
- PrintHeaderArgs=hello,world
运行效果: