Spring cloud - gateway

什么是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-gatewaycloud:gateway:routes:- id: path_routeuri: http://127.0.0.1:9090predicates:- Path=/order/*
eureka:client:service-url: # eureka servicedefaultZone: 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;@AutowiredOrderService orderService;@AutowiredFallbackHandle 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-gatewaycloud:gateway:routes:- id: path_routeuri: lb://orderservicepredicates:- Path=/order/*
eureka:client:service-url: # eureka servicedefaultZone: 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);}@Overridepublic GatewayFilter apply(Config config) {// grab configuration from Config objectlog.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//获取requestServerHttpRequest 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 hereprivate 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-gatewaycloud:gateway:routes:- id: path_route
#          uri: http://127.0.0.1:9090uri: lb://orderservicepredicates:- Path=/order/*filters:- name: Myargs:name: My own pre-filter
eureka:client:service-url: # eureka servicedefaultZone: 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 {@Overridepublic 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.mzph.cn/news/195488.shtml

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

相关文章

Git:分布式版本控制系统的崛起与演变

简介 Git是一个开源的分布式版本控制系统&#xff0c;旨在有效、高速地处理从很小到非常大的项目版本管理。它是由Linus Torvalds于2005年创建的&#xff0c;最初是为了服务于Linux内核开发的版本控制需求。Git通过强大的分支功能、高效的缓存机制以及可扩展的架构设计&#xf…

Golang 并发 — 流水线

并发模式 我们可以将流水线理解为一组由通道连接并由 goroutine 处理的阶段。每个阶段都被定义为执行特定的任务&#xff0c;并按顺序执行&#xff0c;下一个阶段在前一个阶段完成后开始执行。 流水线的另一个重要特性是&#xff0c;除了连接在一起&#xff0c;每个阶段都使用…

统信UOS_麒麟KYLINOS配置apt及git内网代理

原文链接&#xff1a;统信UOS/麒麟KYLINOS上配置APT和GIT内网代理 **hello&#xff0c;大家好啊&#xff01;**在企业环境中&#xff0c;出于安全和管理的考虑&#xff0c;很多公司会设置内网代理服务器&#xff0c;以控制和监管内部网络的访问。这就意味着&#xff0c;员工在使…

jsp多站点图书管理系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 JSP 多站点图书管理系统是一套完善的java web信息管理系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为 TOMCAT7.0,Myeclipse8.5开发&#xff0c;数据库为Mysql5…

git常用命令小记

&#xff08;文章正在持续更新中&#xff09; git init - 在当前目录下初始化一个新的 Git 仓库。 git clone [url] - 克隆远程仓库到本地。 git add [file] - 将文件添加到暂存区。 git commit -m "commit message" - 将添加到暂存区的文件提交到本地仓库。 git pus…

STM32 Nucleo-64 boards 外设资源引脚对应关系图

STM32 Nucleo-64 boards 外设资源引脚对应关系图 1. STM32 NUCLEO-F103RB1.1 串口对应关系图1.2 I2C对应关系图 【参考博文】 1. STM32 NUCLEO-F103RB 1.1 串口对应关系图 1.2 I2C对应关系图 注意&#xff1a;STM32 NUCLEO-F103RB 在Arduino 端子分配的 I2C 重映射为 PB8 PB9 …

直击2023云栖大会-大模型时代到来:“计算,为了无法计算的价值”

2023年的云栖大会以“计算&#xff0c;为了无法计算的价值”为主题&#xff0c;强调了计算技术在现代社会中的重要性&#xff0c;特别是在大模型时代到来的背景下。 大模型时代指的是以深度学习为代表的人工智能技术的快速发展&#xff0c;这些技术需要大量的计算资源来训练和优…

深度学习设计基于Tensorflow卷积神经网络猫的品种识别系统

欢迎大家点赞、收藏、关注、评论啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代码。 文章目录 一项目简介 二、功能三、系统四. 总结 一项目简介 基于Tensorflow卷积神经网络的猫的品种识别系统可以用于自动识别猫的品种类型。下面我将为您介绍一下这个系统的基本…

Python函数的基本使用(一)

Python函数的基本使用&#xff08;一&#xff09; 一、函数概述二、函数的定义2.1 函数的语法2.2 语法说明2.3 函数定义的方式2.4 总结 三、函数的调用3.1 函数调用语法3.2 语法说明3.3 函数调用 四、函数的参数4.1 参数的分类4.2 必需参数4.3 默认值参数4.4 关键字参数4.5 不定…

路由策略,gRPC 路由如何实现

