Springboot集成Gateway实现API服务网关-07

devtools/2024/10/9 15:18:18/

GateWay简介

Spring Cloud Gateway 为 SpringBoot 应用提供了API网关支持,具有强大的智能路由与过滤器功能,本文将对其用法进行详细介绍。

网关术语

关于网关三个重要的概念如下:

  • Route(路由):路由是构建网关的基本模块,它由ID,目标URI,一系列的断言和过滤器组成,如果断言为true则匹配该路由;
  • Predicate(断言):指的是Java 8 的 Function Predicate。 输入类型是Spring框架中的ServerWebExchange。 这使开发人员可以匹配HTTP请求中的所有内容,例如请求头或请求参数。如果请求与断言相匹配,则进行路由;
  • Filter(过滤器):指的是Spring框架中GatewayFilter的实例,使用过滤器,可以在请求被路由前后对请求进行修改,比如参数效验、权限效验、流量监控、日志输出、协议转换等。

主要功能

Gateway是在Spring生态系统之上构建的API网关服务,Gateway旨在提供一种简单而有效的方式来对API进行路由,以及提供一些强大的过滤器功能, 例如:熔断、限流、重试等。
Spring Cloud Gateway 具有如下特性:

  • 基于Spring Framework 5, Project Reactor 和 Spring Boot 2.0 进行构建;
  • 动态路由:能够匹配任何请求属性;
  • 可以对路由指定 Predicate(断言)和 Filter(过滤器);
  • 集成Hystrix的断路器功能;
  • 集成 Spring Cloud 服务发现功能;
  • 易于编写的 Predicate(断言)和 Filter(过滤器);
  • 请求限流功能;
  • 支持路径重写。

调用执行过程

  1. Gateway Client向Gateway Server发送请求
  2. 请求首先会被HttpWebHandlerAdapter进行提取组装成网关上下文
  3. 然后网关的上下文会传递到DispatcherHandler,它负责将请求分发给RoutePredicateHandlerMapping
  4. RoutePredicateHandlerMapping负责路由查找,并根据路由断言判断路由是否可用
  5. 如果过断言成功,由FilteringWebHandler创建过滤器链并调用
  6. 请求会一次经过PreFilter–微服务–PostFilter的方法,最终返回响应

为什么要使用网关

看下面的图即可:

  • 传统应用部署模式:
    在这里插入图片描述
  • 采用网关后的部署模式:
    在这里插入图片描述

此测试中使用了Consul注册中心

GateWay网关服务实现

在这里插入图片描述

pom.xml

依赖版本可参考 springbootSeries 模块中pom.xml文件中的版本定义

        <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-consul-discovery</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></dependency>

application.yml 配置

因为网关配置比较复杂,会有一些数组类的配置,所以这里选用yml格式。

server:port: 19000debug: falsespring:application:name: springbootAPIGatewayprofiles:active: devcloud:consul:discovery:service-name: ${spring.application.name}host: localhostport: 8500gateway:routes:- id: path_route #路由标识、区别于其他routeorder: 9000  #用于多个route之间的排序,数值越小排序越靠前,匹配优先级越高uri:  http://localhost:18096  # 路由指向的目的地uri,即客户端请求最终被转发到的微服务predicates:- Path=/api/load/v1/**  #断言的作用是进行条件判断,只有断言都返回真,才会真正的执行路由main:web-application-type: reactive

SpringbootApplication启动类

这里主要是添加了Consul服务发现注解@EnableDiscoveryClient

java">@Slf4j
@SpringBootApplication(scanBasePackages = {"com.korgs",  "cn.hutool.extra.spring"})
@Configuration
@EnableConfigurationProperties
@ServletComponentScan
@RestController
@EnableDiscoveryClient
public class SpringbootApiGatewayApplication {public static void main(String[] args) {SpringApplication.run(SpringbootApiGatewayApplication.class, args);}@GetMapping("/helloworld")public BaseResponse helloWorld(){log.info( LogGenerator.trackLog()+ "msg=" + "I am busy to handle this request.");return BaseResponse.success("hello world");}
}

springboot_105">被代理的springboot服务

这个就是一个普通的应用,没什么特殊的。
在这里插入图片描述

pom.xml

这里主要配置了注册中心,如果不需要可删除掉consul相关的配置

    <dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-consul-discovery</artifactId></dependency></dependencies>

application.properties 配置

这里主要配置了注册中心,如果不需要可删除掉consul相关的配置

spring.profiles.active = dev
spring.application.name=springbootGatewayServer
server.port=18096spring.cloud.consul.host=localhost
spring.cloud.consul.port=8500
spring.cloud.consul.discovery.service-name=${spring.application.name}

SpringbootApplication启动类

java">@Slf4j
@SpringBootApplication(scanBasePackages = {"com.korgs",  "cn.hutool.extra.spring"})
@Configuration
@EnableConfigurationProperties
@ServletComponentScan
@RestController
@EnableDiscoveryClient
public class SpringbootGatewayServerApplication {public static void main(String[] args) {SpringApplication.run(SpringbootGatewayServerApplication.class, args);}@GetMapping("/helloworld")public String helloWorld(){log.info( LogGenerator.trackLog()+ "msg=" + "I am busy to handle this request.");return "hello world";}
}

实现被代理的Restful API

java">@Slf4j
@RestController
@RequestMapping("/api/load")
public class LoadBalanceController {@Value("${server.port}")private String serverPort;@GetMapping("/v1/hello-content/{uuid}")public BaseResponse<String> loadHelloContent(@PathVariable  String uuid){String str = LogGenerator.trackLog()+ " uuid=" + uuid + " I am busy to handle this request."+ " serverPort=" + serverPort;log.info( str );return BaseResponse.success(str);}
}

