springcloud gateway 介绍与使用

news2025/2/4 19:07:03

定义

该项目提供了一个用于在 Spring WebFlux 之上构建 API 网关的库。Spring Cloud Gateway
旨在提供一种简单而有效的方法来路由到 API,并为它们提供横切关注点,例如:安全性、监控/指标和弹性

特征

Spring Cloud Gateway 特性:

  • 基于 Spring Framework 5、Project Reactor 和 Spring Boot 2.0 构建
  • 能够匹配任何请求属性上的路由。
  • 谓词和过滤器特定于路由。
  • 断路器集成。
  • Spring Cloud DiscoveryClient 集成
  • 易于编写谓词和过滤器
  • 请求速率限制
  • 路径重写

概念

(1)Filter(过滤器):

和Zuul的过滤器在概念上类似,可以使用它拦截和修改请求,并且对上游的响应,进行二次处理。过滤器为
org.springframework.cloud.gateway.filter.GatewayFilter类的实例。

(2)Route(路由):

网关配置的基本组成模块,和Zuul的路由配置模块类似。一个Route模块由一个 ID,一个目标 URI,一组断言和一组过滤器定义。如果断言为真,则路由匹配,目标URI会被访问。

(3)Predicate(断言):

这是一个 Java 8 的 Predicate,可以使用它来匹配来自 HTTP 请求的任何内容,例如 headers 或参数。断言的输入类型是一个 ServerWebExchange

路由配置

spring:
  cloud:
    gateway:
        filter:
            remove-hop-by-hop:
              headers:  #默认的移除request中的header
                - aaa
                - bbb
