百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程网 > 正文

SpringCloud学习笔记(四)

yuyutoo 2025-02-15 18:05 3 浏览 0 评论

7.GateWay网关

7.1. 简介

  • Spring Cloud Gateway是Spring Cloud生态系统中的网关组件,用于提供路由、过滤、限流等功能。Spring Cloud Gateway基于Spring6、Spring Boot3和Project Reactor等技术。它旨在为微服务架构提供简单有效的统一API路由管理。
  • 核心是一系列的过滤器,通过这些过滤器可以将客户端的请求转发到对应的微服务。是加在整个微服务最前沿的防火墙和代理期,隐藏微服务节点IP端口信息,加强安全保护。
  • Spring Cloud Gateway本身也是微服务,需要注册进服务注册中心。

7.2.网关定位

  • GateWay VS Nginx:Nginx位于客户端和服务器之间,用于反向代理和负载均衡,而Spring Cloud Gateway位于微服务和Nginx之间,用于路由、过滤和限流。

7.3. GateWay三大核心

  • 路由:路由是GateWay中最基础的功能,它将客户端的请求转发到对应的微服务。由ID、URI、断言、过滤器组成,如果断言为true则匹配该路由。
  • 断言:断言是GateWay中用于判断请求是否满足特定条件的机制,开发人员可以匹配HTTP请求中的所有内容(例如请求头或请求参数),只有满足条件的请求才会被转发到对应的微服务。
  • 过滤:过滤是GateWay中用于处理请求和响应的机制,它可以在请求被路由前或者之后对请求进行处理。

7.4. GateWay工作流程

  • 客户端向GateWay发送请求,GateWay根据请求的路径和路由规则,将请求发送到WebHandler。Handler通过指定的过滤器链来将请求发送给对应的微服务。
  • 过滤器可能会在发送代理之前或之后执行业务逻辑。
  • "pre"类型的过滤可以做参数校验、权限校验、流量监控、日志输出、协议转换等,
  • "post"类型的过滤器可以做响应内容、响应头的修改,日志的输出,流量监控等有着非常重要的作用。

7.5. GateWay路由配置

  • 配置文件
server:
  port: 9527

spring:
  application:
    name: cloud-gateway
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
  gateway:
    routes:
      - id: payment_route1
