微服务SpringCloud之GateWay路由

在前面博客学习了网关zuul,今天学下spring官方自带的网关spring cloud gateway。Zuul(1.x) 基于 Servlet,使用阻塞 API,它不支持任何长连接,如 WebSockets,Spring Cloud Gateway 使用非阻塞 API,支持 WebSockets,支持限流等新特性。

Spring Cloud Gateway 是 Spring Cloud 的一个全新项目,该项目是基于 Spring 5.0,Spring Boot 2.0 和 Project Reactor 等技术开发的网关,它旨在为微服务架构提供一种简单有效的统一的 API 路由管理方式。

Spring Cloud Gateway 作为 Spring Cloud 生态系统中的网关,目标是替代 Netflix Zuul,其不仅提供统一的路由方式,并且基于 Filter 链的方式提供了网关基本的功能,例如:安全,监控/指标,和限流。

相关概念:

Route(路由):这是网关的基本构建块。它由一个 ID,一个目标 URI,一组断言和一组过滤器定义。如果断言为真,则路由匹配。
Predicate(断言):这是一个 Java 8 的 Predicate。输入类型是一个 ServerWebExchange。我们可以使用它来匹配来自 HTTP 请求的任何内容,例如 headers 或参数。
Filter(过滤器):这是org.springframework.cloud.gateway.filter.GatewayFilter的实例,我们可以使用它修改请求和响应。
工作流程:

客户端向 Spring Cloud Gateway 发出请求。如果 Gateway Handler Mapping 中找到与请求相匹配的路由,将其发送到 Gateway Web Handler。Handler 再通过指定的过滤器链来将请求发送到我们实际的服务执行业务逻辑,然后返回。 过滤器之间用虚线分开是因为过滤器可能会在发送代理请求之前(”pre”)或之后(”post”)执行业务逻辑。

Spring Cloud Gateway 的特征:

  1. 基于 Spring Framework 5,Project Reactor 和 Spring Boot 2.0
  2. 动态路由
  3. Predicates 和 Filters 作用于特定路由
  4. 集成 Hystrix 断路器
  5. 集成 Spring Cloud DiscoveryClient
  6. 易于编写的 Predicates 和 Filters
  7. 限流
  8. 路径重写

Spring Cloud Gateway 网关路由有两种配置方式,这里建议使用yml进行配置。

  1. 在配置文件 yml 中配置
  2. 通过@Bean自定义 RouteLocator,在启动主类 Application 中配置

我们先实现一个简单的路由转发的demo:

1.引入依赖

这里需要引入spring-cloud-starter-gateway。

微服务SpringCloud之GateWay路由
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.1.7.RELEASEversion>
<relativePath/>
parent>
<groupId>com.examplegroupId>
<artifactId>SpringCloudGatewayDemoartifactId>
<version>0.0.1-SNAPSHOTversion>
<packaging>warpackaging>
<name>SpringCloudGatewayDemoname>
<description>Demo project for Spring Bootdescription>
<span>&lt;</span><span>properties</span><span>&gt;</span>
    <span>&lt;</span><span>java.version</span><span>&gt;</span>1.8<span><span>java.version</span><span>&gt;</span>
    <span>&lt;</span><span>spring-cloud.version</span><span>&gt;</span>Greenwich.SR2<span><span>spring-cloud.version</span><span>&gt;</span>
<span><span>properties</span><span>&gt;</span>

<span>&lt;</span><span>dependencies</span><span>&gt;</span>
    <span>&lt;</span><span>dependency</span><span>&gt;</span>
        <span>&lt;</span><span>groupId</span><span>&gt;</span>org.springframework.cloud<span><span>groupId</span><span>&gt;</span>
        <span>&lt;</span><span>artifactId</span><span>&gt;</span>spring-cloud-starter-gateway<span><span>artifactId</span><span>&gt;</span>
    <span><span>dependency</span><span>&gt;</span>
    <span>&lt;</span><span>dependency</span><span>&gt;</span>
        <span>&lt;</span><span>groupId</span><span>&gt;</span>org.springframework.boot<span><span>groupId</span><span>&gt;</span>
        <span>&lt;</span><span>artifactId</span><span>&gt;</span>spring-boot-starter-test<span><span>artifactId</span><span>&gt;</span>
        <span>&lt;</span><span>scope</span><span>&gt;</span>test<span><span>scope</span><span>&gt;</span>
    <span><span>dependency</span><span>&gt;</span>
