SpringCloud-Gateway实现网关 Posted 2023-04-05 W_Meng_H
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SpringCloud-Gateway实现网关相关的知识,希望对你有一定的参考价值。
网关作为流量的入口,常用的功能包括路由转发、权限校验、限流等
Spring Cloud 是Spring官方推出的第二代网关框架,由WebFlux+Netty+Reactor实现的响应式的API网关,它不能在传统的servlet容器工作,也不能构建war包。基于Filter的方式提供网关的基本功能,例如说安全认证、监控、限流等。
一、功能特征
1、路由:
路由是网关中最基础的部分,路由信息包括一个ID、一个目的URI、一组断言工厂、一组Filter组成,如果断言为真,则说明请求的URL和配置的路由匹配。
2、断言:
Java8的断言函数,SpringCloud Gateway中的断言函数类型是Spring5.0框架中的ServerWebExchange。断言函数允许开发者去定义匹配Http request中的任何信息,比如请求头和参数等。
3、过滤器:
SpringCloud Gateway中的Filter分为Gateway Filter和Global Filter。Filter可以对请求和响应进行处理。
官网文档:https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/
二、工作原理
Gateway的工作原理和Zuul的差不多,最大区别就是Gateway的Filter只有pre和post两种。
客户端向Spring Cloud Gateway发出请求,如何请求与网关程序定义的路由匹配,则该请求就会被发送到网关Web处理程序,此时处理程序运行特定的请求过滤器链,过滤器之间用虚线分开的原因是过滤器可能会在发送代理请求的前后处理逻辑。所有pre过滤器逻辑先执行,然后执行代理请求;代理请求完成后,执行post过滤器逻辑组。
本案例未融合Cloud体系,只是使用Gateway网关功能
三、项目案例
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>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.8</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>gateway</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>gateway</name>
<description>gateway</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!-- <dependency>-->
<!-- <groupId>org.springframework.boot</groupId>-->
<!-- <artifactId>spring-boot-starter-web</artifactId>-->
<!-- <exclusions>-->
<!-- <!– 排除掉springmvc相关的配置信息 –>-->
<!-- <exclusion>-->
<!-- <groupId>org.springframework</groupId>-->
<!-- <artifactId>spring-webmvc</artifactId>-->
<!-- </exclusion>-->
<!-- <!– 排除掉tomcat相关的配置 –>-->
<!-- <exclusion>-->
<!-- <groupId>org.springframework.bootk</groupId>-->
<!-- <artifactId>spring-boot-starter-tomcat</artifactId>-->
<!-- </exclusion>-->
<!-- <exclusion>-->
<!-- <groupId>org.apache.tomcat.embed</groupId>-->
<!-- <artifactId>tomcat-embed-core</artifactId>-->
<!-- </exclusion>-->
<!-- <exclusion>-->
<!-- <groupId>org.apache.tomcat.embed</groupId>-->
<!-- <artifactId>tomcat-embed-el</artifactId>-->
<!-- </exclusion>-->
<!-- <exclusion>-->
<!-- <groupId>org.apache.tomcat.embed</groupId>-->
<!-- <artifactId>tomcat-embed-websocket</artifactId>-->
<!-- </exclusion>-->
<!-- </exclusions>-->
<!-- </dependency>-->
<!-- <!– https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-loadbalancer –>-->
<!-- <dependency>-->
<!-- <groupId>org.springframework.cloud</groupId>-->
<!-- <artifactId>spring-cloud-starter-loadbalancer</artifactId>-->
<!-- <version>2.2.5.RELEASE</version>-->
<!-- </dependency>-->
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-gateway-core -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
<version>3.1.5</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.75.Final</version>
</dependency>
<!-- <dependency>-->
<!-- <groupId>org.springframework.boot</groupId>-->
<!-- <artifactId>spring-boot-starter-webflux</artifactId>-->
<!-- <version>2.2.6.RELEASE</version>-->
<!-- </dependency>-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
yml文件
spring:
application:
name: spring-cloud-gateway-sample
cloud:
gateway:
routes:
- id: test
uri: http://www.baidu.com
predicates:
- Path=/api/**
filters:
- StripPrefix=1
server:
port: 9090
启动项目,访问http://localhost:9090/api 会重定向到自己指定的链接
四、路由断言工厂配置
官方文档:https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#gateway-request-predicates-factories
自定义路由断言工厂
继承 AbstractRoutePredicateFactory 类,重写 apply 方法的逻辑和shortcutFieldOrder方法。
在 apply 方法中可以通过 exchange.getRequest() 拿到 ServerHttpRequest 对象,从而可以获取到请求的参数、请求方式、请求头等信息。
注意事项: 类必须是Spring组件;类必须以RoutePredicateFactory作为结尾;类必须继承AbstractRoutePredicateFactory;必须声明静态内部类,声明属性接受配置文件中的信息
@Slf4j
@Component
public class CheckAuthRoutePredicateFactory extends AbstractRoutePredicateFactory<CheckAuthRoutePredicateFactory.Config>
public CheckAuthRoutePredicateFactory()
super(Config.class);
log.info("Loaded RoutePredicateFactory [CheckAuth]");
@Override
public List<String> shortcutFieldOrder()
return Arrays.asList("name");
@Override
public Predicate<ServerWebExchange> apply(Config config)
return exchange ->
if (config.getName().equals("mengmeng"))
return true;
return false;
;
public static class Config
private String name;
public void setName(String name)
this.name = name;
public String getName()
return name;
五、过滤器工厂配置
1.官方文档:https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#gatewayfilter-factories
内置过滤器列表:https://blog.csdn.net/swiftxx/article/details/120545261
2.过滤器有分为三类:
3.过滤器执行顺序:
4.自定义全局过滤器
@Component
public class MyGlobalFilter implements GlobalFilter, Ordered
@Autowired
ObjectMapper objectMapper;
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain)
String token = exchange.getResponse().getHeaders().getFirst("token");//获取第一个名为token的请求头
//无权限
if (StringUtils.isBlank(token))
// 如果消息头中没有 token ,则抛出异常
ServerHttpResponse response = exchange.getResponse();
response.setStatusCode(HttpStatus.UNAUTHORIZED);
response.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
String result = "";
try
Map<String, Object> map = new HashMap<>(16);
map.put("code", HttpStatus.UNAUTHORIZED.value());
map.put("msg", "当前请求未认证,不允许访问");
map.put("data", null);
result = objectMapper.writeValueAsString(map);
catch (JsonProcessingException e)
log.error(e.getMessage(), e);
DataBuffer buffer = response.bufferFactory().wrap(result.getBytes(StandardCharsets.UTF_8));
return response.writeWith(Flux.just(buffer));
//有权限
return chain.filter(exchange);
@Override
public int getOrder()
//值越小,越优先执行
return 1;
局部过滤器与全局过滤器区别:
相关链接:https://blog.csdn.net/qq_43437874/article/details/121626379
全局请求日志打印:https://blog.csdn.net/qq_39529562/article/details/108911943
Gateway实战:SpringCloud-Gateway组件使用
1.什么是服务网关
1.说明
2.为什么需要网关
1.网关可以实现服务的统一管理 2.网关可以解决微服务中通用代码的冗余问题(如权限控制,流量监控,限流等)
3.网关组件在微服务中架构
2.服务网关组件
1.zuul
Zuul is the front door for all requests from devices and web sites to the backend of the Netflix streaming application. As an edge service application, Zuul is built to enable dynamic routing, monitoring, resiliency and security.
原文翻译
zuul版本说明
目前zuul组件已经从1.0更新到2.0,但是作为springcloud官方不再推荐使用zuul2.0,但是依然支持zuul2. springcloud 官方集成zuul文档
2.gateway
This project provides a library for building an API Gateway on top of Spring MVC. Spring Cloud Gateway aims to provide a simple, yet effective way to route to APIs and provide cross cutting concerns to them such as: security, monitoring/metrics, and resiliency.
原文翻译
特性
基于springboot2.x 和 spring webFlux 和 Reactor 构建 响应式异步非阻塞IO模型 动态路由 请求过滤
创建一个新的项目,根据之前写的环境搭建方式
3.开发网关动态路由
网关配置有两种方式一种是快捷方式,一种是完全展开方式
1.创建项目引入网关依赖
< dependency>
< groupId> org.springframework.cloud</ groupId>
< artifactId> spring-cloud-starter-gateway</ artifactId>
</ dependency>
完整的pom.xml
<?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>
< groupId> org.springframework.boot</ groupId>
< artifactId> spring-boot-starter-parent</ artifactId>
< version> 2.2.5.RELEASE</ version>
< relativePath/>
</ parent>
< groupId> com.md</ groupId>
< artifactId> 05-gateway8989</ artifactId>
< version> 0.0.1-SNAPSHOT</ version>
< name> 05-gateway8989</ name>
< description> Demo project for Spring Boot</ description>
< properties>
< java.version> 1.8</ java.version>
< spring-cloud.version> Hoxton.SR6</ spring-cloud.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-test</ artifactId>
< scope> test</ scope>
</ dependency>
< dependency>
< groupId> org.springframework.cloud</ groupId>
< artifactId> spring-cloud-starter-gateway</ artifactId>
</ dependency>
< dependency>
< groupId> org.springframework.cloud</ groupId>
< artifactId> spring-cloud-starter-consul-discovery</ artifactId>
</ dependency>
< dependency>
< groupId> org.springframework.boot</ groupId>
< artifactId> spring-boot-starter-actuator</ artifactId>
</ dependency>
</ dependencies>
< dependencyManagement>
< dependencies>
< dependency>
< groupId> org.springframework.cloud</ groupId>
< artifactId> spring-cloud-dependencies</ artifactId>
< version> ${spring-cloud.version}</ version>
< type> pom</ type>
< scope> import</ scope>
</ dependency>
</ dependencies>
</ dependencyManagement>
< build>
< plugins>
< plugin>
< groupId> org.springframework.boot</ groupId>
< artifactId> spring-boot-maven-plugin</ artifactId>
</ plugin>
</ plugins>
</ build>
</ project>
2.编写网关配置
spring :
application :
name : gateway
cloud :
consul :
host : localhost
port : 8500
discovery :
service-name : ${ spring.application.name}
gateway :
routes :
- id : user_route
uri : http: //localhost: 9999/
predicates :
- Path=/user/**
- id : product_route
uri : http: //localhost: 9998/
predicates :
- Path=/product/**
server :
port : 8989
3.启动gateway网关项目
4.测试网关路由转发
使用之前写的写的,可以看前面几篇文章
java方式配置路由(了解)
环境还是和上面的一样
@Configuration
public class GatewayConfig {
@Bean
public RouteLocator customRouteLocator ( RouteLocatorBuilder builder) {
return builder. routes ( )
. route ( "order_route" , r -> r. path ( "/order/**" )
. uri ( "http://localhost:9997/" ) )
. build ( ) ;
}
}
4.查看网关路由规则列表
1.说明
gateway提供路由访问规则列表的web界面,但是默认是关闭的,如果想要查看服务路由规则可以在配置文件中开启
management :
endpoints :
web :
exposure :
include : "*"
访问路由管理列表地址
3.配置路由服务负载均衡
1.说明
现有路由配置方式,都是基于服务地址写死的路由转发,能不能根据服务名称进行路由转发同时实现负载均衡的呢?
2.动态路由以及负载均衡转发配置
spring :
application :
name : gateway
cloud :
consul :
host : localhost
port : 8500
discovery :
service-name : ${ spring.application.name}
gateway :
routes :
- id : user_route
uri : lb: //users
predicates :
- Path=/user/**
- id : product_route
uri : lb: //products
predicates :
- Path=/product/**
discovery :
locator :
enabled : true
server :
port : 8989
management :
endpoints :
web :
exposure :
include : "*"
此时访问就实现了负载均衡的效果
4.常用路由predicate(断言,验证)
1.Gateway支持多种方式的predicate
After、Before、Between用于商城活动的时候指定日期才能访问
2.使用predicate
spring :
application :
name : gateway
cloud :
gateway :
routes :
- id : product_route
uri : lb: //products
predicates :
- Path=/product/**
filters :
- AddRequestParameter=id, 12
- AddResponseHeader=username, chenyn
5.常用的Filter以及自定义filter
1.作用
当我们有很多个服务时,比如下图中的user-service、order-service、product-service等服务,客户端请求各个服务的Api时,每个服务都需要做相同的事情,比如鉴权、限流、日志输出等。
2.使用内置过滤器
spring :
application :
name : gateway
cloud :
gateway :
routes :
- id : product_route
uri : lb: //products
predicates :
- Path=/product/**
filters :
- AddRequestParameter=id, 12
- AddResponseHeader=username, chenyn
3.使用自定义filter
@Configuration
@Slf4j
public class CustomGlobalFilter implements GlobalFilter , Ordered {
@Override
public Mono < Void > filter ( ServerWebExchange exchange, GatewayFilterChain chain) {
log. info ( "进入自定义的filter" ) ;
if ( exchange. getRequest ( ) . getQueryParams ( ) . get ( "username" ) != null ) {
log. info ( "用户身份信息合法,放行请求继续执行!!!" ) ;
return chain. filter ( exchange) ;
}
log. info ( "非法用户,拒绝访问!!!" ) ;
return exchange. getResponse ( ) . setComplete ( ) ;
}
@Override
public int getOrder ( ) {
return - 1 ;
}
}
自定义全局filter
以上是关于SpringCloud-Gateway实现网关的主要内容,如果未能解决你的问题,请参考以下文章
SpringCloud-Gateway 网关路由断言过滤
Gateway实战:SpringCloud-Gateway组件使用
搭建SpringCloud微服务框架:SpringCloud-Gateway 服务网关处理
搭建SpringCloud微服务框架:SpringCloud-Gateway 服务网关处理
黑马学SpringCloud-Gateway
深入浅出SpringCloud原理及实战「SpringCloud-Gateway系列」微服务API网关服务的Gateway全流程开发实践指南(入门篇)