网关

2024-11-23 13:18

网关的基本概念

SpringCloudGateway网关是所有微服务的统一入口。

它的主要作用是:

  • 反向代理(请求的转发)

  • 路由和负载均衡

  • 身份认证和权限控制

  • 对请求限流

相比于Zuul的优势:

SpringCloudGateway基于Spring5中提供的WebFlux,是一种响应式编程的实现,性能更加优越。

Zuul的实现方式比较老式,基于Servlet的实现,它是一种阻塞式编程,在高并发下性能性能不佳。

拓展:

其实Nginx也可以作为网关,但是要使用Nginx自主实现网关的相关功能,还需要借助lua脚本语言,学习成本是比较高的,现在一般也不会使用它来做网关,但是只按性能来讲Nginx,性能是最高的。

SpringCloudGateway架构图:

图片


微服务只接收来自网关的请求,而其它直接访问微服务本身的请求拒绝。

这样可以极大保护微服务免受不法侵害。

同时在请求压力激增时,可以实施服务限流,保护微服务集群。

基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

  • 项目地址:https://github.com/YunaiV/ruoyi-vue-pro

  • 视频教程:https://doc.iocoder.cn/video/

SpringBoot中配置GateWay

引入GateWay的Maven依赖

<!--网关 起步依赖-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!--nacos服务发现 起步依赖-->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

配置application.yml文件

server:
  port: 10086   # 网关端口