#          uri: http://localhost:9001
        uri: lb://nacos-pay-provider #动态路由,直接寻找微服务,支持负载均衡
        predicates:
          - Path=/pay/gateway/get/**
      - id: payment_route2
#          uri: http://localhost:9001
        uri: lb://nacos-pay-provider
        predicates:
          - Path=/pay/gateway/info/**
  • openfeign配置
@FeignClient(value = "cloud-gateway") //微服务对应网关
public interface PayFeignApi {

    @GetMapping("/pay/nacos/{id}")
    public ResultData getPayInfo(@PathVariable("id") Integer id);

    @GetMapping(value="/pay/micrometer/{id}")
    public String myMicrometer(@PathVariable("id") Integer id);

    @GetMapping("/pay/gateway/get/{id}")
    public ResultData getById(@PathVariable("id") Integer id);

    @GetMapping("/pay/gateway/info")
    public ResultData getInfo();
}

客户端发送请求后,openfeign会寻找对应网关,成功访问9527端口下的 /pay/gateway/get/**/pay/gateway/info/**,请求会被转发到9001端口。

7.6. GateWay断言

  • Path:路径断言,用于匹配请求路径。例如,Path=/pay/gateway/get/**表示匹配所有以/pay/gateway/get/开头的请求路径。
  • After:时间断言,用于匹配请求时间。例如,After=2022-01-01T00:00:00.000+0000表示匹配在2022年1月1日00:00:00之后发出的请求。
  • Before:时间断言,用于匹配请求时间。例如,Before=2022-01-01T00:00:00.000+0000表示匹配在2022年1月1日00:00:00之前发出的请求。
  • Cookie:Cookie断言,用于匹配请求中的Cookie。例如,Cookie=username,zzyy表示匹配Cookie中包含username=zzyy的请求。
  • Header: Header断言,用于匹配请求头。例如,Header=X-Request-Id, \d+表示匹配请求头中包含X-Request-Id且其值为数字的请求。
  • Host: 匹配请求的主机名。例如,Host=**.zzyy.com表示匹配所有以.zzyy.com结尾的主机名。
  • Query: 匹配请求的查询参数。例如,Query=username, \d+表示匹配查询参数中包含username=整数的请求。例如请求为/pay/gateway/get/1?username=1,则匹配成功。
  • RemoteAddr: 匹配请求的远程地址。例如,RemoteAddr=192.168.1.1/24表示匹配来自192.168.1.0/24网段的请求。
  • Metthod: 匹配请求的方法。例如,Method=GET表示匹配GET请求。

示例代码:

server:
  port: 9527

spring:
  application:
    name: cloud-gateway
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
  gateway:
    routes:
      - id: payment_route1
#          uri: http://localhost:9001
        uri: lb://nacos-pay-provider #动态路由,直接寻找微服务,支持负载均衡
        predicates:
          - Path=/pay/gateway/get/**
          - After=2025-02-05T15:08:30.031606300+08:00[Asia/Shanghai]
          - Cookie=username,zzyy
          - Header=X-Request-Id, \d+
          - Host=**.zzyy.com
          - Query=username, \d+
          - RemoteAddr=192.168.83.1/24
          - Method=GET, POST
      - id: payment_route2
#          uri: http://localhost:9001
        uri: lb://nacos-pay-provider
        predicates:
          - Path=/pay/gateway/info/**

7.7. GateWay自定义断言

7.7.1. 自定义步骤

  1. 新建类名以RoutePredicateFactory结尾,继承AbstractRoutePredicateFactory
  2. 重写apply方法
  3. 新建apply方法所需要的静态内部类MyRoutePredicateConfig,这个是路由断言规则
  4. 空参构造方法,内部调用super
  5. 重写apply方法第二版

7.7.2. 代码实现

  1. 编写自定义断言类
@Component
public class MyRoutePredicateFactory extends AbstractRoutePredicateFactory {


    public MyRoutePredicateFactory() {
        super(MyRoutePredicateFactory.Config.class);
    }

    @Override
    public Predicate apply(Config config) {
        return new Predicate() {
            @Override
            public boolean test(ServerWebExchange serverWebExchange) {
                String userType = serverWebExchange.getRequest().getQueryParams().getFirst("userType");
                if (userType == null) {
                    return false;
                }
                if (userType.equalsIgnoreCase(config.getUserType())) {
                    return true;
                }
                return false;
            }
        };
    }

    public static class Config {
        @Setter@Getter@NotEmpty
        private String userType; //用户等级
    }
    # 支持短格式书写配置
    @Override
    public List shortcutFieldOrder() {
        return Collections.singletonList("userType");
    }
}
  1. 编写配置文件
server:
  port: 9527

spring:
  application:
    name: cloud-gateway
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
  gateway:
    routes:
      - id: payment_route1
#          uri: http://localhost:9001
        uri: lb://nacos-pay-provider #动态路由,直接寻找微服务,支持负载均衡
        predicates:
          - Path=/pay/gateway/get/**
#            - name: My
#              args:
#                userType: diamond
          - My=diamond

7.8. GateWay过滤器

7.8.1. 过滤器的作用

  • 过滤器可以在请求被路由之前或之后对请求进行修改,或者对路由的请求响应进行修改。

7.8.2. GateWay内置过滤器

  • 过滤器类型 GatewayFilter GlobalFilter 自定义Filter
  • 过滤器作用范围 单个路由 全局

7.8.3. GateWay常用内置过滤器

1.RequestHeader:

  • AddRequestHeader:添加请求头
  • RemoveRequestHeader:移除请求头
  • SetRequestHeader:设置请求头

2.RequestParameter:

  • AddRequestParameter:添加请求参数
  • RemoveRequestParameter:移除请求参数
  • SetRequestParameter:设置请求参数

3.ResponseHeader:

  • AddResponseHeader:添加响应头
  • RemoveResponseHeader:移除响应头
  • SetResponseHeader:设置响应头

4.Path:

  • PrefixPath:路径前缀
  • SetPath:设置替换路径
  • RedirectTo:重定向

配置文件:

spring:
  application:
    name: cloud-gateway
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
    gateway:
      routes:
        - id: payment_route1
#          uri: http://localhost:9001
          uri: lb://nacos-pay-provider #动态路由,直接寻找微服务,支持负载均衡
          predicates:
            - Path=/pay/gateway/get/**
            - After=2025-02-05T15:08:30.031606300+08:00[Asia/Shanghai]
            - Cookie=username,zzyy
            - Header=X-Request-Id, \d+
            - Host=**.zzyy.com
            - Query=username, \d+
#            - RemoteAddr=192.168.83.1/24
            - Method=GET, POST
#            - name: My
#              args:
#                userType: diamond
            - My=diamond
        - id: payment_route2
#          uri: http://localhost:9001
          uri: lb://nacos-pay-provider
          predicates:
            - Path=/pay/gateway/info/**
        - id: payment_route3
            #          uri: http://localhost:9001
          uri: lb://nacos-pay-provider
          predicates:
            - Path=/pay/gateway/filter/**
#            - Path=/gateway/filter/**
#            - Path=/XYZ/abc/{segment}
          filters:
            - RedirectTo=302,http://www.baidu.com #302错误进行跳转
#            - SetPATH=/pay/gateway/{segment} # 上面配置的/XYZ/abc会被替换为当前路径
#            - PrefixPath= /pay # 前缀由配置统一管理
#            - AddRequestHeader=X-Request-yeffky,yeffky
#            - RemoveRequestHeader=cookie
#            - SetRequestHeader=X-Request-Id,123456
#            - AddRequestParameter=customerId,9527001
#            - RemoveRequestParameter=customerName
#            - AddResponseHeader=X-Response-Id,BlueResponse
#            - RemoveResponseHeader=Content-Type
#            - SetResponseHeader=Date,2099-11-11

7.8.4.自定义过滤器

  • 自定义全局Filter:统计接口调用耗时
@Component
@Slf4j
public class MyGlobalFilter implements GlobalFilter, Ordered {

    public static final String BEGIN_VISIT_TIME = "begin_visit_time";
    @Override
    public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        exchange.getAttributes().put(BEGIN_VISIT_TIME, System.currentTimeMillis());
        return chain.filter(exchange).then(Mono.fromRunnable(()->{
            Long beginVisitTime = exchange.getAttribute(BEGIN_VISIT_TIME);
            if (beginVisitTime != null) {
                log.info("访问接口主机:" + exchange.getRequest().getURI().getHost());
                log.info("访问接口端口:" + exchange.getRequest().getURI().getPort());
                log.info("访问接口URL:" + exchange.getRequest().getURI().getPath());
                log.info("访问接口参数:" + exchange.getRequest().getURI().getRawQuery());
                log.info("访问接口时长:" + (System.currentTimeMillis() - beginVisitTime) + "ms");
                log.info("=================");
                System.out.println();
            }
        }));
    }

//    数字越小,优先级越高
    @Override
    public int getOrder() {
        return 0;
    }
}
  • 自定义条件Filter
  • 配置类
@Component
public class MyGatewayFilterFactory extends AbstractGatewayFilterFactory {

    public MyGatewayFilterFactory() {
        super(MyGatewayFilterFactory.Config.class);
    }


    @Override
    public GatewayFilter apply(Config config) {
        return new GatewayFilter() {
            @Override
            public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {
                ServerHttpRequest request = exchange.getRequest();
                System.out.println("进入了自定义网关过滤器:" + config.getStatus());
                if (request.getQueryParams().containsKey(config.getStatus())) {
                    return chain.filter(exchange);
                } else {
                    exchange.getResponse().setStatusCode(HttpStatus.BAD_GATEWAY);
                    return exchange.getResponse().setComplete();
                }

            }
        };
    }

    public static class Config {
        @Getter @Setter
        private String status;
    }

    @Override
    public List shortcutFieldOrder() {
        return Arrays.asList("status");
    }
}

-yml配置

spring:
  cloud:
    gateway:
      routes:
        - id: payment_route3
            #          uri: http://localhost:9001
          uri: lb://nacos-pay-provider
          predicates:
            - Path=/pay/gateway/filter/**
          filters:
            - My=yeffky #需要有yeffky这个键,而非键值对为"status: yeffky"

相关推荐

微软Win10/Win11版Copilot上线:支持OpenAI o3推理模型

IT之家4月3日消息,科技媒体WindowsLatest昨日(4月2日)发布博文,报道称Windows10、Windows11新版Copilot应用已摘掉Beta帽...

WinForm 双屏幕应用开发:原理、实现与优化

在当今的软件开发领域,多屏幕显示技术的应用越来越广泛。对于WinForm应用程序来说,能够支持双屏幕显示不仅可以提升用户体验,还能满足一些特定场景下的业务需求,比如在演示、监控或者多任务处理等场景...

推荐一个使用 C# 开发的 Windows10 磁贴美化小工具

...

OpenJDK 8 安装(openjdk 8 windows)

通常OpenJDK8和11都能互相编译和通用。我们建议使用11,但是如果你使用JDK8的话也是没有问题的。建议配置使用OpenJDK,不建议使用OracleJDK,主要是因为版...

基于 Linux 快速部署 OpenConnect VPN 服务(ocserv 实战指南)

一、前言在如今远程办公和内网穿透需求日益增长的背景下,搭建一套安全、稳定、高效的VPN系统显得尤为重要。OpenConnectServer(ocserv)是一个开源、高性能的VPN服务端软件...

巧妙设置让Edge浏览器更好用(edge怎么设置好用)

虽然现在新版本的Edge浏览器已经推出,但是毕竟还处于测试的状态中。而Win10系统里面自带的老版Edge浏览器,却越来越不被人重视。其实我们只需要根据实际情况对老版本的Edge浏览器进行一些简单的设...

WPF做一个漂亮的登录界面(wpf页面设计)

...

微软开源博客工具Open Live Writer更新:多项Bug修复

OpenLiveWriter前身是WindowsLiveWriter,是微软WindowsLive系列软件之一,曾经是博主们非常喜爱的一款所见即所得博文编辑工具,支持离线保存,还支持图像编辑...

基于OpenVINO的在线设计和虚拟试穿 | OPENAIGC大赛企业组优秀作品

在第二届拯救者杯OPENAIGC开发者大赛中,涌现出一批技术突出、创意卓越的作品。为了让这些优秀项目被更多人看到,我们特意开设了优秀作品报道专栏,旨在展示其独特之处和开发者的精彩故事。...

C#开源免费的Windows右键菜单管理工具

...

Windows10或11中隐藏的功能,用它再也不用担心电脑中病毒!

...

Python open函数详解(python open函数源码)

演示环境,操作系统:Win1021H2(64bit);Python解释器:3.8.10。open是Python的一个内置函数,一般用于本地文件的读写操作。用法如下。my_file=open(fi...

Windows 11 安装 Docker Desktop(Windows 11 安装助手 Windows 易升 关系)

...

Windows 11 新版发布:屏幕亮度自适应控制,小组件界面重新设计!

...

世界上最好用的Linux发行版之一,OpenSUSE安装及简单体验

背景之前无意在论坛里看到openSUSE的Linux发行版,被称为世界上最好用的Linux发行版之一(阔怕),一直想体验一下,于是这期做一个安装和简单体验教程吧。...

取消回复欢迎 发表评论: