Spring cloud - gateway

news2025/1/18 9:43:45

什么是Spring Cloud Gateway

先去看下官网的解释:

This project provides an API Gateway built on top of the Spring Ecosystem, including: Spring 6, Spring Boot 3 and Project Reactor. 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.

Spring提供了一个API网关,基于Spring 6、Spring Boot 3以及Project Reactor。目标是提供一个简单、有效的方式进行API路由,以及安全、监控等众多项目的公共需求。

这个描述其实很简单,但是我们需要了解一个背景知识:安全、权限、监控、系统弹性等需求是每一个系统或模块的公共需求,这类需求的解决方案可以是在每一个模块中处理,但显而易见的弊端是相同的处理逻辑会在每一个模块中重复实现,增加系统的复杂性,降低系统的可维护性。

Spring Cloud Gateway可以完美解决以上问题,集中处理鉴权、安全、监控、流量监控等公共需求,并可实现对最终用户隐藏真实的业务调用接口,避免业务接口的细节的对外暴露。

术语

  1. route:路由,是网关的基本概念,由路由ID、目标URI、一组断言以及一组过滤器组成,断言判断为true则表示当前路由被匹配。
  2. Predicate:断言,是一个java 8函数式断言接口,输入是Spring framework的ServerWebExchange。由于ServerWebExchange包含了http request以及http response,所以,断言可以基于任何http request设置,比如http header、http请求参数等等。
  3. Filter:过滤器,Spring Cloud Gateway基于GatewayFilter接口、通过特定的过滤器工厂创建的一系列实例,在请求发送给网关后的服务前、或者调用网关后面的服务后执行,从而可以实现修改请求参数及返回信息等增强功能。

Spring Cloud Gateway如何工作

下图展示了Spring Cloud网关的工作原理:
在这里插入图片描述
客户端发送请求给spring cloud网关而不是真实的业务服务端(这种情况下网关的作用类似于反向代理nginx),网关的Gateway Handle Mapping判断Predicate符合的话在转发请求给Gateway Web Handle,之后Gateway Web Handle调用Filters处理后将请求发送给被代理的各业务服务(网关uri定义的)。

有没有发现上图比较眼熟?是不是和Servlet+Spring MVC处理请求的过程很类似?

Filters组成filters chain,像剥洋葱一样逐个调用,先执行各过滤器的before逻辑,调用完Proxied Service之后再执行after逻辑。

引入Spring Cloud Gateway

我们在前面案例的基础上,增加Spring Cloud Gateway模块。

新建一个Springgateway模块:
在这里插入图片描述

项目中引入Spring 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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>springCloud</artifactId>
        <groupId>com.example</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>springgateway</artifactId>

    <dependencies>
        <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>
    </dependencies>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
    </properties>

</project>

注意Spring Cloud Gateway不能是SpringMVC项目,所以pom文件中不能引入spring-boot-starter-web,否则项目启动不了。

然后配置yam文件:

spring:
  application:
    name: spring-gateway
  cloud:
    gateway:
      routes:
        - id: path_route
          uri: http://127.0.0.1:9090
          predicates:
            - Path=/order/*
eureka:
  client:
    service-url: # eureka service
      defaultZone: http://127.0.0.1:10086/eureka/
server:
  port: 9095

在applicaton.yml文件中配置一个route:
id: 任意一个名字就可以,但是需要唯一。
uri:断言判断匹配成功之后的路由地址,指向proxied service
predicates:断言,配置为Path断言,判断请求路径中是否包含/order

Spring Cloud Gateway提供了很多断言工厂:
在这里插入图片描述
我们的案例使用path断言工厂,path断言工厂负责根据请求路径进行匹配。

我们把Spring Cloud Gateway也配置为Eureka客户端,放在注册中心统一管理,后面我们可以看到,Spring Cloud Gateway支持通过注册中心进行路由。

上面的配置很简单,判断请求路径中如果包含/order的话,将请求路由到http://127.0.0.1:9090去处理。

验证

依次启动Eureka、orderservice、orderservice以及springGateway service:
在这里插入图片描述
gateway启动在端口9095,端都9090是orderservice。

看一下10086端口的Eureka注册中心:

在这里插入图片描述
发现orderservice、userservice以及spring-gateway都已经在Eureka注册中心完成注册。

接下来访问9095端口的gateway服务:
在这里插入图片描述
说明Spring Cloud Gateway已经开始正常工作了,能够路由的orderservice服务。

改造orderservice服务

上面路由配置直接指向了 http://127.0.0.1:9090,只能访问到指定的应用,无法访问到spring loadbalance提供的负载均衡服务。

下面我们尝试通过注册中心访问服务、并享受到spring loadbalance提供的负载均衡服务。

前面的案例访问orderservice后,会通过orderservice访问userservice的服务。现在我们是为了验证gateway,简单起见,我们暂时去掉userservice,通过网关gateway访问orderservice、由orderservice直接提供服务,不再访问userservice了。

为此,简单改造一下orderservice的orderController,不再调用userservice了,直接返回当前orderservice的端口:

package com.example.controller;

@RestController
@RequestMapping("/order")
@Slf4j
public class OrderController {

    @Value("${server.port}")
    private String serverPort;

    @Autowired
    OrderService orderService;
    @Autowired
    FallbackHandle fallbackHandle;
    @GetMapping("/getOrder")

    @HystrixCommand(fallbackMethod = "fallback",commandProperties = {
            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "5000")
    })
    public String getOrder(){
        log.info("Come here to get Order....123===");
        return "order service from:"+serverPort;
//        return orderService.getOrder();
    }

    public String fallback(){
        return "orderService服务异常";
    }

}

重新启动服务,访问网关:
在这里插入图片描述
说明网关服务、以及改造后的orderservice都能正常工作了。

增加一个orderservice服务

copy一份orderservice的配置,在9091端口再启动一个orderservice服务:
在这里插入图片描述
启动服务后,检查Eureka注册中心:
在这里插入图片描述
发现9090/9091端口分别由一个orderservice注册到了Eureka注册中心。

通过注册中心配置网关

下面我们修改一下网关服务的配置:

spring:
  application:
    name: spring-gateway
  cloud:
    gateway:
      routes:
        - id: path_route
          uri: lb://orderservice
          predicates:
            - Path=/order/*
eureka:
  client:
    service-url: # eureka service
      defaultZone: http://127.0.0.1:10086/eureka/
server:
  port: 9095

断言匹配成功后,通过Eureka注册中心以及loadbalance路由到orderservice服务。

启动服务,访问验证:
在这里插入图片描述
在这里插入图片描述
可以发现,不需要太多的配置,Spring Cloud Gateway已经可以通过Spring Eureka注册中心获取到注册的服务、并通过Spring LoadBalance负载均衡策略访问到服务了。

通过简单的配置,我们现在的应用其实已经具备了微服务的注册中心、负载均衡、网关等强大能力了!

过滤器

过滤器的作用原理我们在开篇说过了,过滤器可以修改请求的request或response,或者对请求进行某种控制,从而实现众多附加功能,比如修改头信息、修改请求参数、权限验证、超时控制等等。

Spring Cloud Gateway的过滤去分为路由过滤器和全局过滤器,路由过滤器作用范围是当前匹配到的路由,全局过滤器的作用范围是全局(所有路由)。

Spring Cloud Gateway提供了众多内置的路由过滤器:
在这里插入图片描述
以及内置的全局过滤器:
在这里插入图片描述
当请求匹配之后,路由过滤器以及全局过滤器会被装配成filterChain,filterChain装配的过程中,过滤器会按照org.springframework.core.Ordered接口进行排序,按顺序调用。

As Spring Cloud Gateway distinguishes between “pre” and “post” phases for filter logic execution (see How it Works), the filter with the highest precedence is the first in the “pre”-phase and the last in the “post”-phase.

高优先级的过滤器意味着早一些被 pre-phase阶段调用、晚一些被post-phase阶段调用。也就是说,高优先级针对的是请求服务之前的处理,和Servlet的过滤器的优先顺序类似。

除了Spring Cloud Gateway提供的内置过滤器之外,我们还可以实现自己的过滤器。

实现自己的过滤器

我们可以通过实现接口GatewayFilterFactory从而实现自己的路由过滤器。

Spring Cloud Filter提供了一个虚拟类AbstractGatewayFilterFactory,我们可以扩展该类实现自己的路由过滤器,比如我们创建一个MyGatewayFilterFactory :

package com.example.filter;

@Component
@Slf4j
public class MyGatewayFilterFactory extends AbstractGatewayFilterFactory<MyGatewayFilterFactory.Config> {

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

    @Override
    public GatewayFilter apply(Config config) {
        // grab configuration from Config object
		 log.info("filter:"+config.getName());
        return (exchange, chain) -> {
            //If you want to build a "pre" filter you need to manipulate the
            //request before calling chain.filter
            //获取request
            ServerHttpRequest request = exchange.getRequest();
            //从request中获取用户信息,进行用户鉴权......之后

            log.info("This is pre filter===");
            return chain.filter(exchange).then(Mono.fromRunnable(()-> {
                ServerHttpResponse response = exchange.getResponse();
                response.getHeaders().add("Auth","xxxx.yyyy.zzzz");
                log.info("this is after filter");
            }));
        };
    }

    public static class Config {
        //Put the configuration properties for your filter here
        private String name;

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }
    }

}

需要通过@Component注解将过滤器加入到Spring容器中。

通过Config接收一个name参数,在apply方法中可以实现路由前置、以及路由后置过滤逻辑。我们的MyGatewayFilterFactory 同时实现了前置逻辑和后置逻辑,前置逻辑中可以添加用户鉴权等代码,简单起见,我们只是log打印一句话。后置逻辑中同样很简单,打印一句话,设置一个reponse header。

配置路由过滤器

上面我们实现的是漏油过滤器,所以只有配置在某一路由上才会生效:

spring:
  application:
    name: spring-gateway
  cloud:
    gateway:
      routes:
        - id: path_route
#          uri: http://127.0.0.1:9090
          uri: lb://orderservice
          predicates:
            - Path=/order/*
          filters:
            - name: My
              args:
                name: My own pre-filter
eureka:
  client:
    service-url: # eureka service
      defaultZone: http://127.0.0.1:10086/eureka/
server:
  port: 9095

启动服务,测试:
在这里插入图片描述
首先从前端请求中发现response header已经成功添加。然后看一下后台log:
在这里插入图片描述
我们自己的路由过滤器已经可以正常工作了。

添加自己的全局过滤器

全局过滤器需要实现GlobalFilter 接口:

package com.example.filter;

@Component
@Slf4j
public class MyGlobalGatewayFilter implements GlobalFilter {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        log.info("Here i can do anything to exchage");
        return chain.filter(exchange).then(Mono.just(exchange)).map(serverWebExchange->{
            serverWebExchange.getResponse().getHeaders().add("Global-Filter","Global filter OK");
            return serverWebExchange;
        }).then();

    }
}

同样,我们添加的MyGlobalGatewayFilter 同时实现前置和后置过滤逻辑,不过都非常简单,前置过滤逻辑只是打印一段话,后置过滤逻辑添加一个response header。

全局过滤器是不需要额外配置的,对所有router都生效。

重新启动gateway,测试:
在这里插入图片描述
response header已经成功添加。

Ok,我们已经完成了对Spring Cloud Gateway的配置和使用,初步了解了Spring Cloud Gateway的用法,其实使用和配置起来一点都不复杂。

Thanks!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1280673.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

javaweb mybatis(手动jar包)

基础&#xff1a;https://blog.csdn.net/qq_67832732/article/details/134764134 条件查询 在映射文件的SQL配置中配置参数 使用parameterType来指定参数类型 使用#{参数名}来接收参数的值 parameterType"string" 表示sql语句需要一个参数&#xff0c;类型为字符…

计算UDP报文CRC校验的总结

概述 因公司项目需求&#xff0c;遇到需要发送带UDP/IP头数据包的功能&#xff0c;经过多次尝试顺利完成&#xff0c;博文记录以备忘。 环境信息 操作系统 ARM64平台的中标麒麟Kylin V10 工具 tcpdump、wireshark、vscode 原理 请查看大佬的博文 UDP伪包头定义&#x…

2023年【G1工业锅炉司炉】考试试题及G1工业锅炉司炉模拟考试题库

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2023年【G1工业锅炉司炉】考试试题及G1工业锅炉司炉模拟考试题库&#xff0c;包含G1工业锅炉司炉考试试题答案和解析及G1工业锅炉司炉模拟考试题库练习。安全生产模拟考试一点通结合国家G1工业锅炉司炉考试最新大纲及…

【开源】基于Vue和SpringBoot的校园二手交易系统

项目编号&#xff1a; S 009 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S009&#xff0c;文末获取源码。} 项目编号&#xff1a;S009&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 二手商品档案管理模…

Docker容器(一)概述

一、虚拟化概述 1.1引⼊虚拟化技术的必要性 服务器只有5%的时间是在⼯作的&#xff1b;在其它时间服务器都处于“休眠”状态. 虚拟化前 每台主机⼀个操作系统; 软硬件紧密结合; 在同⼀个主机上运⾏多个应⽤程序通常会遭遇冲突; 系统的资源利⽤率低; 硬件成本⾼昂⽽且不够灵活…

TIA西门子博途V19安装教程及注意事项

TIA西门子博途V19安装教程及注意事项 前提条件: TIA Portal V19需要.Net Framework 3.5环境,所以在安装TIA V19之前要先安装它。 如下图所示,否则可能会提示报错信息: 大家可以在控制面板中的程序和功能中检查是否已经安装,如果没有,可以参考以下步骤自行安装:

OpenWrt作为旁路由(网关)配置

目录 背景前提条件环境操作步骤物理层连接设置与主路由同一网段禁用IPv6取消LAN接口桥接防火墙配置 背景 本文简介如何配置OpenWrt&#xff0c;使其作为旁路由&#xff08;网关&#xff09;运行。 旁路由大概有以下这几种工作方式&#xff1a; 主路由开DHCP&#xff0c;网关未…

十、FreeRTOS之FreeRTOS任务调度

本节需要掌握的内容如下&#xff1a; 1&#xff0c;开启任务调度器&#xff08;熟悉&#xff09; 2&#xff0c;启动第一个任务&#xff08;熟悉&#xff09; 3&#xff0c;任务切换&#xff08;掌握&#xff09; 一&#xff0c;开启任务调度器&#xff08;熟悉&#xff09…

java高校实验室排课学生考勤系统springboot+vue

随着各高校办学规模的迅速扩大,学科专业的不断拓宽,传统的实验教学和实验室管理方法已经不能适应学校管理的要求,特别是化学实验室的管理,化学实验室仪器药品繁杂多样,管理任务繁重,目前主要使用人工记录方法管理,使用不便,效率低下,而且容易疏漏.时间一长将产生大量的文件和数…

【C++】异常处理 ⑦ ( 异常类的继承层次结构 | 抛出 / 捕获 多个类型异常对象 | 抛出子类异常对象 / 捕获并处理 父类异常对象 )

文章目录 一、抛出 / 捕获 多个类型异常对象1、抛出 / 捕获 多个类型异常对象2、操作弊端3、完整代码示例 二、异常类的继承层次结构1、抛出子类异常对象 / 捕获并处理 父类异常对象2、完整代码示例 - 抛出子类异常对象 / 捕获并处理 父类异常对象 自定义的 异常类 , 可能存在 …

Java数据结构 之 包装类简单认识泛类

生命不息&#xff0c;奋斗不止 目录 1. 什么是包装类&#xff1f; 1.1 装箱和拆箱 1.2 自动装箱和自动拆箱 2. 什么是泛型 3. 引出泛型 3.1 语法 4 泛型类的使用 4.1 语法 4.2 示例 4.3 类型推导(Type Inference) 5. 裸类型(Raw Type) &#xff08;了解&#xff09…

〖大前端 - 基础入门三大核心之JS篇㊻〗- JS + CSS实现动画

说明&#xff1a;该文属于 大前端全栈架构白宝书专栏&#xff0c;目前阶段免费&#xff0c;如需要项目实战或者是体系化资源&#xff0c;文末名片加V&#xff01;作者&#xff1a;不渴望力量的哈士奇(哈哥)&#xff0c;十余年工作经验, 从事过全栈研发、产品经理等工作&#xf…

JSP格式化标签 parseDate将指定时间格式字符串转为真正的date对象

格式化标签最后一个就是 parseDate 作用 将一个日期/时间格式字符串 转为 真正的date时间类型 有点无语 这种 东西应该都是在java中去做的 而不是在java中 这个建议也是做个了解即可 作用不是那么大 基本语法如下 这里 我们 直接编写代码如下 <% page contentType"…

智能优化算法应用:基于天牛须算法无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于天牛须算法无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于天牛须算法无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.天牛须算法4.实验参数设定5.算法结果6.参考文献7.…

2024年AMC8美国初中数学竞赛最后一个月复习指南(附资料)

还有一个半月的时间&#xff0c;2024年AMC8&#xff08;大家默认都直接叫这个比赛的英文名&#xff0c;而不叫中文名美国数学竞赛或美国初中数学竞赛了&#xff09;就要开始了。 有志于在2024年AMC8的比赛中拿到奖项的孩子已经在“磨拳霍霍”了。那么最后一个半月的时间该如何…

智能优化算法应用:基于热交换算法无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于热交换算法无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于热交换算法无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.热交换算法4.实验参数设定5.算法结果6.参考文献7.…

Java线程池的使用和最佳实践

第1章&#xff1a;引言 处理并发问题时&#xff0c;如果每次都新建线程&#xff0c;那系统的压力得有多大&#xff1f;这时候&#xff0c;线程池就像一个英雄一样出现了&#xff0c;它帮我们有效地管理线程&#xff0c;提高资源利用率&#xff0c;降低开销。那么&#xff0c;为…

还搞不懂什么是参数,超参数吗?三分钟快速了解参数与超参数的概念和区别!!!

文章目录 前言一、参数是什么&#xff1f;二、超参数是什么三&#xff0c;常使用的超参数有哪些 前言 参数是模型中可被学习和调整的参数&#xff0c;通过训练数据进行学习和优化&#xff1b; 而超参数则是手动设置的参数&#xff0c;用于控制模型的行为和性能&#xff0c;超…

探秘Python FastAPI、Sanic、Tornado 与Golang Gin性能之战!

更多资料获取 &#x1f4da; 个人网站&#xff1a;ipengtao.com Python和Golang作为两种流行的编程语言&#xff0c;都拥有强大的异步框架&#xff0c;为开发者提供了在构建高性能应用时的选择。在Python阵营中&#xff0c;FastAPI、Sanic、Tornado等框架因其异步特性和高效的…

viple模拟器使用(四):unity模拟器中实现两距离局部最优迷宫算法

名字解读 两距离&#xff1a;指的是左侧距离和右侧距离 局部最优&#xff1a;对当前状态来说最好的选择&#xff0c;至于整体能不能达到最优&#xff0c;是无法确定的。 从节点1到节点5&#xff0c;一共有3条路 第1条路线&#xff1a;1→2→4→5&#xff0c;对应的花销是&…