#      httpclient:
#        connect-timeout: 1000 # 转发后端服务超时时间
#        response-timeout: 3s  # 转发后端服务响应超时时间
#      discovery:
#        locator:
#          enabled: true #开启服务注册和发现
#          lower-case-service-id: true #注册名转为小写
      routes: #路由配置
        - id: route_1 #直接跳转到指定域名下 http://10.2.11.6:8808/gw/1 > http://10.2.11.6:8800/gw/1
          uri: http://10.2.11.6:8800 #目标路径
          predicates: #谓词匹配
            - Path=/gw/** #匹配路径
        - id: route_2 #去除前缀跳转 http://10.2.11.6:8808/sp/hi/1 > http://10.2.11.6:8800/hi/1
          uri: http://10.2.11.6:8800 #目标路径
          predicates: #谓词匹配
            - Path=/sp/** #匹配路径
            - Method=GET #指定方式
          filters:
            - StripPrefix=1 #去除第一个级前缀
        - id: route_3 # 增加前缀  http://10.2.11.6:8808/pp/1 > http://10.2.11.6:8800/hi/1
          uri: http://10.2.11.6:8800  #目标路径
          predicates: #谓词匹配
            - Path=/pp/** #匹配路径
          filters:
            - StripPrefix=1 #去除第一个级前缀
            - PrefixPath=/hi #
        - id: route_4 # 重写前缀  http://10.2.11.6:8808/rp/1 > http://10.2.11.6:8800/hi/1
          uri: http://10.2.11.6:8800  #目标路径
          predicates: #谓词匹配
            - Path=/rp/** #匹配路径
          filters:
            - RewritePath=/rp, /hi
        - id: route_5 # 动态重写前缀  http://10.2.11.6:8808/rp1 > http://10.2.11.6:8800/hi/rp1
          uri: http://10.2.11.6:8800  #目标路径
          predicates: #谓词匹配
            - Path=/rp1/** #匹配路径
          filters:
            - RewritePath=(?<oldPath>^/), /hi$\{oldPath}
        - id: route_6 # 指定跳转路径  http://10.2.11.6:8808/setpath > http://10.2.11.6:8800/hi/1
          uri: http://10.2.11.6:8800  #目标路径
          predicates: #谓词匹配
            - Path=/setpath/** #匹配路径
          filters:
            - SetPath=/hi/1
        - id: route_7 # 设置路径,同时使用时,根据前后顺序进行设置,改变顺序结果不同 http://10.2.11.6:8808/allpath > http://10.2.11.6:8800/hi/a
          uri: http://10.2.11.6:8800  #目标路径
          predicates: #谓词匹配
            - Path=/allpath/** #匹配路径
          filters:
            - PrefixPath=/b # http://10.2.11.6:8808/allpath > http://10.2.11.6:8800/b/allpath
            - SetPath=/a # http://10.2.11.6:8800/b/allpath > http://10.2.11.6:8800/a
            - RewritePath=(?<oldPath>^/), /hi$\{oldPath} # http://10.2.11.6:8800/b/a > http://10.2.11.6:8800/hi/a
        - id: route_8 # 通过eureka访问 http://10.2.11.6:8808/eureka/lb/1 > http://10.2.11.6:8800/lb/1
          uri: lb://lizz-eureka-provider  #目标路径
          predicates: #谓词匹配
            - Path=/eureka/** #匹配路径
#          metadata:
#            connect-timeout: 200 #响应时间 ,当前2.2.0版本暂不支持
#            response-timeout: 1000 #链接时间,当前2.2.0版本暂不支持
          filters:
            - StripPrefix=1 #去除第一个级前缀
            - name : RequestSize
              args:
                maxSize: 500000 #限制请求数据大小,byte,比较的长度String contentLength = request.getHeaders().getFirst("content-length");
            - name: Retry #重试过滤器,重试调用lizz-eureka-provider的次数
              args:
                retries: 1 #重试次数 默认3次
                statuses: BAD_GATEWAY #HttpStatus 什么情况下重试,可以是错误码,如:500,502
                series: # HttpStatus.重试系列 默认 SERVER_ERROR-5xx,SUCCESSFUL-2xx ,空为异常补重试,与statuses并行使用
                exceptions:  #异常重试 默认IOException and TimeoutException,空为异常补重试
                methods: GET,POST # HttpMethod 重试的方法 默认 GET GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE;
                backoff: #延时重试
                  firstBackoff: 10ms #首次延时次数
                  maxBackoff: 50ms # 最大延迟后停止
                  factor: 2 #重试因子 下一次重试延时为firstBackoff*2*n次
                  basedOnPreviousValue: false #为true, backoff 计算公式为 prevBackoff * factor.
        - id: route_9 # 流量限制
          uri: lb://lizz-eureka-provider  #目标路径
          predicates: #谓词匹配
            - Path=/iprate/** #匹配路径
          filters:
            - StripPrefix=1 #去除第一个级前缀
            - name: RequestRateLimiter
              args:
                redis-rate-limiter: #过期时间=burstCapacity/replenishRate*2s
                  replenishRate: 3 #每次补充数量
                  burstCapacity: 1000 #突发容量
                  requestedTokens: 1 #每次请求消耗几个令牌,可以控制不同频率,默认1
                key-resolver: "#{@ipKeyResolver}" # ipKeyResolver 自定义限流柜子
#                rate-limiter: "#{@myRateLimiter}" # 使用自定义限流规则
        - id: route_10 # 修改header
          uri: lb://lizz-eureka-provider  #目标路径
          predicates: #谓词匹配
            - Path=/userrate/** #匹配路径
          filters:
            - AddRequestHeader=X-Request-Foo,Bar #增加转发请求的header 格式:key,value
            - AddRequestParameter=foo,bar #增加转发请求的参数
            - AddResponseHeader=X-Request-Foo,Bar #增加返回数据的header
            - RemoveRequestHeader=X-Request-Foo #移除转发请求的header
            - RemoveResponseHeader=X-Request-Foo #移除返回数据的header
            

快速开始

  • maven依赖
 <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
  • 配置
server:
  port: 8899
spring:
  application:
    name: gateway
  cloud:
    gateway:
      routes:
      - id: gateway
        uri: http://172.16.100.24:8087
        predicates:
        - Path=/consumer/**

  main:
    web-application-type: reactive
  • 跨域配置
@Configuration
public class CorsConfig {

    @Bean
    public CorsFilter corsFilter() {
        //1. 添加 CORS配置信息
        CorsConfiguration config = new CorsConfiguration();
        //放行哪些原始域
        config.addAllowedOrigin("*");
        //是否发送 Cookie
        config.setAllowCredentials(true);
        //放行哪些请求方式
        config.addAllowedMethod("*");
        //放行哪些原始请求头部信息
        config.addAllowedHeader("*");
        //暴露哪些头部信息
        config.addExposedHeader("*");
        //2. 添加映射路径
        UrlBasedCorsConfigurationSource corsConfigurationSource = new UrlBasedCorsConfigurationSource();
        corsConfigurationSource.registerCorsConfiguration("/**",config);
        //3. 返回新的CorsFilter
        return new CorsFilter(corsConfigurationSource);
    }

}
  • 自定义全局过滤器
@Component
public class AuthFilter implements GlobalFilter, Ordered {


    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        //TODO 自定义认证逻辑(token认证或者接口认证)
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return Ordered.LOWEST_PRECEDENCE;
    }
}
  • 接口调用

经过网关

拓展

在高并发的系统中,防止大量请求使服务器过载,进行一些限流操作


常见的限流算法

  • 计数器算法

计数器算法为最简单的限流算法,其实现原理是为维护一个单位时间内的计数器。在单位时间内,开始计数器为0,每次通过一个请求计数器+1。如果单位时间内 计数器的数量大于了预先设定的阈值,则在此刻到单位时间的最后一刻范围内的请求都将被拒绝。单位时间结束计数器归零,重新开始计数

  • 令牌桶算法(推荐)

从某种意义上讲,令牌桶算法是对漏桶算法的一种改进,桶算法能够限制请求调用的速率,而令牌桶算法能够在限制调用的平均速率的同时还允许一定程度的突发调用。在令牌桶算法中,存在一个桶,用来存放固定数量的令牌。算法中存在一种机制,以一定的速率往桶中放令牌。每次请求调用需要先获取令牌,只有拿到令牌,才有机会继续执行,否则选择选择等待可用的令牌、或者直接拒绝。放令牌这个动作是持续不断的进行,如果桶中令牌数达到上限,就丢弃令牌,所以就存在这种情况,桶中一直有大量的可用令牌,这时进来的请求就可以直接拿到令牌执行,比如设置qps为100,那么限流器初始化完成一秒后,桶中就已经有100个令牌了,这时服务还没完全启动好,等启动完成对外提供服务时,该限流器可以抵挡瞬时的100个请求。所以,只有桶中没有令牌时,请求才会进行等待,最后相当于以一定的速率执行

实现思路:可以准备一个队列,用来保存令牌,另外通过一个线程池定期生成令牌放到队列中,每来一个请求,就从队列中获取一个令牌,并继续执行。

以redis 方式实现令牌桶算法

maven依赖

 <dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
 
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifatId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>

配置

server:
  port: 8081
spring:
  cloud:
    gateway:
      routes:
      - id: limit_route
        uri: http://httpbin.org:80/get
        predicates:
        - After=2017-01-20T17:42:47.789-07:00[America/Denver]
        filters:
        - name: RequestRateLimiter
          args:
            key-resolver: '#{@hostAddrKeyResolver}'
            redis-rate-limiter.replenishRate: 1
            redis-rate-limiter.burstCapacity: 3
  application:
    name: gateway-limiter
  redis:
    host: localhost
    port: 6379

在上面的配置文件,指定程序的端口为8081,配置了 redis的信息,并配置了RequestRateLimiter的限流过滤器,该过滤器需要配置三个参数:

  • burstCapacity,令牌桶总容量。
  • replenishRate,令牌桶每秒填充平均速率。
  • key-resolver,用于限流的键的解析器的 Bean 对象的名字。它使用 SpEL 表达式根据#{@beanName}从 Spring 容器中获取 Bean 对象。

KeyResolver需要实现resolve方法,比如根据Hostname进行限流,则需要用hostAddress去判断。实现完KeyResolver之后,需要将这个类的Bean注册到Ioc容器中

public class HostAddrKeyResolver implements KeyResolver {
 
    @Override
    public Mono<String> resolve(ServerWebExchange exchange) {
        return Mono.just(exchange.getRequest().getRemoteAddress().getAddress().getHostAddress());
    }
 
}
 
 @Bean
    public HostAddrKeyResolver hostAddrKeyResolver() {
        return new HostAddrKeyResolver();
    }

根据uri去限流,这时KeyResolver代码如下

public class UriKeyResolver  implements KeyResolver {
 
    @Override
    public Mono<String> resolve(ServerWebExchange exchange) {
        return Mono.just(exchange.getRequest().getURI().getPath());
    }
 
}
 
 @Bean
    public UriKeyResolver uriKeyResolver() {
        return new UriKeyResolver();
    }

也可以以用户的维度去限流:

 
   @Bean
    KeyResolver userKeyResolver() {
        return exchange -> Mono.just(exchange.getRequest().getQueryParams().getFirst("user"));
    }
 
 

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

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

相关文章

Smartbi 身份认证绕过漏洞

0x00 简介 Smartbi是广州思迈特软件有限公司旗下的商业智能BI和数据分析产品&#xff0c;致力于为企业客户提供一站式商业智能解决方案。 0x01 漏洞概述 Smartbi在安装时会内置三个用户&#xff08;public、service、system&#xff09;&#xff0c;在使用特定接口时&#x…

只会用插件可不行,这些前端动画技术同样值得收藏-JavaScript篇(上)

目录 前言 settimeout/setinterval requestAnimationFrame 基本用法 时间戳参数 帧数与时间戳计算 自动暂停 JS中的贝塞尔曲线 概念 公式 二次贝塞尔 三次贝塞尔 N次贝塞尔 贝塞尔曲线动画 动画类 在动画中使用贝塞尔 总结 相关代码&#xff1a; 贝塞尔曲线相…

【深度学习】:《PyTorch入门到项目实战》(十五):三大经典卷积神经网络架构:LeNet、AlexNet、VGG

【深度学习】&#xff1a;《PyTorch入门到项目实战》(十五)&#xff1a;三大经典卷积神经网络架构&#xff1a;LeNet、AlexNet、VGG&#xff08;代码实现及实际案例比较&#xff09; ✨本文收录于【深度学习】&#xff1a;《PyTorch入门到项目实战》专栏&#xff0c;此专栏主要…

数据结构与算法——顺序表的基本操作(C语言详解版)

顺序表插入元素 向已有顺序表中插入数据元素&#xff0c;根据插入位置的不同&#xff0c;可分为以下 3 种情况&#xff1a; 插入到顺序表的表头&#xff1b;在表的中间位置插入元素&#xff1b;尾随顺序表中已有元素&#xff0c;作为顺序表中的最后一个元素&#xff1b; 虽然…

GaussDB OLTP 云数据库配套工具DAS

目录 一 、前言 二、DAS的定义 1、DAS的定义 2、DAS功能特点 三、DAS应用场景 1、标准版 2、企业版 四、操作示例&#xff08;标准版&#xff09; 1、登录华为控制台登录&#xff0c;输入账号密码 2、新增数据库实例链接 3、新建对象 4、SQL操作 5、导入导出 五、…

OC多态性浅析

OC多态性浅析 小实验 假设有以下两个类classA与class B的声明与实现&#xff1a; /// classA.h#ifndef classA_h #define classA_h#import <Foundation/Foundation.h>interface classA : NSObject-(void) printVar;end#endif /* classA_h *//// classB.h#ifndef class…

微信小程序事件点击跳转页面的五种方法

第一种:标签 这是最常见的一种跳转方式,相当于html里的a标签 <navigator url"/pages/main/main"></navigator>第二种:wx.navigateTo({})方法 1.前端wxml <button bindtap"getCeshi" type"primary"> 测试按钮 </button>…

基于SpringBoot+vue的外卖点餐系统设计与实现

博主介绍&#xff1a; 大家好&#xff0c;我是一名在Java圈混迹十余年的程序员&#xff0c;精通Java编程语言&#xff0c;同时也熟练掌握微信小程序、Python和Android等技术&#xff0c;能够为大家提供全方位的技术支持和交流。 我擅长在JavaWeb、SSH、SSM、SpringBoot等框架…

【Android知识笔记】应用进程(二)

Service的启动原理 向AMS发送startService请求 startService时会首先拿到AMS的Binder代理对象,向AMS发起startService请求: AMS处理startService请求 接下来看AMS端处理应用的startService请求: 回忆一下应用进程启动流程: 接下来看如果Service所在应用进程没有启动的情…

GitLab 私有 Go Modules 的搭建配置

配置步骤 配置 GitLab Access Token 将 GitLab Access Token 写入到 ~/.netrc 文件里(也就是根目录下的 .netrc 文件),没有则新建,并写入内容:machine git.tenorshare.cn login ${USER_NAME} password ${GITLAB_ACCESS_TOKEN},其中 ${USER_NAME} 是GitLab 用户名,${GIT…

K8S的部署项目流程

步骤 &#xff08;1&#xff09;条件准备 &#xff08;2&#xff09;制作镜像 &#xff08;3&#xff09;docker启动程序 &#xff08;4&#xff09;启动制作好的镜像&#xff0c;看是否可以访问 &#xff08;5&#xff09;上传镜像到镜像容器中&#xff08;如&#xff1a;阿里…

Hive最全总结,学习与面试,看这一篇就行了!

废话不多说,上题: 1.Hadoop中两个⼤表实现join的操作,简单描述。 (1)Hive中可以通过分区来减少数据量;(2)还可以通过优化HQL语句,⽐如只查询需要的字段,尽量避免全表、全字段查询; 2.Hive中存放是什么? 表。存的是和hdfs的映射关系,hive是逻辑上的数据仓库,…

使用docker安装portainer

portainer是一个非常好用的docker可视化工具&#xff0c;这篇文章就介绍一下怎么使用docker来安装portainer。 第一步&#xff1a;在docker仓库查找portainer的版本 docker search portainer 我们可以看到&#xff0c;第一个portainer/portainer的描述中说了&#xff0c;这个仓…

【数据架构实践】Netflix 万亿级实时数据基础架构的四个创新阶段

Netflix 是一个很棒的地方&#xff0c;周围有许多了不起的同事。我为参与将共同信念变为现实的旅程中的每个人感到无比自豪。我想花点时间分享一下团队的主要成就&#xff1a; 我们在 Netflix 的所有组织中将流数据用例从 0 增加到 2000 多个。我们构建和发展了成功的产品&…

【Spring框架】getBean的更多用法

目录 用法1&#xff1a;根据名称获取Bean对象用法2&#xff1a;根据类型获取Bean对象用法3&#xff1a;根据名称类型来获取Bean对象 用法1&#xff1a;根据名称获取Bean对象 UserService userService (UserService)context.getBean("user");用法2&#xff1a;根据类…

如何利用量比和换手率?

1 量比 有人说&#xff0c;量比指标是盘口语言的翻译器&#xff0c;堪称股市风向标&#xff01;这一说法究竟从何而来&#xff0c;量比大小到底意味着什么呢&#xff1f; 量比是衡量相对成交量的指标。它是指股市开市后平均每分钟的成交量与过去5个交易日平均每分钟成交量之比…

【高并发网络通信架构】4.高效事件驱动模型:Reactor 模型

目录 一&#xff0c;往期文章 二&#xff0c;基本概念 1.前言 2.基本框架 3.核心特征 4.工作流程 5.用“网络通信”来理解 Reactor 模型 三&#xff0c;代码实现 1.使用 epoll 进行多路复用实现 Reactor 模式的操作流程 2.Reactor 模式实现代码&#xff08;参考&…

【SQL】Your password has expired. To log in you must change it.......

在配置SQL的编辑器的时候&#xff0c;连接过程出现了如下的错误&#xff1a; Your password has expired. To log in you must change it using a client that supports expired passwords.当连接到 SQL 时&#xff0c;如果出现 “Your password has expired. To log in you m…

【LSTM】理解LSTM

原文&#xff1a;https://colah.github.io/posts/2015-08-Understanding-LSTMs/ 递归神经网路 Humans don;t start their thinking from scratch every second. 人类都不是每一秒都从零开始思考。 from scratch 从零开始 当你读到这篇文章时&#xff0c;你理解每个单词时&a…

会议音响系统麦克风阵列波束形成算法C语言实现

+v hezkz17进数字音频系统研究开发交流答疑 一 应用麦克风阵列波束成形算法做的项目产品 二 麦克风波束形成技术应用领域? 麦克风波束形成技术是一种利用多个麦克风阵列来实现声音定向捕捉和增强的技术。通过对多个麦克风信号进行处理和合成,可以使麦克风系统在特定方向…