spring cloud gateway一些相关概念

在云架构中运行着众多客户端和服务端,API网关的存在提供了保护和路由消息,隐藏服务,限制负载等等功能。下图是spring cloud gateway所处的位置。

它有三大概念:

路由:路由是构建网关的基本模块,它由ID,目标URI,一系列的断言Predicates和过滤器Filters组成,如果断言为true,则匹配该路由。

断言:参考Java8的java.util.function.Predicate,开发人员可以匹配HTTP请求中的所有内容,例如请求头或请求参数,如果请求与断言相匹配则进行路由。

过滤:Spring框架中GatewayFilter的实例,使用过滤器,可以载请求被路由前或者后对请求进行修改。

工作流程图如下:

SpringCloud Gateway 和nginx 都在流量进入服务前做一些处理, 那谁先执行呢,他们之间有联系吗 ?

在微服务架构中,SpringCloud Gateway和Nginx的执行顺序和它们之间的联系主要取决于你的具体配置和架构设计。

  1. 执行顺序

    • 如果你将Nginx用作反向代理服务器,并且将所有入站流量都首先路由到Nginx,那么Nginx将首先执行。Nginx可以根据其配置将请求转发到后端的SpringCloud Gateway或其他微服务。
    • 如果SpringCloud Gateway是直接暴露给外部用户的,那么它将首先执行。但是,你仍然可以在SpringCloud Gateway之前使用Nginx作为反向代理,以增加额外的安全性、负载均衡或其他功能。
  2. 联系

    • 反向代理:Nginx经常被用作反向代理服务器,将外部请求转发到后端的SpringCloud Gateway或其他微服务。这可以为你的架构提供额外的安全性、负载均衡和缓存功能。
    • 负载均衡:Nginx和SpringCloud Gateway都支持负载均衡功能。Nginx可以在其配置中定义负载均衡规则,将请求分发到多个SpringCloud Gateway实例或其他微服务实例上。同样,SpringCloud Gateway也可以配置负载均衡策略,将请求路由到后端的微服务实例。
    • 安全性:Nginx和SpringCloud Gateway都可以提供安全性功能,如SSL终止、IP白名单、基本身份验证等。但是,它们的安全性功能可能有所不同,具体取决于你的配置和需求。
    • 解耦和细分:在某些情况下,Nginx可能不再承担服务的路由分发和负载均衡的角色,而是将这些功能转交给更专业的工具(如SpringCloud Gateway)来处理。这是一种解耦和细分的表现,可以使你的架构更加灵活和可扩展。

Nginx和SpringCloud Gateway之间可以存在紧密的联系,但也可以完全独立地运行。需要根据你的具体需求和架构设计来决定如何配置和使用它们。

那SpringCloud Gateway 和spring security谁先执行呢?

在Spring Cloud微服务架构中,SpringCloud GatewaySpring Security的执行顺序取决于它们是如何配置和集成的。但通常来说,SpringCloud Gateway作为API网关,会首先接收到来自客户端的请求,并在处理这些请求时可能会涉及到Spring Security的安全检查。

以下是它们之间可能的工作流程:

  1. 客户端发起请求:客户端(如Web浏览器、移动应用或其他服务)向API网关(即SpringCloud Gateway)发起HTTP请求。
  2. SpringCloud Gateway接收请求:SpringCloud Gateway作为API网关,会首先接收到这些请求。它会根据配置的路由规则来确定将请求转发到哪个微服务。
  3. SpringCloud Gateway的安全检查(如果配置):在转发请求之前,SpringCloud Gateway可能会执行一些安全检查。这些检查可能包括验证请求头、请求参数或JWT令牌等。这些安全检查可以通过自定义的过滤器(Filter)来实现,这些过滤器可以在请求被转发到微服务之前对请求进行拦截和处理。
  4. 转发请求到微服务:如果请求通过了SpringCloud Gateway的安全检查(如果有的话),那么它就会被转发到相应的微服务。
  5. Spring Security在微服务中的执行:当请求到达微服务时,如果微服务配置了Spring Security,那么Spring Security就会执行相应的安全检查。这些检查可能包括验证用户的身份(如用户名和密码登录、OAuth令牌等)、检查用户是否有权访问请求的资源等。
  6. 微服务处理请求并返回响应:如果请求通过了Spring Security的安全检查,那么微服务就会处理该请求并返回响应。这个响应会经过SpringCloud Gateway返回给客户端。

SpringCloud Gateway和Spring Security的安全检查是独立的,它们可以分别配置和执行。在某些情况下,你可能需要在SpringCloud Gateway中执行一些安全检查(如验证JWT令牌),然后在微服务中执行更细粒度的安全检查(如基于角色的访问控制)。这取决于具体需求和架构设计。

spring cloud gateway 断言配置:

