SpringCloud微服务API网关Gateway的使用和配置(一)路由转发、断言谓词

一、介绍

实现微服务网关的技术有很多。

  1. nginx
    Nginx(enginex)是一个高性能的HTTP和反向代理web服务器,同时也提供 了IMAP/POP3/SMTP服务
  2. zuul ,
    Zuul 是 Netflix 出品的一个基于 JVM 路由和服务端的负载均衡器。
  3. spring-cloud-gateway,
    Gateway是spring 出品的 基于spring 的网关项目,集成断路器,路径重写,性能比Zuul好。

我们使用gateway这个网关技术,无缝衔接到基于spring cloud的微服务开发中来。

Gateway官网:https://spring.io/projects/spring-cloud-gateway

  1. Route(路由):
    这是网关的基本构建块。它由一个ID、一个URI、一组断言和一组过滤器定义。如果断言为真,则路由匹配。
  2. Predicate(断言):
    输入类型是一个 Serverwebexchange。我们可以使用它来匹配来自HTP请求的任何内容,例如 headers或参数。
  3. filter( 过滤器):
    Gateway中的 Filter分为两种类型的 Filter,分别是 GatewayFilterGlobal Filter。过滤器 Filter将会对请求和响应进行修改处理。

二、Gateway依赖

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

三、 Gateway网关的yml配置

自动转发配置

      discovery:
        locator:
          #开启从注册中心动态创建路由的功能,网关自动映射处理逻辑:http://gatewayIP:gatewayPort/微服务名称/微服务请求地址
          enabled: false # 把网关请求自动转发到微服务请求地址: http://微服务名称/微服务请求地址
          lower-case-service-id: true #开启服务名称小写装换,Eureka 对服务名称默认大写管理
          # ========以上配置就已经实现请求转发的功能了============
          # 如 http://localhost:9003/springcloud-alibaba-account/account/findAll 自动转发到 http://springcloud-alibaba-account/account/findAll
          # 商业开发中,enable 一般不设置,使用默认值false ,避免不必要的自动转发规则

跨域配置

      globalcors: # 跨域配置
        corsConfigurations:
          '[/**]':
            allowedHeaders: "*"
            allowedOrigins: "*"
            allowCredentials: true
            allowedMethods:
              - GET
              - POST
              - DELETE
              - PUT
              - OPTION

全局http超时配置

      httpclient: # 配置全局 http 超时
        connect-timeout: 1000 #必须以毫秒为单位指定
        response-timeout: 5s  #必须指定为 java.time.Duration

route (路由)配置

一个route包括 idpredicates(断言、谓词)、filters(过滤器)、uri 等属性。
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

        - id: account # 路由定义的命名 唯一即可
#          uri: http://localhost:9000
          uri: lb://springcloud-alibaba-account
         # 当前路由定义对应的转发地址 lb:服务名称 使用LoadBalancerClient 实现负载均衡
          #配置谓词集合 RoutePredicateFactory
          predicates:
            # 谓词名称是有套路的,是GatewayPredicate接口实现类的命名前缀 XxxRoutePredicateFactory
            - Path=/account/**,/aaa/** #定义一个谓词 格式:谓词名字=参数 或者 name:名字 args:参数 所有以/account/开始的请求都将路由到uri http://springcloud-alibaba-account
            # http://localhost:9004/account/account/findAll 转发到 http://localhost:9000/account/findAll
          # 配置过滤集合
          filters:
            - StripPrefix=1 # 将请求中的第一个路径去掉 请求路径以/区分,一个/表示一个路径,如:/api/account  会变成/account
            #- PrefixPath=/brand # 为请求路径添加前缀/brand

lb://微服务名实现负载均衡

Route中的uri属性中可以使用lb实现负载均衡。
通过 LoadBalancerClient 路由过滤器(客户端负载均衡)
在这里插入图片描述
在这里插入图片描述

例如:我们启动两个Account服务的实例:
先以9000端口启动Account服务,
然后修改接口返回信息,在以9001端口启动。
在这里插入图片描述

在这里插入图片描述

在浏览器访问:http://localhost:9004/aaa/account/findAll
在这里插入图片描述
在这里插入图片描述

看后台控制台打印信息:

9004网关服务:在这里插入图片描述
Account9000服务:
在这里插入图片描述
Account9001服务:
在这里插入图片描述

predicates (断言/谓词)配置

在这里插入图片描述
可以看到AbstractRoutePredicateFactory有许多的实现类,这些类的前缀就是我们谓词的参数,比如:Path、Header、Before、Query、Host、Method、Weight、Cookie、After、Between、Read等。

Path

        - id: account # 路由定义的命名 唯一即可
          uri: http://localhost:9000
          #uri: ld://springcloud-alibaba-account/ # 当前路由定义对应的转发地址 lb:服务名称 使用LoadBalancerClient 实现负载均衡
          #配置谓词集合 RoutePredicateFactory
          predicates:
            # 谓词名称是有套路的,是GatewayPredicate接口实现类的命名前缀 XxxRoutePredicateFactory
            - Path=/account/** #定义一个谓词 格式:谓词名字=参数 或者 name:名字 args:参数 
            # http://localhost:9004/account/account/findAll 转发到 http://localhost:9000/account/findAll
          # 配置过滤集合
          filters:
            - StripPrefix=1 # 将请求中的第一个路径去掉 请求路径以/区分,一个/表示一个路径,如:/api/good  会变成/good

        - id: baidu
          uri: https://www.baidu.com
          predicates:
            # http://localhost:9004/bd/ 转发至  https://www.baidu.com
            # 断言匹配到Path    转发 https://www.baidu.com/bd   去掉/bd路径
            - Path=/bd/**
          filters:
            - StripPrefix=1
            

比如 http://localhost:9004/account/account/findAll 就会被Path断言匹配到,而转发到 http://localhost:9000/account/account/findAll,经过StripPrefix会去除一个路径,最终变为:http://localhost:9000/account/findAll
在这里插入图片描述
在这里插入图片描述
http://localhost:9004/bd/ 可以断言匹配转发到百度,而http://localhost:9004/bd/a 则转发失败,原因是断言后的转发路径是https://www.baidu.com/a
在这里插入图片描述
在这里插入图片描述

Query

        - id: queryuri
          uri: https://www.qq.com/
          predicates:
            # http://localhost:9004/?uri=qq   转发至   https://www.qq.com
            # http://localhost:9004/?uri=qq&url=baidu   也可以转发到  https://www.qq.com
            # http://localhost:9004/?url=baidu&uri=qq   也可以转发到  https://www.qq.com
            # 由此可见: 只要路径中有uri=qq 就可以匹配转发  ,且断言匹配是由上到下的
            # uri中匹配qq
            - Query=uri,qq
          metadata: # 配置每条路由超时
            response-timeout: 200 # 必须以毫秒为单位指定。
            connect-timeout: 200  # 必须以毫秒为单位指定。
    
        - id: queryurl
          uri: https://www.baidu.com
          predicates:
            # http://localhost:9004/?url=baidu 转发至  https://www.baidu.com 
            # url 中匹配 baidu 
            - Query=url,baidu
                            
        - id: queayname
          uri: https://www.baidu.com
          predicates:
            # 参数name的值包含zs则会匹配成功
            - Query=name,zs.*

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

Header

        - id: header
          uri: http://localhost:9000
          predicates:
            # http://localhost:9004/header/account/findAll 转发至 http://localhost:9000/account/findAll
            # 路径匹配 header ,请求头中必须myheader:zhangsan  并去除 一个路径 header 才能成功转发
            - Path=/header/**
            - name: Header
              args:
                # key: value
                header: myheader
                regexp: zhangsan.*
          filters:
            - StripPrefix=1

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
如果没有匹配断言的请求头信息,则不会被转发:
在这里插入图片描述

Method

        - id: queayname
          uri: https://www.baidu.com
          predicates:
            # http://localhost:9004/?url=baidu 转发至  https://www.baidu.com
            - Query=name,zs.*
            - Method=GET

使用Method属性指定方法的请求格式,如以上配置只允许GET请求:
在这里插入图片描述
在这里插入图片描述
如果修改为:- Method=GET,POST,则允许GET和POST请求:
在这里插入图片描述

Cookie

        - id: queryurl
          uri: https://www.baidu.com
          predicates:
            # http://localhost:9004/?url=baidu 转发至  https://www.baidu.com
            - Query=url,baidu
            # Cookie 接收两个参数,cookie 名字和一个正则表达式。 判断请求cookie是否具有给定名称且值与正则表达式匹配。
            - Cookie= username,admin.*

在浏览器页面访问,没有添加Cookie,不转发:
在这里插入图片描述

PostMan手动添加Cookie
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

After、Before、Between

After:在时间之后进行转发,之前不转发。
Before:在时间之前的进行转发,之后不转发。
Between:即在时间分为之内的才进行转发。

        - id: queayname
          uri: https://www.baidu.com
          predicates:
            # http://localhost:9004/?url=baidu 转发至  https://www.baidu.com
            - Query=name,zs.*
              # 请求方法 GET、POST、 PUT、DELETE
            - Method=GET,POST
              # IP地址 判断请求主机地址是否在地址段中,将匹配192.168.1.1~192.168.1.254之间的IP地址 其中24为子网掩码255.255.255.0          172.30.0.105
#            - RemoteAddr=192.168.1.1/24
            # Cookie 接收两个参数,cookie 名字和一个正则表达式。 判断请求cookie是否具有给定名称且值与正则表达式匹配。
#            - Cookie= username,admin.*
              # 时间之前  不做转发
            - After= 2021-08-01T00:00:00.000+08:00[Asia/Shanghai]
              # 时间之后  不做转发
            - Before=2021-08-03T14:03:00.789+08:00[Asia/Shanghai]
              # 请求必须在设定是时间之内才能请求转发
            - Between=2021-08-01T00:00:00.000+08:00[Asia/Shanghai],2021-08-03T14:03:00.789+08:00[Asia/Shanghai]

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

Weight

负载均衡中的权重,同一个组中URI进行负载均衡 语法: weight=组名,负载均衡权重,两个的路由的Path是一样的, 但是组名都是 orderGroup 其中80%被转发到order-one,20%被转发到 order-two。
一般用于多版本发布的时候。

        - id: weight1
          uri: ld://order-one
          predicates:
              -Path=/order/**
              # 负载均衡中的权重,同一个组中URI进行负载均衡  语法: weight=组名,负载均衡权重
              -Weight=orderGroup,8
          filters:
            - StripPrefix=1
        - 
        - id: weight2
          uri: ld://order-two
          predicates:
              -Path=/order/**
              # 两个的路由的Path是一样的, 但是组名都是 orderGroup 其中80%被转发到order-one,20%被转发到 order-two
              -Weight=orderGroup,2
          filters:
            - StripPrefix=1

Host 、RemoteAddr

这两个不知道怎么用:
Host:判断请求的Host是否满足匹配规则。
RemoteAddr:接收一个IP地址段,判断请求主机地址是否在地址段中。

filters(过滤器)配置

PrefixPath

-PrefixPath :添加一个路径

          filters:
            - PrefixPath=/brand # 为请求路径添加前缀/brand

在这里插入图片描述

StripPrefix

请求路径以 / 区分 一个/代表一个路径
-StripPrefix:去掉一个路径

          filters:
            - StripPrefix=1

四、完整yml配置

server:
  port: 9004
spring:
  application:
    # 应用名称
    name: api-service
#  profiles:
    # 环境配置
#    active: dev
  cloud:
    nacos:
      discovery:
        # 服务注册地址
        server-addr: 127.0.0.1:8848
    gateway:
      httpclient: # 配置全局 http 超时
        connect-timeout: 1000 #必须以毫秒为单位指定
        response-timeout: 5s  #必须指定为 java.time.Duration
      globalcors: # 跨域配置
        corsConfigurations:
          '[/**]':
            allowedHeaders: "*"
            allowedOrigins: "*"
            allowCredentials: true
            allowedMethods:
              - GET
              - POST
              - DELETE
              - PUT
              - OPTION
      discovery:
        locator:
          #开启从注册中心动态创建路由的功能,网关自动映射处理逻辑:http://gatewayIP:gatewayPort/微服务名称/微服务请求地址
          enabled: false # 把网关请求自动转发到微服务请求地址: http://微服务名称/微服务请求地址
          lower-case-service-id: true #开启服务名称小写装换,Eureka 对服务名称默认大写管理
          # ========以上配置就已经实现请求转发的功能了============
          # 商业开发中,enable 一般不设置,使用默认值false ,避免不必要的自动转发规则
      routes:
        # 配置网关中的一个完整路由 包括 命名、地址、谓词集合(规则)、过滤器集合
        # Spring系列配置文件中,可以直接使用字符串赋值的类型有哪些?
        # 8种基本数据类型、包装类型、String、URI统一资源路径地址、Class、Resource资源文件位置:classpath:xx/*.xml
        - id: queryuri
          uri: https://www.qq.com/
          predicates:
            # http://localhost:9004/?uri=qq   转发至   https://www.qq.com
            # http://localhost:9004/?uri=qq&url=baidu   也可以转发到  https://www.qq.com
            # http://localhost:9004/?url=baidu&uri=qq   也可以转发到  https://www.qq.com
            # 由此可见: 只要路径中有uri=qq 就可以匹配转发  ,且断言匹配是由上到下的
            - Query=uri,qq
          metadata: # 配置每条路由超时
            response-timeout: 200 # 必须以毫秒为单位指定。
            connect-timeout: 200  # 必须以毫秒为单位指定。

        - id: queryurl
          uri: https://www.baidu.com
          predicates:
            # http://localhost:9004/?url=baidu 转发至  https://www.baidu.com
            - Query=url,baidu
            # Cookie 接收两个参数,cookie 名字和一个正则表达式。 判断请求cookie是否具有给定名称且值与正则表达式匹配。
            - Cookie= username,admin.*

        - id: queayname
          uri: https://www.baidu.com
          predicates:
            # http://localhost:9004/?url=baidu 转发至  https://www.baidu.com
            - Query=name,zs.*
              # 请求方法 GET、POST、 PUT、DELETE
            - Method=GET,POST
              # 时间之前  不做转发
            - After= 2021-08-01T00:00:00.000+08:00[Asia/Shanghai]
              # 时间之后  不做转发
#            - Before=2021-08-03T14:03:00.789+08:00[Asia/Shanghai]
              # 请求必须在设定是时间之内才能请求转发
#            - Between=2021-08-01T00:00:00.000+08:00[Asia/Shanghai],2021-08-03T14:03:00.789+08:00[Asia/Shanghai]

        - id: weight1
          uri: ld://order-one
          predicates:
              - Path=/order/**
              # 负载均衡中的权重,同一个组中URI进行负载均衡  语法: weight=组名,负载均衡权重
              - Weight=orderGroup,8
          filters:
            - StripPrefix=1
        - id: weight2
          uri: ld://order-two
          predicates:
              - Path=/order/**
              # 两个的路由的Path是一样的, 但是组名都是 orderGroup 其中80%被转发到order-one,20%被转发到 order-two
              - Weight=orderGroup,2
          filters:
            - StripPrefix=1


        - id: pathbaidu
          uri: https://www.baidu.com
          predicates:
            # http://localhost:9004/bd/ 转发至  https://www.baidu.com
            # 断言匹配到Path    转发 https://www.baidu.com/bd   去掉/bd路径
            - Path=/bd/**
          filters:
            - StripPrefix=1

        - id: header
          uri: http://localhost:9000
          predicates:
            # http://localhost:9004/header/account/findAll 转发至 http://localhost:9000/account/findAll
            # 路径匹配 header ,请求头中必须myheader:zhangsan  并去除 一个路径 header 才能成功转发
            - Path=/header/**
            - name: Header
              args:
                # key: value
                header: myheader
                regexp: zhangsan.*
          filters:
            - StripPrefix=1

        # 账户服务
        - id: account # 路由定义的命名 唯一即可
#          uri: http://localhost:9000
          uri: lb://springcloud-alibaba-account
         # 当前路由定义对应的转发地址 lb:服务名称 使用LoadBalancerClient 实现负载均衡
          #配置谓词集合 RoutePredicateFactory
          predicates:
            # 谓词名称是有套路的,是GatewayPredicate接口实现类的命名前缀 XxxRoutePredicateFactory
            - Path=/account/**,/aaa/** #定义一个谓词 格式:谓词名字=参数 或者 name:名字 args:参数 所有以/account/开始的请求都将路由到uri http://springcloud-alibaba-account
            # http://localhost:9004/account/account/findAll 转发到 http://localhost:9000/account/findAll
          # 配置过滤集合
          filters:
            - StripPrefix=1 # 将请求中的第一个路径去掉 请求路径以/区分,一个/表示一个路径,如:/api/account  会变成/account
            #- PrefixPath=/brand # 为请求路径添加前缀/brand
        # 订单服务
        - id: order
          uri: lb://springcloud-alibaba-order
          predicates:
            - Path=/order/**
          filters:
            - StripPrefix=1
        # 库存服务
        - id: storage
          uri: lb://springcloud-alibaba-storage
          predicates:
            - Path=/storage/**
          filters:
            - StripPrefix=1



下一章

SpringCloud微服务API网关Gateway的使用和配置(二)过滤器:
https://blog.csdn.net/DreamsArchitects/article/details/119351793

五、源码

源码已上传码云:
https://gitee.com/L1692312138/spring-cloud-alibaba

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Liu_Shihao

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值