目录 一、为啥我们要路由策略&#xff1a; 二、基于gRPC 路由策略 一、为啥我们要路由策略&#xff1a; 我们可以重新回到调用方发起 RPC 调用的流程。在 RPC 发起真实请求的时候&#xff0c;有一个步骤就是从服务提供方节点集合里面选择一个合适的节点&#xff08;就是我们…

保育员个人简历精选7篇

想要在保育员职位的求职过程中脱颖而出吗&#xff0c;参考这7篇精选的保育员简历案例&#xff01;无论您的经验如何&#xff0c;都能找到适合自己的简历样式及参考内容。 保育员个人简历模板下载&#xff08;可在线编辑制作&#xff09;&#xff1a;来幻主简历&#xff0c;做好…

微服务的流量管理-服务网格

对于单体应用来说&#xff0c;一般只有流入和流出两种流量。而微服务架构引入了跨进程的网络通信&#xff0c;流量发生在服务之间。由许多服务组成了复杂的网络拓扑结构&#xff0c;每次请求都会产生流量。 这些流量如果没有妥善的管理&#xff0c;整个应用的行为和状态将会不…

封装Servlet使用自定义注解进行参数接收

文章目录 前言一、前后对比✨二、具体实现&#x1f387;三、效果展示&#x1f38f; 前言 先说项目背景&#xff0c;本项目是本人在校期间老师布置的作业&#xff08;就一个CRUD&#xff09;&#xff0c;课程是后端应用程序设计&#xff0c;其实就是servlet和jsp那一套&#xf…

【c】课程满意度计算

我们不好直接比较二维数组中任意多个元素的值是否相等&#xff0c;我们可以创建一维数组&#xff0c;首先将一维数组的值全部设为0&#xff0c;一维数组的下标代表你喜欢课程的量&#xff0c;一维数组的各个元素的值代表你喜欢的次数 例如 你输入3 5&#xff0c;代表你喜欢第三…

好用的挂耳式蓝牙耳机有哪些?分享几款热门好用的蓝牙耳机

挂耳式蓝牙耳机已经成为我们日常生活中的一部分&#xff0c;无论是在通勤、运动还是日常休闲时&#xff0c;它们都发挥着不可替代的作用&#xff0c;随着技术的不断进步&#xff0c;挂耳式蓝牙耳机的音质、连接稳定性以及续航时间都有了显著的提升&#xff0c;下面&#xff0c;…

【C++初阶】六、类和对象(初始化列表、static成员、友元、内部类)

相关代码gitee自取&#xff1a; C语言学习日记: 加油努力 (gitee.com) 接上期&#xff1a; 【C初阶】五、类和对象 &#xff08;日期类的完善、流运算符重载函数、const成员、“&”取地址运算符重载&#xff09;-CSDN博客 目录 ​​​​​​​一 . 初始化列表 构造函数…

06 g2o 学习

文章目录 06 g2o 学习6.1 概念6.2 框架简介6.3 代码示例 06 g2o 学习 6.1 概念 g2o(General Graphic Optimization)是基于图优化的库。图优化是把优化问题表现成图的一种方式。一个图由若干个顶点(Vertex)&#xff0c;以及连接这这些顶点的边(Edge)组成。用顶点表示优化变量&…

【python】——函数

&#x1f383;个人专栏&#xff1a; &#x1f42c; 算法设计与分析&#xff1a;算法设计与分析_IT闫的博客-CSDN博客 &#x1f433;Java基础&#xff1a;Java基础_IT闫的博客-CSDN博客 &#x1f40b;c语言&#xff1a;c语言_IT闫的博客-CSDN博客 &#x1f41f;MySQL&#xff1a…

P8 删除链表指定节点

前言 &#x1f3ac; 个人主页&#xff1a;ChenPi &#x1f43b;推荐专栏1: 《C_ChenPi的博客-CSDN博客》✨✨✨ &#x1f525; 推荐专栏2: 《Linux C应用编程&#xff08;概念类&#xff09;_ChenPi的博客-CSDN博客》✨✨✨ &#x1f4…

【灵魂 |数据结构与算法】 数据结构必备经法(开山篇),一起修炼算法经法!

&#x1f935;‍♂️ 个人主页: AI_magician &#x1f4e1;主页地址&#xff1a; 作者简介&#xff1a;CSDN内容合伙人&#xff0c;全栈领域优质创作者。 &#x1f468;‍&#x1f4bb;景愿&#xff1a;旨在于能和更多的热爱计算机的伙伴一起成长&#xff01;&#xff01;&…