java 复制代码
        predicates:
        - Before=2017-01-20T17:42:47.789-07:00[America/Denver]  # 在..之前可以匹配
        - After=2017-01-20T17:42:47.789-07:00[America/Denver]   # 在..之后可以匹配
        - Between=xxx,xxx										# 在..之间可以匹配
        - Cookie=chocolate, ch.p								# 带cookie
        - Header=X-Request-Id, \d+								# 规定header
        - Host=**.somehost.org,**.anotherhost.org				# 规定host
        - Method=GET,POST										# 规定请求方法
        - Path=/red/{segment},/blue/{segment}					# 规定请求路径
        - Query=green											# 规定请求参数
        - RemoteAddr=192.168.1.1/24								# 规定remoteAddr
        
        # 将80%的流量转到weighthigh.org,20%转到weightlow.org
      - id: weight_high
        uri: https://weighthigh.org
        predicates:
        - Weight=group1, 8
      - id: weight_low
        uri: https://weightlow.org
        predicates:
        - Weight=group1, 2

例子:假如有两个相同的服务实例cloud-payment-service(即它们提供相同的功能和API),并且你希望它们能够共同分担负载(即实现负载均衡,端口分别为8001和8002),现在通过gateway的断言设置分别请求这两个服务里的/payment/hello方法。

gateway的yml配置:

XML 复制代码
server:
  port: 9527

spring:
  application:
    name: cloud-gateway
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true #开启从注册中心动态创建路由的功能,利用微服务名进行路由
      routes:
        - id: payment_routh #payment_route    #路由的ID,没有固定规则但要求唯一,建议配合服务名
          #uri: http://localhost:8001          #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service #匹配后提供服务的路由地址
          predicates:
            - Path=/payment1/**         # 断言,路径相匹配的进行路由
            - After=2020-11-26T21:27:26.256+08:00[Asia/Shanghai]

        - id: payment_routh2 #payment_route    #路由的ID,没有固定规则但要求唯一,建议配合服务名
          #uri: http://localhost:8001          #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service #匹配后提供服务的路由地址
          predicates:
            - Path=/payment2/lb/**         # 断言,路径相匹配的进行路由
            - After=2020-11-25T22:42:23.608+08:00[Asia/Shanghai]
            - Cookie=username,hyh
            #- Header=X-Request-Id, \d+  # 请求头要有X-Request-Id属性并且值为整数的正则表达式
#            - Host=**.somehost.org,**.anotherhost.org  # 匹配hostname
#            - Method=GET,POST
#            - Path=/red/{segment},/blue/{segment}
#            - Query=green
#            - RemoteAddr=192.168.1.1/24
#            - Weight=group1, 2
        - id: payment_routh3 #payment_route    #路由的ID,没有固定规则但要求唯一,建议配合服务名
          #uri: http://localhost:8001          #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service #匹配后提供服务的路由地址
          predicates:
            - Path=/payment/hello         # 断言,路径相匹配的进行路由
            - After=2020-11-25T22:42:23.608+08:00[Asia/Shanghai]
            - Cookie=username,hyh
            - Header=X-Request-Num, \d+
eureka:
  instance:
    hostname: cloud-gateway-service
    instance-id: gateway9527
    prefer-ip-address: true
  client: #服务提供者provider注册进eureka服务列表内
    service-url:
      register-with-eureka: true
      fetch-registry: true
      defaultZone: http://eureka7001.com:7001/eureka

8001的服务的方法:

java 复制代码
 @GetMapping("/payment/hello")
 public String helloNum() {
        log.info("(8001)/payment/hello 执行了");
        return serverPort + "/payment/hello 执行了";
 }

8002的服务的方法:

java 复制代码
@GetMapping("/payment/hello")
public String helloNum() {
        log.info("(8001)/payment/hello 执行了");
        return serverPort + "/payment/hello 执行了";
}

设置请求参数:

连点两次发送请求gateway服务,发现两次分别调用了两个服务的同一个方法:

如果将请求头header或者cookies设置为错误的值,不满足断言,gateway则不转发这个请求:

相关推荐
学会沉淀。4 分钟前
Docker学习
java·开发语言·学习
如若1236 分钟前
对文件内的文件名生成目录,方便查阅
java·前端·python
西猫雷婶35 分钟前
python学opencv|读取图像(二十一)使用cv2.circle()绘制圆形进阶
开发语言·python·opencv
kiiila35 分钟前
【Qt】对象树(生命周期管理)和字符集(cout打印乱码问题)
开发语言·qt
初晴~36 分钟前
【Redis分布式锁】高并发场景下秒杀业务的实现思路(集群模式)
java·数据库·redis·分布式·后端·spring·
小_太_阳1 小时前
Scala_【2】变量和数据类型
开发语言·后端·scala·intellij-idea
直裾1 小时前
scala借阅图书保存记录(三)
开发语言·后端·scala
黑胡子大叔的小屋1 小时前
基于springboot的海洋知识服务平台的设计与实现
java·spring boot·毕业设计
ThisIsClark1 小时前
【后端面试总结】深入解析进程和线程的区别
java·jvm·面试
唐 城1 小时前
curl 放弃对 Hyper Rust HTTP 后端的支持
开发语言·http·rust