SpringCloud Gateway
SpringCloud Gateway由来: Cloud全家桶中有个很重要的组件就是网关,在1.x版本中都是采用的Zuul网关;但在2.x版本中,zuul的升级-直跳票,SpringCloud最后自 己研发了一个网关替代Zuul,那就是SpringCloud Gateway一句话: Gateway是原zuul1.x版的替代。
Gateway介绍
SpringCloud Gateway作为Spring Cloud生态系统中的网关,目标是替代Zuul,在Spring Cloud 2.0以上版本中,没有对新版本的Zuul 2.0以上最新高性能版本进行集成,仍然还是使用的Zuul 1.x非Reactor模式的老版本。而为了提升网关的性能,SpingCloud Gateway是基于WebFlux框架实现的,而WebFlux框架底层则使用了高性能的Reactor模式通信框架Netty。
Spring Cloud Gateway的目标提供统一的路由方式且基于 Filter 链的方式提供了网关基本的功能,例如:安全,监控/指标,和限流。
网关在程序中的位置
三大特性
路由:路由是构建网关的基本模块,它由ID,目标URI,一系列的断言和过滤器组成,如果断言为true则匹配该路由
断言:参考的是Java8的java.util.function.Predicate。开发人员可以匹配HTTP请求中的所有内容(例如请求头或请求参数),如果请求与断言相匹配则进行路由
过滤:指的是Spring框架中GatewayFilter的实例,使用过滤器,可以在请求被路由前或者之后对请求进行修改。
总结:
web请求,通过-些匹配条件,定位到真正的服务节点。并在这个转发过程的前后,进行一些精细化控制。
predicate就是我们的匹配条件。而filter,就可以理解为-个无所不能的拦截器。有了这两个元素,再加上目标uri,就可以实现个具体的路由了
客户端向Spring Cloud Gateway发出请求。然后在Gateway Handler Mapping中找到与请求相匹配的路由,将其发送到Gateway
Web Handler。Handler再通过指定的过滤器链来将请求发送到我们实际的服务执行业务逻辑,然后返回。过滤器之间用虚线分开是因为过滤器可能会在发送代理请求之前( “pre” )或之后( “post” )执行业务逻辑。
Filter在"pre" 类型的过滤器可以做参数校验、权限校验、流量监控、日志输出、协议转换等,
在"post"类型的过滤器中可以做响应内容、响应头的修改,志的输出,流量监控等有着非常重要的作用。
下面是简单的一个gateway服务
没有使用到断路器过滤等操作
maven
1.引入gateway依赖
2.映入注册中心:可以是eureka也可以是其他的
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>cloud2021</artifactId>
<groupId>com.yu.springcloud</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cloud-gateway9527</artifactId>
<dependencies>
<!--eureka-client-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>com.yu.springcloud</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
yml
1.配置gateway相关内容
- 路由
- 断言
- 过滤
- 可以配置默认的过滤器
spring: cloud: gateway: default-filters: - AddResponseHeader=X-Response-Default-Red, Default-Blue - PrefixPath=/httpbin
server:
port: 9527
spring:
application:
name: cloud-gateway
cloud:
gateway:
routes:
- id: payment # 路由id,没有固定的要求,但是必须唯一
uri: lb://CLOUD-PAYMENT-SERVICE #配置后提供服务的路由地址,这里通过微服务名称开启服务名
predicates:
- Path=/payment/get/** #断言(有很种断言,可以进行多个断言匹配,就是相当于多个条件&&的关系),路径匹配成功之后进行路由
- After=2017-01-20T17:42:47.789-07:00[America/Denver] #这个可以在2017年1月20日17:42(丹佛)之后提出的任何请求
filters: #可能我们一般不使用它,我们可能会使用一个全局的filters,
- AddRequestHeader=X-Request-red, blue #这个清单为所有匹配请求的下游请求的头添加了 X-Request-red: blue 头
discovery:
locator:
enabled: true #开启通过微服务名称访问访问,结合ribbon可以实现负载均衡的作用
eureka:
client:
fetchRegistry: true #是否从Eureka注册中心抓取已有的服务,默认是true,
#但是集群必须是true才可以配合ribbon做负载均衡
register-with-eureka: true #向eureka注册中心注册自己
service-url: #eureka注册中心地址
defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka #集群配置,往多个注册中心都注册
instance:
instance-id: gateway9527 #设置Eureka注册中心web页面中Status中名称
prefer-ip-address: true # 是否显示ip地址
lease-renewal-interval-in-seconds: 1 #Eureka客户端向服务端发送心跳的时间间隔,单位为秒(默认是30秒)
lease-expiration-duration-in-seconds: 2 #Eureka服务端在收到最后一次心跳后等待时间上限,单位为秒(默认是90秒),超时将剔除服务
全局的过滤器类配置
1.配置了请求参数中不带username的不允许访问
package com.yu.springcloud.filter;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
/**
* @author 小鱼
* @version 1.0
* @date 2021/8/2 10:52 下午
* 使用全局的过滤器
* 1.实现GlobalFilter和Ordered
*/
@Component
@Slf4j
public class MyGlobalFilter implements GlobalFilter, Ordered {
@Override
public int getOrder() {
return 0;
}
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
//判断请求里面是否包含username参数,没有就不允许继续请求
String username = exchange.getRequest().getQueryParams().getFirst("username");
if(StrUtil.isEmpty(username)){
log.info("用户名为null,不允许操作");
exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);
return exchange.getResponse().setComplete();
}
return chain.filter(exchange);
}
}
个人总结
经过查看官方文档:过滤器(filter)配置是可以配置断路器的,当然如果你断路器已经在自己的服务配置好了,不需要在网关的配置文件中配置这个对象。
ps:博客内容参考周阳老师视频:https://www.bilibili.com/video/BV18E411x7eT?p=74
springcloud官网:https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#fallback-headers