<span><span>dependencies</span><span>&gt;</span>

<span>&lt;</span><span>dependencyManagement</span><span>&gt;</span>
    <span>&lt;</span><span>dependencies</span><span>&gt;</span>
        <span>&lt;</span><span>dependency</span><span>&gt;</span>
            <span>&lt;</span><span>groupId</span><span>&gt;</span>org.springframework.cloud<span><span>groupId</span><span>&gt;</span>
            <span>&lt;</span><span>artifactId</span><span>&gt;</span>spring-cloud-dependencies<span><span>artifactId</span><span>&gt;</span>
            <span>&lt;</span><span>version</span><span>&gt;</span>${spring-cloud.version}<span><span>version</span><span>&gt;</span>
            <span>&lt;</span><span>type</span><span>&gt;</span>pom<span><span>type</span><span>&gt;</span>
            <span>&lt;</span><span>scope</span><span>&gt;</span>import<span><span>scope</span><span>&gt;</span>
        <span><span>dependency</span><span>&gt;</span>
    <span><span>dependencies</span><span>&gt;</span>
<span><span>dependencyManagement</span><span>&gt;</span>

<span>&lt;</span><span>build</span><span>&gt;</span>
    <span>&lt;</span><span>plugins</span><span>&gt;</span>
        <span>&lt;</span><span>plugin</span><span>&gt;</span>
            <span>&lt;</span><span>groupId</span><span>&gt;</span>org.springframework.boot<span><span>groupId</span><span>&gt;</span>
            <span>&lt;</span><span>artifactId</span><span>&gt;</span>spring-boot-maven-plugin<span><span>artifactId</span><span>&gt;</span>
        <span><span>plugin</span><span>&gt;</span>
    <span><span>plugins</span><span>&gt;</span>
<span><span>build</span><span>&gt;</span>

project>

View Code

2.创建application.yml增加配置

server:
  port: 8081
spring:
  cloud:
    gateway:
      routes:
      - id: neo_route
        uri: http://www.cnblogs.com
        predicates:
          - Path=/5ishare

各字段含义如下:

id:我们自定义的路由 ID,保持唯一
uri:目标服务地址
predicates:路由条件,Predicate 接受一个输入参数,返回一个布尔值结果。该接口包含多种默认方法来将 Predicate 组合成其他复杂的逻辑(比如:与,或,非)。
filters:过滤规则,本示例暂时没用。

上面这段配置的意思是,配置了一个 id 为 neo_route 的路由规则,当访问地址 http://localhost:8081/5ishare时会自动转发到地址:http://www.cnblogs.com/spring-cloud。配置完成启动项目即可在浏览器访问进行测试,当我们访问地址http://localhost:8080/5ishare 时会展示https://www.cnblogs.com/5ishare页面。

路由规则

Spring Cloud Gateway 的功能很强大,我们仅仅通过 Predicates 的设计就可以看出来,前面我们只是使用了 predicates 进行了简单的条件匹配,其实 Spring Cloud Gataway 帮我们内置了很多 Predicates 功能。

Spring Cloud Gateway 是通过 Spring WebFlux 的 HandlerMapping 做为底层支持来匹配到转发路由,Spring Cloud Gateway 内置了很多 Predicates 工厂,这些 Predicates 工厂通过不同的 HTTP 请求参数来匹配,多个 Predicates 工厂可以组合使用。

Predicate 介绍
Predicate 来源于 Java 8,是 Java 8 中引入的一个函数,Predicate 接受一个输入参数,返回一个布尔值结果。该接口包含多种默认方法来将 Predicate 组合成其他复杂的逻辑(比如:与,或,非)。可以用于接口请求参数校验、判断新老数据是否有变化需要进行更新操作。

在 Spring Cloud Gateway 中 Spring 利用 Predicate 的特性实现了各种路由匹配规则,有通过 Header、请求参数等不同的条件来进行作为条件匹配到对应的路由。网上有一张图总结了 Spring Cloud 内置的几种 Predicate 的实现。

微服务SpringCloud之GateWay路由

通过时间匹配
Predicate 支持设置一个时间,在请求进行转发的时候,可以通过判断在这个时间之前或者之后进行转发。这里使用After来设置该时间之后转发,Before来设置该时间之前转发,Between来设置该时间区间端转发。在测试的过程中开始设置After转发之后再修改另外两个Before和Between时不起作用了,需要清下浏览器缓存。

server:
  port: 8081
spring:
  cloud:
    gateway:
      routes:
       - id: time_route
         uri: http://www.cnblogs.com
         predicates:
          -After=2019-11-03T10:20:06+08:00[Asia/Shanghai]
         - Before=2019-11-03T10:55:06+08:00[Asia/Shanghai]
         - Between=2019-11-03T11:01:06+08:00[Asia/Shanghai], 2019-11-03T11:05:06+08:00[Asia/Shanghai]

通过 Cookie 匹配

Cookie Route Predicate 可以接收两个参数,一个是 Cookie name ,一个是正则表达式,路由规则会通过获取对应的 Cookie name 值和正则表达式去匹配,如果匹配上就会执行路由,如果没有匹配上则不执行。如下图所示,当在请求的Cookie中添加name=cuiyw时跳转到http://www.cnblogs.com,当不添加时报404错误。

微服务SpringCloud之GateWay路由

通过 Header 属性匹配

Header Route Predicate 和 Cookie Route Predicate 一样,也是接收 2 个参数,一个 header 中属性名称和一个正则表达式,这个属性值和正则表达式匹配则执行。如下图所示当设置X-Request-Id=6666时页面跳转正常,当设置为cuiyw时报404错。

server:
  port: 8081
spring:
  cloud:
    gateway:
      routes:
       - id: cookie_route
         uri: http://www.cnblogs.com
         predicates:
           - Cookie=name,cuiyw
           - Header=X-Request-Id, \d+

微服务SpringCloud之GateWay路由

微服务SpringCloud之GateWay路由

通过 Host 匹配

Host Route Predicate 接收一组参数,一组匹配的域名列表,这个模板是一个 ant 分隔的模板,用 .号作为分隔符。它通过参数中的主机地址作为匹配规则。这里没测试出来,暂时略过。

通过请求方式匹配

可以通过是 POST、GET、PUT、DELETE 等不同的请求方式来进行路由,如下配置文件配置的是使用Get请求来进行路由,如果使用post则报404错误

server:
  port: 8081
spring:
  cloud:
    gateway:
      routes:
       - id: method_route
         uri: http://www.cnblogs.com
         predicates:
          - Method=GET

微服务SpringCloud之GateWay路由

通过请求路径匹配

Path Route Predicate 接收一个匹配路径的参数来判断是否走路由。当输入http://localhost:8081/5ishare时报404错误,当输入http://localhost:8081/5ishare/p正常跳转。

server:
  port: 8081
spring:
  cloud:
    gateway:
      routes:
       - id: method_route
         uri: http://www.cnblogs.com
         predicates:
          - Method=GET
          - Path=/5ishare/{segment}

微服务SpringCloud之GateWay路由

通过请求参数匹配

Query Route Predicate 支持传入两个参数,一个是属性名一个为属性值,属性值可以是正则表达式。当输入http://localhost:8081/5ishare时报404错误,当输入http://localhost:8081/5ishare?name=cuiyw时跳转正常

微服务SpringCloud之GateWay路由

通过请求 ip 地址进行匹配

Predicate 也支持通过设置某个 ip 区间号段的请求才会路由,RemoteAddr Route Predicate 接受 cidr 符号(IPv4 或 IPv6 )字符串的列表(最小大小为1),例如 192.168.0.1/16 (其中 192.168.0.1 是 IP 地址,16 是子网掩码)。这个目前没找到验证方法,暂时略过。

组合使用

在上面的例子有就能看到多个匹配组合在一起使用。例如通过Header属性匹配中设置了Cookie和Header。

Original: https://www.cnblogs.com/5ishare/p/11785687.html
Author: 社会主义接班人
Title: 微服务SpringCloud之GateWay路由

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/542040/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • HashMap原理

    Java7 : 数组 + 链表 Java8: 数组 + 链表 + 红黑树 (链表超过8则转为红黑树,小于6则变会链表) >> 加快查询. 源码如下: 参数解释: DEF…

    Java 2023年6月8日
    068
  • java —— 异步任务失败后处理

    场景: 实际项目中,程序操作出了问题,后续要怎么处理是个很重要的问题,如果这个问题是同步操作引起的解决起来比较简单,比如用户注册,如果系统注册失败,后台可以马上返回错误信息,用户也…

    Java 2023年5月29日
    093
  • IO(异常处理)

    程序的异常:Throwable* 严重问题:Error 我们不处理。这种问题一般都是很严重的,比如说内存溢出。* 问题:ExceptionA:编译期问题:不是RuntimeExce…

    Java 2023年6月5日
    0109
  • Spring(三)-AOP

    1、名词理解 切面(Aspect): 含有前置通知,后置通知,返回通知,异常抛出通知,环绕通知等方法的 类; 通知(Advice): 对原方法进行添加处理(如日志等)的 方法; 切…

    Java 2023年6月15日
    078
  • 基于开源方案构建统一的文件在线预览与office协同编辑平台的架构与实现历程

    大家好,又见面了。 在构建业务系统的时候,经常会涉及到对附件的支持,继而又会引申出对附件 &#x5728;&#x7EBF;&#x9884;&#x89…

    Java 2023年6月7日
    0106
  • 5.Hystrix简介

    Hystrix介绍 Hystrix是用于处理延迟和容错的开源库 Hystrix主要用于避免级联故障,提高系统弹性 Hystrix解决了由于扇出导致的”雪崩效应&#822…

    Java 2023年6月8日
    085
  • Java高并发教程:Reactor反应器模式

    Java高并发教程:Reactor反应器模式 Reactor反应器模式 到目前为止, 高性能网络编程都绕不开反应器模式。很多著名的服务器软件或者中间件都是基于反应器模式实现的,如N…

    Java 2023年5月29日
    067
  • HM2022ssm-mp2【MyBatisPlus标准数据层开发】

    标准CRUD使用 新增 @Test public void testSave() { User user = new User(); user.setName("黑马程序…

    Java 2023年6月5日
    095
  • RabbitMQ镜像集群配置

    上面已经完成RabbitMQ默认集群模式, 但并不保证队列的高可用性,队列内容不会复制。如果队列节点宕机直接导致该队列无法应用,只能等待重启,所以要想在队列节点宕机或故障也能正常应…

    Java 2023年5月30日
    083
  • 7月8日 学习日记

    HashMap 通过扩容可以减少链表长度 当链表长度超过8时会扩容 当数组长度到达64且链表长度超过8个的时候会转化成红黑树 红黑树 左结点都是比结点小 右结点都是比结点大 先比较…

    Java 2023年6月6日
    089
  • IDEA中项目创建和git常用操作

    20221118新增视频教程http://doc.canglaoshi.org/doc/git/push/push.htmlhttp://doc.canglaoshi.org/do…

    Java 2023年6月5日
    099
  • 并发编程之:线程

    大家好,我是小黑,一个在互联网苟且偷生的农民工。前段时间公司面试招人,发现好多小伙伴虽然已经有两三年的工作经验,但是对于一些Java基础的知识掌握的都不是很扎实,所以小黑决定开始跟…

    Java 2023年6月7日
    091
  • [Java] 详细解说final关键字

    final final 可以修饰变量、方法和类,表示所修饰的内容一旦赋值之后就不会再被改变。例如 String类就是一个 final类型的类。 1.具体使用场景 1.1 变量 1….

    Java 2023年6月5日
    0101
  • SpringBoot+Mybatis配置多数据源,分包方式

    看了不少网上关于多数据源的配置,大致可分为两类,分包方式和通过切面方式; 第一个子项目ds01即时使用分包方式完成多数据源配置。 总结项目中出现的问题和解决办法: 数据库的连接信息…

    Java 2023年6月8日
    0114
  • 用antlr的grammar获得java ast

    anttlr的代码样例:https://github.com/antlr/grammars-v4.git 很早之前就想基于java的语法树做一些事情,今天再次弄来看看。 基于ant…

    Java 2023年5月29日
    095
  • java基础篇—-数组

    数组是有序数据的集合,数组中的每个元素具有相同的数据类型,可以用一个统一的数组名和不同的下标来唯一确定数组中的元素. 一、一维数组 1.声明 数据类型[] 数组名; 或者是 数据类…

    Java 2023年6月8日
    098
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球