源码下载

涉及模块:

  • springcloud-api-gateway:19000 ,网关服务
  • springcloud-gateway-server:18096 ,这个就是一个普通的应用,没什么特殊的

源码下载:

  • 基础框架源码下载
  • Springboot集成Gateway实现API服务网关

源码运行方法:

  • 模块详细功能说明和运行测试方法

访问 : http://localhost:19000/api/load/v1/hello-content/2会发现端口号19000不变,但实际访问了18096服务的实现。
在这里插入图片描述

注意事项

断言Predicate配置

注意:此应用的spring文件最好用yaml来配置,配置的重点就是uri 和 predicates 正常来讲是一一对应的,比如下面配置中,最终访问地址是uri+path,但Path不能随便写,比如把/api去掉,如果去掉了就不能访问到真实地址了,而且后台好像也有一个验证的过程,最恶心的是一直提示404。

        gateway:routes:- id: path_routeuri:  http://localhost:18096predicates:- Path=/api/load/v1/**

断言Predicate类别说明

  1. After:匹配在指定日期时间之后发生的请求。
  2. Before:匹配在指定日期之前发生的请求。
  3. Between:需要指定两个日期参数,设定一个时间区间,匹配此时间区间内的请求。
  4. Cookie:需要指定两个参数,分别为name和regexp(正则表达式),也可以理解Key和Value,匹配具有给定名称且其值与正则表达式匹配的Cookie。
  5. Header:需要两个参数header和regexp(正则表达式),也可以理解为Key和Value,匹配请求携带信息。
  6. Host:匹配当前请求是否来自于设置的主机。
  7. Method:可以设置一个或多个参数,匹配HTTP请求,比如GET、POST
  8. Path:匹配指定路径下的请求,可以是多个用逗号分隔
  9. Query:需要指定一个或者多个参数,一个必须参数和一个可选的正则表达式,匹配请求中是否包含第一个参数,如果有两个参数,则匹配请求中第一个参数的值是否符合正则表达式。
  10. RemoteAddr:匹配指定IP或IP段,符合条件转发。
  11. Weight:需要两个参数group和weight(int),实现了路由权重功能,按照路由权重选择同一个分组中的路由

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


http://www.ppmy.cn/devtools/41903.html

相关文章

python读取excel数据写入mysql

概述 业务中有时会需要解析excel中的数据&#xff0c;按照要求处理后&#xff0c;写入到db中&#xff1b; 用python处理这个正好简便快捷 demo 没有依赖就 pip install pymysql一下 import pymysql from pymysql.converters import escape_string from openpyxl import loa…

手机号码的正则表达式

手机号码的正则表达式会根据不同的国家/地区有所不同&#xff0c;因为每个国家/地区都有自己特定的手机号码格式。但是&#xff0c;我可以为你提供一个通用的正则表达式模板&#xff0c;并给出一些具体国家/地区的例子。 通用模板 一个基本的手机号码正则表达式模板可能如下所…

深入理解Linux下的网络监控工具:iftop

目录标题 1. 什么是iftop?2. 安装iftop在Debian/Ubuntu上安装在CentOS/RHEL上安装在其他Linux发行版上 3. 使用iftop监控网络流量命令行选项界面说明交互命令 4. 相关参数及说明 在维护和监控Linux服务器时&#xff0c;了解网络流量的细节非常重要。网络监控可以帮助我们诊断延…

解决springboot+vue静态资源刷新后无法访问的问题

一、背景 原项目是有前后端分离设计&#xff0c;测试环境是centos系统&#xff0c;采用nginx代理和转发&#xff0c;项目正常运行。 项目近期上线到正式环境&#xff0c;结果更换了系统环境&#xff0c;需要放到一台windows系统中&#xff0c;前后端打成一个jar包&#xff0c;…

【k8s多集群管理平台开发实践】十一、client-go实现读取k8s的事件信息

文章目录 简介 一.k8s读取k8s事件1.1.controllers控制器代码1.2.models模型代码 二.路由设置2.1.路由设置 三.前端代码5.1.列表部分html代码 四.完整代码4.1.控制器event.go的完整代码4.2.模型eventModel.go的完整代码 五.效果图 简介 本章节主要讲解通过client-go实现读取k8s事…

Leaflet.canvaslabel在Ajax异步请求时bindPopup无效的解决办法

目录 前言 一、场景重现 1、遇到问题的代码 2、问题排查 二、通过实验验证猜想 1、排查LayerGroup和FeatureGroup 2、排查Leaflet.canvaslabel.js 三、柳暗花明又一村 1、点聚类的办法 2、歪打正着 总结 前言 在上一篇博客中介绍了基于SpringBoot的全国风景区WebGIS按…

行为型模式

模板方法模式 #include<iostream> #include<string> using namespace std;/*案例&#xff1a;写简历内容&#xff1a;最近有个招聘会&#xff0c;可以带上简历去应聘了。但是&#xff0c;其中有一家公司不接受简历&#xff0c;而是给应聘者发了一张简历表&#xf…

Pytorch的深度学习

PyTorch是一个流行的深度学习框架&#xff0c;它以其易用性、灵活性和动态图特性而广受开发者喜爱。以下是对PyTorch在深度学习中的详细介绍&#xff1a; 核心基础架构&#xff1a; 张量&#xff08;Tensor&#xff09;&#xff1a;PyTorch的基本数据结构&#xff0c;类似于Num…