spring:
  application:
    name: gateway # 服务名称
  cloud:
    nacos:
      server-addr: localhost:8848    # nacos 地址
    gateway:
      routes:         # 网关路由配置
        - id: user-service      # 路由id,自定义,只要唯一即可
          # uri: http://127.0.0.1:8081   # 路由的目标地址 (直接写死地址的方式,不推荐)
          uri: lb://userservice    # 路由的目标地址 lb是负载均衡,后面跟服务名称(推荐)
          predicates:       # 路由断言,判断请求是否符合路由规则的条件
            - Path=/user/**      # 按照路径匹配,以/user/开头的请求就符合要求
        - id: card-service
          uri: lb://cardservice
          predicates:
            - Path=/card/**

gateway配置中的注意点:

1.routes 后面的路由可以配置多个,相当于配置个数组,一个-开头的配置就是其中的一个数组元素。

2.uri为什么选择以服务名+负载均衡的方式?

主要是写死地址的话,今后如果userservice的地址变了,那么又要去修改yml配置文件。而lb://userservice可以让程序员一眼认出这是哪个微服务,以后地址变了也无需修改yml配置文件。

上述配置详解:

/user/**开头的请求,代理到lb://userservice

/card/**开头的请求,代理到lb://cardservice

lb是负载均衡,根据服务名拉取服务列表,实现负载均衡。

  • http://127.0.0.1:10086/user/99 就算是/user/**开头的请求,不要把协议、ip和端口计算在内。

  • 有多少个需要配置的路由,都按上面的格式配置即可

基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

  • 项目地址:https://github.com/YunaiV/yudao-cloud

  • 视频教程:https://doc.iocoder.cn/video/

GateWay路由配置详解

路由主要有四个配置:

  • 路由id(id)

  • 路由目标(uri)

  • 路由断言(predicates):判断路由的规则,

  • 路由过滤器(filters):对请求或响应做处理

路由id

当前路由的唯一标识。

路由目标

路由的目标地址,http代表固定地址,lb代表根据服务名负载均衡。

一般都不会选择写死http固定地址的方式。而是选择可维护性更强的lb根据服务名负载均衡的方式。

具体优势如上所言。

路由断言

路由断言主要用来判断路由的规则。

配置文件中写的断言规则只是字符串,这些字符串会被Predicate Factory读取并处理。

例如Path=/user/**是按照路径匹配,这个规则是由org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactory类来处理。

像这样的断言工厂在SpringCloudGateway还有十几个:

名称

说明

示例

After

是某个时间点后的请求

- After=2022-01-20T14:32:27.789-07:00[Asia/Shanghai]

Before

是某个时间点之前的请求

- Before=2022-04-13T15:14:47.433+08:00[Asia/Shanghai]

Between

是某两个时间点之前的请求

- Between=2021-01-20T17:42:47.789-07:00[Asia/Shanghai], 2023-01-21T17:42:47.789-07:00[Asia/Shanghai]

Cookie

请求必须包含某些cookie

- Cookie=chocolate

Header

请求必须包含某些header

- Header=asd, cas

Host

请求必须是访问某个host(域名)

- Host=baidu.com, jd.com

Method

请求方式必须是指定方式

- Method=GET,POST

Path

请求路径必须符合指定规则

- Path=/user/{params},/card/**

Query

请求参数必须包含指定参数

- Query=name, Jack

RemoteAddr

请求者的ip必须是指定范围

- RemoteAddr=192.168.1.1/24

Weight

权重处理


实际使用时,根绝业务要求选择使用即可。

不过一般来讲,最常用的是使用Path这种断言工厂,仅用它就能满足常见的需求了。

关于Path断言工厂的补充:

  • Path=/card/**代表 以/card/路径开头的多级路径请求,这么写多级路径请求和一级路径请求都生效。

  • Path=/card/*代表 以/card/路径开头的一级路径请求,这么写多级路径请求将不会生效。

断言工厂官方文档:

  • https://docs.spring.io/spring-cloud-gateway/docs/3.1.4-SNAPSHOT/reference/html/#gateway-request-predicates-factories

今后如果有复杂的断言工厂配置,可以参照官网文档上的例子去实现。

路由过滤器(filters)

路由过滤器对请求或响应做处理。

图片

客户端请求先找到路由,路由匹配时经过过滤器层层筛选,最终访问到微服务。

当然微服务的请求反悔时,也会经过过滤器的筛选,只不过我们一般只对请求过滤,而不会对响应过滤。

SpringCloudGateWay目前已经提供了34种不同的过滤器工厂。

常用的几个有:

名称

说明

AddRequestHeader

给当前请求添加一个请求头

RemoveRequestHeader

移除请求中的一个请求头

AddResponseHeader

给响应结果中添加一个响应头

RemoveResponseHeader

从响应结果中移除有一个响应头

RequestRateLimiter

限制请求的流量

请求头过滤器配置示例(局部过滤器)

spring:
  cloud:
    gateway:
      routes:
      - id: user-service 
        uri: lb://userservice 
        predicates: 
        - Path=/user/** 
        filters:         # 过滤器配置
        - AddRequestHeader=token, test # 添加请求头

上述过滤器的含义:

给所有进入userservice的请求添加一个请求头。

请求头的key为token,value为test。

由于当前前过滤器写在微服务的userservice路由下,因此仅仅对访问微服务userservice的请求有效。

默认过滤器配置示例(全局过滤器)

spring:
  cloud:
    gateway:
      routes:
        - id: user-service 
          uri: lb://userservice 
          predicates: 
          - Path=/user/**
      default-filters:      # 默认过滤器配置
        - AddRequestHeader=token, test  # 添加请求头

default-filters的配置和routes平级。

只要配置在default-filters下面的过滤器,会对routes配置的所有路由都生效。

过滤器工厂官方文档:

  • https://docs.spring.io/spring-cloud-gateway/docs/3.1.4-SNAPSHOT/reference/html/#gateway-request-predicates-factories

今后如果有复杂的断言工厂配置,可以参照官网文档上的例子去实现。

自定义全局路由过滤器

有时候SpringCloudGateWay提供的过滤器工厂不能满足自己的要求。

可能有时候需要在过滤时做一些其它的逻辑操作。

那么这时候可以选择使用java代码自定义全局过滤器。

代码示例:

@Component
public class GateWayFilter implements GlobalFilter, Ordered {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

        // 1.获取请求参数 
        //1.这里的request并不是servlet中的request  
        //2.返回值是一个多键的map集合、也就是说这个map集合的键可以重复
        MultiValueMap<String, String> params = exchange.getRequest().getQueryParams();
        // 2.获取userName参数
        String userName = params.getFirst("userName");
        // 3.校验
        if ("root".equals(userName)) {
            // 放行
            return chain.filter(exchange);
        }
        // 4.拦截
        // 4.1.禁止访问,设置状态码
        exchange.getResponse().setStatusCode(500);
        // 4.2.结束处理
        return exchange.getResponse().setComplete();
    }

    @Override
    public int getOrder() {
        return -1;
    }
}

当有多个过滤器时,Order的值决定了过滤器的执行顺序。

数值越大优先级越低, 负的越多, 优先级越高。

设置Order的值有两种方式:

1. 实现Ordered接口,并且重写getOrder方法

@Component
public class GateWayFilter implements GlobalFilter, Ordered {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

    }

    @Override
    public int getOrder() {
        return -1;
    }
}

2. 使用@Order注解

@Order(-1)
@Component
public class GateWayFilter implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

    }
}

过滤路由过滤器的执行顺序

过滤器的种类

SpringCloudGateWay中,有三种过滤器:

  • 默认过滤器default-filters

  • 只对具体某个路由生效的局部过滤器filters

  • 使用java代码编写的全局过滤器GlobalFilter

过滤器的执行顺序

图片

由上图知过滤器的执行顺序为:默认过滤器 → 当前路由过滤器 → 全局过滤器。

相关文章
热点文章
精彩视频
Tags

站点地图 在线访客: 今日访问量: 昨日访问量: 总访问量: