前言

在深入探讨Spring Cloud Gateway的细节之前,让我们了解有关反向代理和api网关模式的一些基础知识。

什么是反向代理?

反向代理是代表其他事物进行请求的事物。它的行为更像是简单的路由。它可以增加基本的安全性和监视功能,但实际上不能做某些高级事情,例如中介或业务流程。NGINX是众所周知的反向代理服务器之一。

什么是API网关?

简而言之,API Gateway是增强的反向代理,具有更高级的功能,包括编排以及增加的安全性和监视功能。Netflix Zuul(上文介绍),Amazon API Gateway,Apigee以及Spring Cloud Gateway当然是少数著名的api网关实现。

Spring Cloud Gateway主要功能:

  • 建立在Spring Framework 5,Project Reactor(后面我会单独开篇幅去介绍reactor3)和Spring Boot 2.0之上

  • 能够匹配任何请求属性上的路由。

  • 谓词和过滤器特定于路由。

  • 断路器集成。

  • Spring Cloud DiscoveryClient集成

  • 易于编写的谓词和过滤器

  • 请求速率限制

  • 路径改写

Spring Cloud Gateway 对比 Zuul

  • 我知道所有使用Spring Boot的人都想知道,我们已经在使用Zuul。它几乎提供了与Spring Cloud Gateway相同的功能。那么,为什么我们要切换到新框架?对我来说,主要原因是Zuul 1.x没有反应式编程。它使用阻塞api。现在,如果您正在迁移到Reactive模式以从微服务中获得更好的性能,并且您将Spring Boot 2与Reactor一起使用。

  • 您可以使用Zuul 2.0,它确实具有Netty的Reactive nonblocking支持。 但是Spring生态系统没有像Zuul 1.x那样给予Zuul 2.0的内置支持,这意味着,您必须使用Zuul运行自己的独立服务。你不能让它与其他现有的spring微服务集成。Spring团队并不打算用Spring来增加对它的支持。

  • 所以Spring Cloud Gateway可以与任何微服务集成,使之成为真正的api网关,在一个地方添加身份验证和其他安全功能。因为推荐使用Spring Cloud Gateway。

Spring Cloud Gateway简介

Spring Cloud Gateway是Spring Cloud团队在Spring反应生态系统(Webflux)之上的API网关实现。它提供了一种简单有效的方法,即使用网关处理程序映射将传入的请求路由到适当的目的地。Spring Cloud Gateway使用Netty服务器提供非阻塞异步请求处理。以下是在Spring Cloud Gateway中请求路由的工作原理的高层流程:


Spring Cloud Gateway架构

Spring Cloud Gateway包含3个主要构建模块:

  • Route(路由)

    将此视为我们希望将特定请求路由到的目的地。它由目标URI、必须满足的条件或技术术语、谓词和一个或多个筛选器组成。

  • Predicate(谓词)

    这实际上是一个需要匹配的条件。 例如if条件。如果请求有某些东西-例如,path=blah或请求头包含foo-bar等。在java技术术语中,它类似于java8函数谓词Predicate。

    具体谓词类型参考文档: https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#gateway-request-predicates-factories

  • Filter(过滤器)

    这些是springframeworkwebfilter的实例。在这里您可以应用修改请求或响应的魔力。框架提供了很多现成的WebFilter。当然,我们讨论的是Spring框架。所以,大家休息吧!!!您始终可以使用自己的逻辑添加自己的筛选器。

Spring Cloud Gateway 原理

Spring Cloud Gateway 的工作原理跟 Zuul 的差不多,最大的区别就是 Gateway 的 Filter 只有 pre 和 post 两种。下面我们简单了解一下 Gateway 的工作原理图,如下图所示。


架构图
  • Predicate 原理

    Predicte由PredicateSpec来构建,主要实现有:


Predicte

以PathRoutePredicateFactory为例看下源码:

    @Override
    public Predicate<ServerWebExchange> apply(Config config) {
        final ArrayList<PathPattern> pathPatterns = new ArrayList<>();
        synchronized (this.pathPatternParser) {
            pathPatternParser.setMatchOptionalTrailingSeparator(config.isMatchOptionalTrailingSeparator());
            config.getPatterns()
                    .forEach(pattern -> {
                        // 构建匹配规则
                        PathPattern pathPattern = this.pathPatternParser.parse(pattern);
                        pathPatterns.add(pathPattern);
                    })
            ;
        }
        return exchange -> {
            PathContainer path = parsePath(exchange.getRequest().getURI().getPath());
            // 匹配过滤
            Optional<PathPattern> optionalPathPattern = pathPatterns.stream().filter(pattern -> pattern.matches(path)).findFirst();
            if (optionalPathPattern.isPresent()) {
                // 如果存在匹配成功的  然后设置匹配成功的PathMatchInfo
                PathPattern pathPattern = optionalPathPattern.get();
                traceMatch("Pattern", pathPattern.getPatternString(), path, true);
                PathMatchInfo pathMatchInfo = pathPattern.matchAndExtract(path);
                putUriTemplateVariables(exchange, pathMatchInfo.getUriVariables());
                return true;
            } else {
                traceMatch("Pattern", config.getPatterns(), path, false);
                return false;
            }
        };
    }
  • Filter 原理

    Filter分两种,一种GatewayFilter(网关路由过滤器),一种GlobalFilter(全局路由器)

    - GlobalFilter
    为请求业务以及路由的URI转换为真实业务服务的请求地址的核心过滤器,不需要配置,模式系统初始化时加载,并作用在每个路由上。

    GlobalFilter类型参考文档

    • GatewayFilter

    Gateway内置了不少可用的GatewayFilter,具体如下:


    GatewayFilter

    下面以OrderedGatewayFilter为例子看下源码:

    /**
     * 排序的网关路由过滤器,用于包装真实的网关过滤器,已达到过滤器可排序
     */
    public class OrderedGatewayFilter implements GatewayFilter, Ordered {

        //目标过滤器
        private final GatewayFilter delegate;
        //排序字段
        private final int order;

        public OrderedGatewayFilter(GatewayFilter delegate, int order) {
            this.delegate = delegate;
            this.order = order;
        }
        @Override
        public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
            // 让下个过滤器过滤
            return this.delegate.filter(exchange, chain);
        }
    }
     具体GatewayFilter类型参考文档: `https://docs.spring.io/spring-cloud-gateway/docs/2.2.8.BUILD-SNAPSHOT/reference/html/#gatewayfilter-factories`

Spring Cloud Gateway 入门

  1. ###引入依赖
  <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
  1. 使用RouteLocator去构建url路由
@SpringBootApplication
public class GatewayClientApplication {

    @Value("${test.uri}")
    private String uri;

    @Bean
    public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
        return builder.routes()
                //basic proxy
                .route(r -> r.path("/order/**")
                        .uri(uri)
                ).build();
    }

    public static void main(String[] args) {
        SpringApplication.run(GatewayClientApplication.class, args);
    }
}
  1. application.ymal方式

假设test1-service和test2-service的服务地址分别是http://127.0.0.1:8070,http://127.0.0.1:8060

例如下面的写法中,test1-service最终转发后的路径就是:http://127.0.0.1:8070/** 去除了test1-service路径

test2-service最终路径 :http://127.0.0.1:8060/test2-service/** 不做路径剥离直接请求。

spring:
  application:
    name: gateway
  cloud:
    gateway:
      discovery:
        locator:
          lowerCaseServiceId: true
          enabled: true
      routes:
        - id: test-1
          uri: lb://test1-service  #负载均衡url
          order: 8001 #定义顺序
          predicates: #谓词
            - Path=/test1-service/**
          filters: #过滤器  
            - AddResponseHeader=X-Response-test1, test1
        - id: test-2
          uri: lb://test2-service
          order: 8003
          predicates:
            - Path=/test2-service/oauth/token
          filters:   
            - AddResponseHeader=X-Response-test2, test2

END

下篇详细介绍 Spring Cloud Gateway 高级用法

欢迎关注公众号!
公众号回复:入群 ,扫码加入我们交流群!

一文搞定zuul使用的更多相关文章

  1. 一文搞定 SonarQube 接入 C#(.NET) 代码质量分析

    1. 前言 C#语言接入Sonar代码静态扫描相较于Java.Python来说,相对麻烦一些.Sonar检测C#代码时需要预先编译,而且C#代码必须用MSbuid进行编译,如果需要使用SonarQub ...

  2. 一文搞定MySQL的事务和隔离级别

    一.事务简介 事务是数据库管理系统执行过程中的一个逻辑单位,由一个有限的数据库操作序列构成. 一个数据库事务通常包含了一个序列的对数据库的读/写操作.它的存在包含有以下两个目的: 为数据库操作序列提供 ...

  3. 一文搞定scrapy爬取众多知名技术博客文章保存到本地数据库,包含:cnblog、csdn、51cto、itpub、jobbole、oschina等

    本文旨在通过爬取一系列博客网站技术文章的实践,介绍一下scrapy这个python语言中强大的整站爬虫框架的使用.各位童鞋可不要用来干坏事哦,这些技术博客平台也是为了让我们大家更方便的交流.学习.提高 ...

  4. 一文搞定Spring Boot + Vue 项目在Linux Mysql环境的部署(强烈建议收藏)

    本文介绍Spring Boot.Vue .Vue Element编写的项目,在Linux下的部署,系统采用Mysql数据库.按照本文进行项目部署,不迷路. 1. 前言 典型的软件开发,经过" ...

  5. 21.SpringCloud实战项目-后台题目类型功能(网关、跨域、路由问题一文搞定)

    SpringCloud实战项目全套学习教程连载中 PassJava 学习教程 简介 PassJava-Learning项目是PassJava(佳必过)项目的学习教程.对架构.业务.技术要点进行讲解. ...

  6. 一文搞定FastDFS分布式文件系统配置与部署

    Ubuntu下FastDFS分布式文件系统配置与部署 白宁超 2017年4月15日09:11:52 摘要: FastDFS是一个开源的轻量级分布式文件系统,功能包括:文件存储.文件同步.文件访问(文件 ...

  7. 一文搞定 Git 相关概念和常用指令

    我几乎每天都使用 Git,但仍然无法记住很多命令. 通常,只需要记住下图中的 6 个命令就足以供日常使用.但是,为了确保使用地很顺滑,其实你应该记住 60 到 100 个命令. Git 相关术语 Gi ...

  8. 一文搞定Flask

    Flask 一 .Flask简介 Flask是一个基于Python开发并且依赖jinja2模板和Werkzeug WSGI服务的一个微型框架,对于Werkzeug本质是Socket服务端,其用于接收h ...

  9. SpringCloud第二代实战系列:一文搞定Nacos实现服务注册与发现

    一.背景:SpringCloud 生态圈 在正式开始本篇文章之前我们先岔开来讲一下SpringCloud的生态圈. SpringCloud大家都比较熟悉了,它制定了分布式系统的标准规范,做了高度抽象和 ...

随机推荐

  1. 「NGK每日快讯」11.19日NGK第16期官方快讯!

  2. 使用 Tye 辅助开发 k8s 应用竟如此简单(三)

    续上篇,这篇我们来进一步探索 Tye 更多的使用方法.本篇我们来了解一下如何在 Tye 中如何对数据库进行链接. Newbe.Claptrap 是一个用于轻松应对并发问题的分布式开发框架.如果您是首次 ...

  3. emplace_back与push_back

    资料参考: https://blog.csdn.net/p942005405/article/details/84764104 实际精华在评论中,转载如下: STL的实现版本很多,VS.GCC版本不同 ...

  4. 05_MySQL什么是sql语句

    什么是SQL语言 SQL语言的分类 SQL语言的注意事项 SQL语句的注释 数据的创建.查看及删除 实操: 创建数据表 实操: 数据表的其他操作 查看数据库的数据表 查看表结构: 查看建表语句:

  5. IntelliJ Idea Error Address localhost 1099 is already in use.

        Reference: https://stackoverflow.com/questions/38986910/intellij-idea-address-localhost1099-is-a ...

  6. Java基础语法:JavaDoc

    一.简介 JavaDoc是一种将注释生成HTML文档的技术,它从程序源代码中抽取类.方法.成员等注释形成一个和源代码配套的API帮助文档. 也就是说,只要在编写程序时以一套特定的标签作注释,在程序编写 ...

  7. su: Authentication failure解决方法

    su命令不能切换root,提示su: Authentication failure,需要sudo passwd root一次之后,下次再su的时候只要输入密码就可以成功登录.

  8. python进阶(9)多线程

    什么是线程? 线程也叫轻量级进程,是操作系统能够进行运算调度的最小单位,它被包涵在进程之中,是进程中的实际运作单位.线程自己不拥有系统资源,只拥有一点儿在运行中必不可少的资源,但它可与同属一个进程的其 ...

  9. gRPC-go源码(2):ClientConn

    摘要 在上一篇文章中,我们聊了聊gRPC是怎么管理一条从Client到Server的连接的. 我们聊到了gRPC拥有Resolver,用来解析地址:拥有Balancer,用来做负载均衡. 在这一篇文章 ...

  10. 剑指 Offer 62. 圆圈中最后剩下的数字 + 约瑟夫环问题

    剑指 Offer 62. 圆圈中最后剩下的数字 Offer_62 题目描述 方法一:使用链表模拟 这种方法是暴力方法,时间复杂度为O(nm),在本题中数据量过大会超时. 方法二:递归方法 packag ...