gateway 订阅
Gateway是一家1985年成立于美国爱荷华州的公司,现成长为美国知名的PC品牌,2007年10月被Acer宏碁以7.1亿美元收购该公司。Gateway公司的品牌产品已经通过主要零售商、电子零售商和渠道合作伙伴进入美国、墨西哥、加拿大、日本、中国以及越来越多的亚太地区市场。 展开全文
Gateway是一家1985年成立于美国爱荷华州的公司,现成长为美国知名的PC品牌,2007年10月被Acer宏碁以7.1亿美元收购该公司。Gateway公司的品牌产品已经通过主要零售商、电子零售商和渠道合作伙伴进入美国、墨西哥、加拿大、日本、中国以及越来越多的亚太地区市场。
信息
成立时间
1985年
公司名称
捷威
总部地点
美国南加利福尼亚州
公司类型
股份公司
外文名称
Gateway
经营范围
IT产品
Gateway电脑品牌
Gateway (中文商标:捷威)于 1985 年在美国中西部的一间农舍里创立,已经成长为世界最知名的技术品牌之一,拥有数百万满意的客户。公司创始人泰德-温特(Ted Waitt) 以他祖母向银行担保的 10,000 美元贷款、一台租赁的计算机和一份三页的经营计划起家,将 Gateway 发展成了一个具有革命性意义的公司,它的创新改变了技术产业的面貌。1991 年,公司(原名 Gateway 2000)推出了彰显其牧场起家背景的别具一格的奶牛花斑盒状商标,获得了全国消费者的认可。1993 年,它进入财富 500 强并在 纳斯达克(NASDAQ)上市,随后,在 1997 年转到纽约证券交易所。第二年,Gateway 将其总部从南达科他州的 North Sioux City 迁到了南加利福尼亚州。2004 年 3 月,Gateway 收购了世界上成长最快、效率最高的 PC 制造商之一eMachines。eMachines 是美国第二大个人计算机零售品牌,以低价PC 为主营业务,其技术支持和质量屡获殊荣。 2004年9月,公司将总部迁至加州Irvine。Gateway在中国大陆的昵称为花斑奶牛。 [1]  在创业初期, Gateway开创了业内多个第一。它是第一个提供彩色显示器系统的PC公司,也是第一个提供三年质保的公司,同时也是第一个整合PC和电视功能的厂商。它是直销知名电子消费品并获得成功的公司之一。Gateway是美国第二大PC厂商,居世界前10名。公司的eMachines品牌由国内的著名零售巨头独家销售,而 Gateway的增值产品则通过电话、网络以及直销力量向主要的零售厂商提供。Gateway尊重客户,关注于服务品质和价值的提升。在客户忠诚度方面,其连续多年居于业内之首。2007 年 10 月,Gateway 被总部设在台湾的宏碁公司 (Acer Inc.) 收购,收购后的联合实体现已成为世界第三大 PC 公司。 [2]  2008年,Gateway团队操盘宏碁全球台式机业务,宏碁对台式机业务有更高的期望值,Gateway团队对台式机又有较强的研发及市场经验,因此,决定由GateWay公司的团队操盘其全球台式机业务。Gateway 始终致力追求让客户在购买、拥有和使用 PC 时感到方便无忧这一境界。在 Gateway 向新市场迈进的过程中,公司将继续坚持其最初的目标:通过技术帮助人们提高生活品质。Gateway 产品由指定零售合作伙伴销售。上海市黄浦区西藏中路168号都市总部大厦3楼(200001)2010Gateway 品牌 品牌 电脑报 5月 最佳服务奖Gateway 笔记本 NV49C 中国电脑教育报 6月28日 暑期档最佳产品Gateway 笔记本 NV49C 微型计算机 11月 BUST SHOPPING Gateway产品(4张) Gateway 笔记本 NV49C83C 电脑报 12月20日 2010年度推荐奖Gateway 笔记本 NV4435c 中关村在线 12月 2010年度推荐产品Gateway 台式机 FX6840-000C 中关村在线 12月 2010年度推荐产品Gateway 笔记本 NV59C PConline 12月27日 最佳外观奖Gateway 笔记本 EC39C PConline 12月27日 最佳外观奖Gateway 超便携笔记本 LT3115c PConline 12月27日 编辑选择奖Gateway 笔记本 EC39C PCPOP 12月30日 最佳设计奖Gateway 笔记本 ID49C IT168 1月5日 2010年度产品奖Gateway 笔记本 EC39C 6月 台北国际计算机展2010创新设计奖Gateway 笔记本 EC39C 10月 2010日本优良设计奖Gateway 显示器 FHD2303L 10月 2010日本优良设计奖Gateway 显示器 FHD2303L 12月 iF Product Design Award 产品设计奖Packard Bell笔记本 EasyNote Butterfly 12月 iF Product Design Award 产品设计奖 GTW EC39C与其同样模具Gateway 台式机 FX系列 12月 2011年CES创新与工程设计大奖
收起全文
精华内容
参与话题
问答
  • Gateway网关简介及使用

    万次阅读 多人点赞 2019-10-09 20:54:12
    Gateway网关简介及使用 1. 什么是 API 网关(API Gateway) 分布式服务架构、微服务架构与 API 网关 在微服务架构里,服务的粒度被进一步细分,各个业务服务可以被独立的设计、开发、测试、部署和管理。这时,各个...

    Gateway网关简介及使用

    1. 什么是 API 网关(API Gateway)

    分布式服务架构、微服务架构与 API 网关

    在微服务架构里,服务的粒度被进一步细分,各个业务服务可以被独立的设计、开发、测试、部署和管理。这时,各个独立部署单元可以用不同的开发测试团队维护,可以使用不同的编程语言和技术平台进行设计,这就要求必须使用一种语言和平 台无关的服务协议作为各个单元间的通讯方式。

    API 网关的定义

    网关的角色是作为一个 API 架构,用来保护、增强和控制对于 API 服务的访问。

    API 网关是一个处于应用程序或服务(提供 REST API 接口服务)之前的系统,用来管理授权、访问控制和流量限制等,这样 REST API 接口服务就被 API 网关保护起来,对所有的调用者透明。因此,隐藏在 API 网关后面的业务系统就可以专注于创建和管理服务,而不用去处理这些策略性的基础设施。

    API 网关的职能

    API 网关的分类与功能

    2. Gateway是什么

    Spring Cloud Gateway是Spring官方基于Spring 5.0,Spring Boot 2.0和Project Reactor等技术开发的网关,Spring Cloud Gateway旨在为微服务架构提供一种简单而有效的统一的API路由管理方式。Spring Cloud Gateway作为Spring Cloud生态系中的网关,目标是替代ZUUL,其不仅提供统一的路由方式,并且基于Filter链的方式提供了网关基本的功能,例如:安全,监控/埋点,和限流等。

    3. 为什么用Gateway

    Spring Cloud Gateway 可以看做是一个 Zuul 1.x 的升级版和代替品,比 Zuul 2 更早的使用 Netty 实现异步 IO,从而实现了一个简单、比 Zuul 1.x 更高效的、与 Spring Cloud 紧密配合的 API 网关。
    Spring Cloud Gateway 里明确的区分了 Router 和 Filter,并且一个很大的特点是内置了非常多的开箱即用功能,并且都可以通过 SpringBoot 配置或者手工编码链式调用来使用。
    比如内置了 10 种 Router,使得我们可以直接配置一下就可以随心所欲的根据 Header、或者 Path、或者 Host、或者 Query 来做路由。
    比如区分了一般的 Filter 和全局 Filter,内置了 20 种 Filter 和 9 种全局 Filter,也都可以直接用。当然自定义 Filter 也非常方便。

    最重要的几个概念

    4. Gateway怎么用

    说白了 Predicate 就是为了实现一组匹配规则,方便让请求过来找到对应的 Route 进行处理,接下来我们接下 Spring Cloud GateWay 内置几种 Predicate 的使用。

    通过时间匹配

    Predicate 支持设置一个时间,在请求进行转发的时候,可以通过判断在这个时间之前或者之后进行转发。比如我们现在设置只有在 2019 年 1 月 1 日才会转发到我的网站,在这之前不进行转发,我就可以这样配置:

    spring:
      cloud:
        gateway:
          routes:
           - id: time_route
            uri: http://ityouknow.com
            predicates:
             - After=2018-01-20T06:06:06+08:00[Asia/Shanghai]
    
    
    

    Spring 是通过 ZonedDateTime 来对时间进行的对比,ZonedDateTime 是 Java 8 中日期时间功能里,用于表示带时区的日期与时间信息的类,ZonedDateTime 支持通过时区来设置时间,中国的时区是:Asia/Shanghai

    After Route Predicate 是指在这个时间之后的请求都转发到目标地址。上面的示例是指,请求时间在 2018 年 1 月 20 日 6 点 6 分 6 秒之后的所有请求都转发到地址http://ityouknow.com+08:00是指时间和 UTC 时间相差八个小时,时间地区为Asia/Shanghai

    添加完路由规则之后,访问地址http://localhost:8080会自动转发到http://ityouknow.com

    Before Route Predicate 刚好相反,在某个时间之前的请求的请求都进行转发。我们把上面路由规则中的 After 改为 Before,如下:

    spring:
      cloud:
        gateway:
          routes:
           - id: after_route
            uri: http://ityouknow.com
            predicates:
             - Before=2018-01-20T06:06:06+08:00[Asia/Shanghai]
    
    
    

    就表示在这个时间之前可以进行路由,在这时间之后停止路由,修改完之后重启项目再次访问地址http://localhost:8080,页面会报 404 没有找到地址。

    除过在时间之前或者之后外,Gateway 还支持限制路由请求在某一个时间段范围内,可以使用 Between Route Predicate 来实现。

    spring:
      cloud:
        gateway:
          routes:
           - id: after_route
            uri: http://ityouknow.com
            predicates:
             - Between=2018-01-20T06:06:06+08:00[Asia/Shanghai], 2019-01-20T06:06:06+08:00[Asia/Shanghai]
    
    
    

    这样设置就意味着在这个时间段内可以匹配到此路由,超过这个时间段范围则不会进行匹配。通过时间匹配路由的功能很酷,可以用在限时抢购的一些场景中。

    通过 Cookie 匹配

    Cookie Route Predicate 可以接收两个参数,一个是 Cookie name , 一个是正则表达式,路由规则会通过获取对应的 Cookie name 值和正则表达式去匹配,如果匹配上就会执行路由,如果没有匹配上则不执行。

    spring:
      cloud:
        gateway:
          routes:
           - id: cookie_route
             uri: http://ityouknow.com
             predicates:
             - Cookie=ityouknow, kee.e
    
    
    

    使用 curl 测试,命令行输入:

    curl http://localhost:8080 --cookie "ityouknow=kee.e"
    
    
    

    则会返回页面代码,如果去掉--cookie "ityouknow=kee.e",后台汇报 404 错误。

    Header Route Predicate 和 Cookie Route Predicate 一样,也是接收 2 个参数,一个 header 中属性名称和一个正则表达式,这个属性值和正则表达式匹配则执行。

    spring:
      cloud:
        gateway:
          routes:
          - id: header_route
            uri: http://ityouknow.com
            predicates:
            - Header=X-Request-Id, \d+
    
    
    

    使用 curl 测试,命令行输入:

    curl http://localhost:8080  -H "X-Request-Id:666666" 
    
    
    

    则返回页面代码证明匹配成功。将参数-H "X-Request-Id:666666"改为-H "X-Request-Id:neo"再次执行时返回 404 证明没有匹配。

    通过 Host 匹配

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

    spring:
      cloud:
        gateway:
          routes:
          - id: host_route
            uri: http://ityouknow.com
            predicates:
            - Host=**.ityouknow.com
    
    
    

    使用 curl 测试,命令行输入:

    curl http://localhost:8080  -H "Host: www.ityouknow.com" 
    curl http://localhost:8080  -H "Host: md.ityouknow.com" 
    
    
    

    经测试以上两种 host 均可匹配到 host_route 路由,去掉 host 参数则会报 404 错误。

    通过请求方式匹配

    可以通过是 POST、GET、PUT、DELETE 等不同的请求方式来进行路由。

    spring:
      cloud:
        gateway:
          routes:
          - id: method_route
            uri: http://ityouknow.com
            predicates:
            - Method=GET
    
    
    

    使用 curl 测试,命令行输入:

    # curl 默认是以 GET 的方式去请求
    curl http://localhost:8080
    
    
    

    测试返回页面代码,证明匹配到路由,我们再以 POST 的方式请求测试。

    # curl 默认是以 GET 的方式去请求
    curl -X POST http://localhost:8080
    
    
    

    返回 404 没有找到,证明没有匹配上路由

    通过请求路径匹配

    Path Route Predicate 接收一个匹配路径的参数来判断是否走路由。

    spring:
      cloud:
        gateway:
          routes:
          - id: host_route
            uri: http://ityouknow.com
            predicates:
            - Path=/foo/{segment}
    
    
    

    如果请求路径符合要求,则此路由将匹配,例如:/foo/1 或者 /foo/bar。

    使用 curl 测试,命令行输入:

    curl http://localhost:8080/foo/1
    curl http://localhost:8080/foo/xx
    curl http://localhost:8080/boo/xx
    
    
    

    经过测试第一和第二条命令可以正常获取到页面返回值,最后一个命令报 404,证明路由是通过指定路由来匹配。

    通过请求参数匹配

    Query Route Predicate 支持传入两个参数,一个是属性名一个为属性值,属性值可以是正则表达式。

    spring:
      cloud:
        gateway:
          routes:
          - id: query_route
            uri: http://ityouknow.com
            predicates:
            - Query=smile
    
    
    

    这样配置,只要请求中包含 smile 属性的参数即可匹配路由。

    使用 curl 测试,命令行输入:

    curl localhost:8080?smile=x&id=2
    
    
    

    经过测试发现只要请求汇总带有 smile 参数即会匹配路由,不带 smile 参数则不会匹配。

    还可以将 Query 的值以键值对的方式进行配置,这样在请求过来时会对属性值和正则进行匹配,匹配上才会走路由。

    spring:
      cloud:
        gateway:
          routes:
          - id: query_route
            uri: http://ityouknow.com
            predicates:
            - Query=keep, pu.
    
    
    
    

    这样只要当请求中包含 keep 属性并且参数值是以 pu 开头的长度为三位的字符串才会进行匹配和路由。

    使用 curl 测试,命令行输入:

    curl localhost:8080?keep=pub
    
    
    
    

    测试可以返回页面代码,将 keep 的属性值改为 pubx 再次访问就会报 404, 证明路由需要匹配正则表达式才会进行路由。

    通过请求 ip 地址进行匹配

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

    spring:
      cloud:
        gateway:
          routes:
          - id: remoteaddr_route
            uri: http://ityouknow.com
            predicates:
            - RemoteAddr=192.168.1.1/24
    
    
    

    可以将此地址设置为本机的 ip 地址进行测试。

    果请求的远程地址是 192.168.1.10,则此路由将匹配。

    组合使用

    上面为了演示各个 Predicate 的使用,我们是单个单个进行配置测试,其实可以将各种 Predicate 组合起来一起使用。

    例如:

    spring:
      cloud:
        gateway:
          routes:
           - id: host_foo_path_headers_to_httpbin
            uri: http://ityouknow.com
            predicates:
            - Host=**.foo.org
            - Path=/headers
            - Method=GET
            - Header=X-Request-Id, \d+
            - Query=foo, ba.
            - Query=baz
            - Cookie=chocolate, ch.p
            - After=2018-01-20T06:06:06+08:00[Asia/Shanghai]
    
    
    

    各种 Predicates 同时存在于同一个路由时,请求必须同时满足所有的条件才被这个路由匹配。

    一个请求满足多个路由的谓词条件时,请求只会被首个成功匹配的路由转发

    展开全文
  • SpringCloud之服务网关Gateway

    万次阅读 多人点赞 2019-06-30 22:02:38
    Spring Cloud Gateway 是 Spring Cloud 新推出的网关框架,之前是Netflix Zuul。网关通常在项目中为了简化 前端的调用逻辑,同时也简化内部服务之间互相调用的复杂度;具体作用就是转发服务,接收并转发所有内外 ...

    前言

      SpringCloud 是微服务中的翘楚,最佳的落地方案。

      Spring Cloud Gateway 是 Spring Cloud 新推出的网关框架,之前是 Netflix Zuul。网关通常在项目中为了简化

      前端的调用逻辑,同时也简化内部服务之间互相调用的复杂度;具体作用就是转发服务,接收并转发所有内外

      部的客户端调用;其他常见的功能还有权限认证,限流控制等等。

      本博客会提到网关的基本转发功能熔断功能限流功能以及功能的综合使用

    源码

      GitHub地址:https://github.com/intomylife/SpringCloud

    环境

    • JDK 1.8.0 +
    • Maven 3.0 +
    • SpringBoot 2.0.3
    • SpringCloud Finchley.RELEASE
    • Redis 3.0 +

    开发工具

    • IntelliJ IDEA

    正文

    commons 工程

    commons 工程 - POM 文件

    <?xml version="1.0" encoding="UTF-8"?>
    <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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <!-- 三坐标 -->
        <groupId>com.zwc</groupId>
        <artifactId>springcloud-gateway-commons</artifactId>
        <version>1.0</version>
    
        <!-- 工程名称和描述 -->
        <name>springcloud-gateway-commons</name>
        <description>公用工程</description>
    
        <!-- 打包方式 -->
        <packaging>jar</packaging>
    
        <!-- 在 properties 下声明相应的版本信息,然后在 dependency 下引用的时候用 ${} 就可以引入该版本 jar 包了 -->
        <properties>
            <!-- 编码 -->
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <!-- jdk -->
            <java.version>1.8</java.version>
    
            <!-- SpringBoot -->
            <platform-bom.version>Cairo-SR3</platform-bom.version>
    
            <!-- SpringCloud -->
            <spring-cloud-dependencies.version>Finchley.RELEASE</spring-cloud-dependencies.version>
        </properties>
    
        <!-- 加入依赖 -->
        <dependencies>
    
        </dependencies>
    
        <!-- 依赖 jar 包版本管理的管理器 -->
        <!-- 如果 dependencies 里的 dependency 自己没有声明 version 元素,那么 maven 就此处来找版本声明。 -->
        <!-- 如果有,就会继承它;如果没有就会报错,告诉你没有版本信息 -->
        <!-- 优先级:如果 dependencies 里的 dependency 已经声明了版本信息,就不会生效此处的版本信息了 -->
        <dependencyManagement>
            <dependencies>
                <!-- SpringBoot -->
                <dependency>
                    <groupId>io.spring.platform</groupId>
                    <artifactId>platform-bom</artifactId>
                    <version>${platform-bom.version}</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
                <!-- SpringCloud -->
                <dependency>
                    <groupId>org.springframework.cloud</groupId>
                    <artifactId>spring-cloud-dependencies</artifactId>
                    <version>${spring-cloud-dependencies.version}</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
            </dependencies>
        </dependencyManagement>
    
        <!-- 插件依赖 -->
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    
    </project>
    
    • 配置一些共用依赖

    commons 工程 - 项目结构

     

    service 工程

      ① 此工程下有四个模块:一个注册中心,一个网关以及两个提供者

      ② 两个提供者除端口不一致以外,其他代码基本一致

     

    registry-service(注册中心)

    registry-service - POM 文件

    <?xml version="1.0" encoding="UTF-8"?>
    <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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <!-- 继承父 -->
        <parent>
            <groupId>com.zwc</groupId>
            <artifactId>springcloud-gateway-service</artifactId>
            <version>1.0</version>
        </parent>
    
        <!-- 三坐标 -->
        <groupId>com.zwc</groupId>
        <artifactId>springcloud-gateway-registry-service</artifactId>
        <version>1.0</version>
    
        <!-- 工程名称描述 -->
        <name>springcloud-gateway-registry-service</name>
        <description>注册中心</description>
    
        <!-- 打包方式 -->
        <packaging>jar</packaging>
    
        <!-- 在 properties下声明相应的版本信息,然后在dependency下引用的时候用 ${} 就可以引入该版本jar包了 -->
        <properties>
    
        </properties>
    
        <!-- 加入依赖 -->
        <dependencies>
            <!-- 服务注册中心 -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
            </dependency>
        </dependencies>
    
        <!-- 插件依赖 -->
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    
    </project>
    
    • 主要加入 spring-cloud-starter-netflix-eureka-server 依赖

    registry-service - application.yml 配置文件

    # 端口
    server:
      port: 8761
    
    # 应用名称
    spring:
      application:
        name: eureka-server
    
    eureka:
      instance:
        # 使用 ip 代替实例名
        prefer-ip-address: true
        # 实例的主机名
        hostname: ${spring.cloud.client.ip-address}
        # 实例的 ID 规则
        instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}
      client:
        # 是否向注册中心注册自己
        registerWithEureka: false
        # 是否向注册中心获取注册信息
        fetchRegistry: false
        serviceUrl:
          # 注册中心地址
          defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
    • 这里使用了默认的 8761 端口,当然也可以更改,不过在发现调用服务端的注册中心地址端口要与它一致

    registry-service - 启动类

    package com.zwc;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
    
    @SpringBootApplication
    @EnableEurekaServer
    public class SpringcloudGatewayRegistryServiceApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(SpringcloudGatewayRegistryServiceApplication.class, args);
        }
    
    }
    
    • 在启动类中添加 @EnableEurekaServer 注解表示此工程是注册中心

    registry-service - 启动项目

      1. 项目启动成功后访问 http://localhost:8761/ 即可看到 eureka-server 主页面

     

      注:由于服务工程 A 和服务工程 B 除端口不一致以外,其他代码基本一致,所以服务工程 B 不再赘述

    a-service(服务工程 A)

    a-service - POM 文件

    <?xml version="1.0" encoding="UTF-8"?>
    <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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <!-- 继承父 -->
        <parent>
            <groupId>com.zwc</groupId>
            <artifactId>springcloud-gateway-a-service</artifactId>
            <version>1.0</version>
        </parent>
    
        <!-- 三坐标 -->
        <groupId>com.zwc</groupId>
        <artifactId>springcloud-gateway-a-service-core</artifactId>
        <version>1.0</version>
    
        <!-- 工程名称描述 -->
        <name>springcloud-gateway-a-service-core</name>
        <description>服务工程 - A 核心</description>
    
        <!-- 打包方式 -->
        <packaging>jar</packaging>
    
        <!-- 在 properties下声明相应的版本信息,然后在dependency下引用的时候用 ${} 就可以引入该版本jar包了 -->
        <properties>
    
        </properties>
    
        <!-- 加入依赖 -->
        <dependencies>
            <!-- commons工程 依赖 -->
            <dependency>
                <groupId>com.zwc</groupId>
                <artifactId>springcloud-gateway-commons</artifactId>
                <version>1.0</version>
            </dependency>
    
            <!-- api工程 依赖 -->
            <dependency>
                <groupId>com.zwc</groupId>
                <artifactId>springcloud-gateway-a-service-api</artifactId>
                <version>1.0</version>
            </dependency>
    
            <!-- springboot web 依赖 -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
    
            <!-- 提供者消费者 -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
            </dependency>
        </dependencies>
    
        <!-- 插件依赖 -->
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    
    </project>
    
    • 加入 spring-cloud-starter-netflix-eureka-client 依赖

    a-service - application.yml 配置文件

    # 端口
    server:
      port: 9000
    
    # 应用名称
    spring:
      application:
        name: gateway-service
    
    eureka:
      instance:
        # 使用 ip 代替实例名
        prefer-ip-address: true
        # 实例的主机名
        hostname: ${spring.cloud.client.ip-address}
        # 实例的 ID 规则
        instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}
      client:
        serviceUrl:
          # 注册中心地址
          defaultZone: http://${eureka.instance.hostname}:8761/eureka/
    • 注意此处配置注册中心地址的端口为 8761 也就是上面注册中心工程配置的端口

    a-service - controller 前端控制器(提供服务)

    package com.zwc.a.controller;
    
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    /*
     * @ClassName ASayHelloController
     * @Desc TODO   Say Hello
     * @Date 2019/5/20 23:24
     * @Version 1.0
     */
    @RestController
    public class ASayHelloController {
    
        /*
         * @ClassName ASayHelloController
         * @Desc TODO   读取配置文件中的端口
         * @Date 2019/5/20 23:24
         * @Version 1.0
         */
        @Value("${server.port}")
        private String port;
    
        /*
         * @ClassName ASayHelloController
         * @Desc TODO   Say Hello
         * @Date 2019/5/20 23:24
         * @Version 1.0
         */
        @RequestMapping("/hello")
        public String hello(){
            return "Hello!I'm a. port:" + port;
        }
    
        /*
         * @ClassName ASayHelloController
         * @Desc TODO   接收从网关传入的参数
         * @Date 2019/6/23 16:28
         * @Version 1.0
         */
        @RequestMapping("/name")
        public String name(String name){
            return "My name is " + name + ". aaa";
        }
    
        /*
         * @ClassName ASayHelloController
         * @Desc TODO   接收从网关传入的参数
         * @Date 2019/6/23 16:52
         * @Version 1.0
         */
        @RequestMapping("/age")
        public String age(String age){
            return "I am " + age + " years old this year. aaa";
        }
    
        /*
         * @ClassName ASayHelloController
         * @Desc TODO   接收从网关传入的参数
         * @Date 2019/6/29 22:00
         * @Version 1.0
         */
        @RequestMapping("/routeAll")
        public String routeAll(String pass) {
            return "Can I pass? " + pass + "! port:" + port;
        }
    
    }
    
    • 提供输出字符串服务,供网关调用

    a-service - 启动类

    package com.zwc;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
    
    @SpringBootApplication
    @EnableEurekaClient
    public class SpringcloudGatewayAServiceCoreApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(SpringcloudGatewayAServiceCoreApplication.class, args);
        }
    
    }
    
    • 添加 @EnableEurekaClient 注解表示此工程可以向注册中心提供服务

    a-service - 启动项目

      1. 刷新 http://localhost:8761/(注册中心)可以看到服务已经被注册进来了

      2. 项目启动成功后访问:http://localhost:9000/hello

      3. 输出内容:'Hello!I'm a. port:9000'

      4. 同样启动服务工程 B后,刷新 http://localhost:8761/(注册中心)

      5. 项目启动成功后访问:http://localhost:9001/hello

      6. 输出内容:'Hello!I'm b. port:9001'

      7. 其他接口是下面网关服务启动后转发调用的,也是本博客的重头戏

     

    master-service(网关)

    master-service - POM 文件

    <?xml version="1.0" encoding="UTF-8"?>
    <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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <!-- 继承父 -->
        <parent>
            <groupId>com.zwc</groupId>
            <artifactId>springcloud-gateway-service</artifactId>
            <version>1.0</version>
        </parent>
    
        <!-- 三坐标 -->
        <groupId>com.zwc</groupId>
        <artifactId>springcloud-gateway-master-service</artifactId>
        <version>1.0</version>
    
        <!-- 工程名称描述 -->
        <name>springcloud-gateway-master-service</name>
        <description>Spring Cloud Gateway 服务网关</description>
    
        <!-- 打包方式 -->
        <packaging>jar</packaging>
    
        <!-- 在 properties下声明相应的版本信息,然后在 dependency 下引用的时候用 ${} 就可以引入该版本 jar 包了 -->
        <properties>
            <!-- ali json -->
            <fastjson.version>1.2.47</fastjson.version>
        </properties>
    
        <!-- 加入依赖 -->
        <dependencies>
            <!-- 提供者消费者 -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
            </dependency>
    
            <!-- gateway -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-gateway</artifactId>
            </dependency>
    
            <!-- redis -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
            </dependency>
    
            <!-- hystrix -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
            </dependency>
    
            <!-- ali json依赖 -->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>fastjson</artifactId>
                <version>${fastjson.version}</version>
            </dependency>
        </dependencies>
    
        <!-- 插件依赖 -->
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    
    </project>
    
    • 加入 spring-cloud-starter-netflix-eureka-client 依赖:提供和注册服务
    • 加入 spring-cloud-starter-gateway 依赖:gateway
    • 加入 spring-boot-starter-data-redis-reactive 依赖:结合 Redis 限流
    • 加入 spring-cloud-starter-netflix-hystrix 依赖:熔断器

    master-service - application.yml 配置文件

    # 端口
    server:
      port: 8000
    
    spring:
      profiles:
        # 指定配置
        # route_simple:简单尝试
        # route_stripPrefix:截取请求
        # route_uri:转发指定地址并传入参数
        # route_addRequestParameter:转发指定服务并传入参数
        # route_hystrix:熔断
        # route_requestRateLimiter:限流
        # route_all:综合
        active: route_simple
    
    ---
    
    spring:
      # 配置文件名称,用来标识不同环境的配置。由 spring.profiles.active 的值来决定使用哪组配置。
      ## 简单尝试
      profiles: route_simple
      application:
        # 应用名称
        name: gateway-master
      cloud:
        gateway:
          discovery:
            locator:
              # 是否和服务注册与发现组件结合,设置为 true 后可以直接使用应用名称调用服务
              enabled: true
          # 路由(routes:路由,它由唯一标识(ID)、目标服务地址(uri)、一组断言(predicates)和一组过滤器组成(filters)。filters 不是必需参数。)
          routes:
          # 路由标识(id:标识,具有唯一性)   简单尝试
          - id: route_simple
            # 目标服务地址(uri:地址,请求转发后的地址)
            uri: https://www.zouwencong.com
            # 路由条件(predicates:断言,匹配 HTTP 请求内容)
            predicates:
            ## 转发地址格式为 uri/archive
            - Path=/archive
    
    eureka:
      instance:
        # 使用 ip 代替实例名
        prefer-ip-address: true
        # 实例的主机名
        hostname: ${spring.cloud.client.ip-address}
        # 实例的 ID 规则
        instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}
      client:
        serviceUrl:
          # 注册中心地址
          defaultZone: http://${eureka.instance.hostname}:8761/eureka/
    
    logging:
      level:
        # log 级别
        org.springframework.cloud.gateway: debug
    
    ---
    
    spring:
      # 配置文件名称,用来标识不同环境的配置。由 spring.profiles.active 的值来决定使用哪组配置。
      ## 截取请求
      profiles: route_stripPrefix
      application:
        # 应用名称
        name: gateway-master
      cloud:
        gateway:
          discovery:
            locator:
              # 是否和服务注册与发现组件结合,设置为 true 后可以直接使用应用名称调用服务
              enabled: true
          # 路由(routes:路由,它由唯一标识(ID)、目标服务地址(uri)、一组断言(predicates)和一组过滤器组成(filters)。filters 不是必需参数。)
          routes:
          # 路由标识(id:标识,具有唯一性)   截取请求
          - id: route_simple
            # 目标服务地址(uri:地址,请求转发后的地址)
            uri: https://www.zouwencong.com
            # 路由条件(predicates:断言,匹配 HTTP 请求内容)
            predicates:
            ## 转发地址格式为 uri/archive,/str 部分会被下面的过滤器给截取掉
            - Path=/str/archive
            filters:
            ## 截取路径位数
            - StripPrefix=1
    
    eureka:
      instance:
        # 使用 ip 代替实例名
        prefer-ip-address: true
        # 实例的主机名
        hostname: ${spring.cloud.client.ip-address}
        # 实例的 ID 规则
        instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}
      client:
        serviceUrl:
          # 注册中心地址
          defaultZone: http://${eureka.instance.hostname}:8761/eureka/
    
    logging:
      level:
        # log 级别
        org.springframework.cloud.gateway: debug
    
    ---
    
    spring:
      # 配置文件名称,用来标识不同环境的配置。由 spring.profiles.active 的值来决定使用哪组配置。
      ## 转发指定地址并传入参数
      profiles: route_uri
      application:
        # 应用名称
        name: gateway-master
      cloud:
        gateway:
          discovery:
            locator:
              # 是否和服务注册与发现组件结合,设置为 true 后可以直接使用应用名称调用服务
              enabled: true
          # 路由(routes:路由,它由唯一标识(ID)、目标服务地址(uri)、一组断言(predicates)和一组过滤器组成(filters)。filters 不是必需参数。)
          routes:
          # 路由标识(id:标识,具有唯一性)   转发指定地址并传入参数
          - id: route_uri
            # 目标服务地址(uri:地址,请求转发后的地址)
            uri: http://localhost:9000
            # 路由条件(predicates:断言,匹配 HTTP 请求内容)
            predicates:
            ## 匹配 GET 请求
            - Method=GET
            # 过滤器(filters:过滤器,过滤规则)
            filters:
            ## 添加指定参数
            - AddRequestParameter=name, zwc
    
    eureka:
      instance:
        # 使用 ip 代替实例名
        prefer-ip-address: true
        # 实例的主机名
        hostname: ${spring.cloud.client.ip-address}
        # 实例的 ID 规则
        instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}
      client:
        serviceUrl:
          # 注册中心地址
          defaultZone: http://${eureka.instance.hostname}:8761/eureka/
    
    logging:
      level:
        # log 级别
        org.springframework.cloud.gateway: debug
    
    ---
    
    spring:
      # 配置文件名称,用来标识不同环境的配置。由 spring.profiles.active 的值来决定使用哪组配置。
      ## 转发指定服务并传入参数
      profiles: route_addRequestParameter
      application:
        # 应用名称
        name: gateway-master
      cloud:
        gateway:
          discovery:
            locator:
              # 是否和服务注册与发现组件结合,设置为 true 后可以直接使用应用名称调用服务
              enabled: true
          # 路由(routes:路由,它由唯一标识(ID)、目标服务地址(uri)、一组断言(predicates)和一组过滤器组成(filters)。filters 不是必需参数。)
          routes:
          # 路由标识(id:标识,具有唯一性)   转发指定服务并传入参数
          - id: route_addRequestParameter
            # 目标服务地址(uri:地址,请求转发后的地址)
            uri: lb://gateway-service
            # 路由条件(predicates:断言,匹配 HTTP 请求内容)
            predicates:
            ## 匹配 GET 请求
            - Method=GET
            # 过滤器(filters:过滤器,过滤规则)
            filters:
            ## 添加指定参数
            - AddRequestParameter=age, three
    
    eureka:
      instance:
        # 使用 ip 代替实例名
        prefer-ip-address: true
        # 实例的主机名
        hostname: ${spring.cloud.client.ip-address}
        # 实例的 ID 规则
        instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}
      client:
        serviceUrl:
          # 注册中心地址
          defaultZone: http://${eureka.instance.hostname}:8761/eureka/
    
    logging:
      level:
        # log 级别
        org.springframework.cloud.gateway: debug
    
    ---
    
    spring:
      # 配置文件名称,用来标识不同环境的配置。由 spring.profiles.active 的值来决定使用哪组配置。
      ## 熔断
      profiles: route_hystrix
      application:
        # 应用名称
        name: gateway-master
      cloud:
        gateway:
          discovery:
            locator:
              # 是否和服务注册与发现组件结合,设置为 true 后可以直接使用应用名称调用服务
              enabled: true
          # 路由(routes:路由,它由唯一标识(ID)、目标服务地址(uri)、一组断言(predicates)和一组过滤器组成(filters)。filters 不是必需参数。)
          routes:
          # 路由标识(id:标识,具有唯一性)   熔断
          - id: route_hystrix
            # 目标服务地址(uri:地址,请求转发后的地址)
            uri: lb://gateway-service
            # 路由条件(predicates:断言,匹配 HTTP 请求内容)
            predicates:
            ## 匹配 GET 请求
            - Method=GET
            # 过滤器(filters:过滤器,过滤规则)
            filters:
            ## 添加指定参数
            - AddRequestParameter=age, three
            ## 熔断
            - name: Hystrix
              args:
                name: fallbackcmd
                ### fallback 时调用的方法 http://localhost:8000/fallback
                fallbackUri: forward:/fallback
    
    eureka:
      instance:
        # 使用 ip 代替实例名
        prefer-ip-address: true
        # 实例的主机名
        hostname: ${spring.cloud.client.ip-address}
        # 实例的 ID 规则
        instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}
      client:
        serviceUrl:
          # 注册中心地址
          defaultZone: http://${eureka.instance.hostname}:8761/eureka/
    
    logging:
      level:
        # log 级别
        org.springframework.cloud.gateway: debug
    
    ---
    
    spring:
      # 配置文件名称,用来标识不同环境的配置。由 spring.profiles.active 的值来决定使用哪组配置。
      ## 限流
      profiles: route_requestRateLimiter
      redis:
        host: localhost
        port: 6379
        database: 0
      application:
        # 应用名称
        name: gateway-master
      cloud:
        gateway:
          discovery:
            locator:
              # 是否和服务注册与发现组件结合,设置为 true 后可以直接使用应用名称调用服务
              enabled: true
          # 路由(routes:路由,它由唯一标识(ID)、目标服务地址(uri)、一组断言(predicates)和一组过滤器组成(filters)。filters 不是必需参数。)
          routes:
          # 路由标识(id:标识,具有唯一性)   限流
          - id: route_requestRateLimiter
            # 目标服务地址(uri:地址,请求转发后的地址)
            uri: lb://gateway-service
            # 路由条件(predicates:断言,匹配 HTTP 请求内容)
            predicates:
            ## 匹配 GET 请求
            - Method=GET
            # 过滤器(filters:过滤器,过滤规则)
            filters:
            ## 添加指定参数
            - AddRequestParameter=age, three
            ## 限流
            - name: RequestRateLimiter
              args:
                ### 限流过滤器的 Bean 名称
                key-resolver: '#{@uriKeyResolver}'
                ### 希望允许用户每秒处理多少个请求
                redis-rate-limiter.replenishRate: 1
                ### 用户允许在一秒钟内完成的最大请求数
                redis-rate-limiter.burstCapacity: 3
    
    eureka:
      instance:
        # 使用 ip 代替实例名
        prefer-ip-address: true
        # 实例的主机名
        hostname: ${spring.cloud.client.ip-address}
        # 实例的 ID 规则
        instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}
      client:
        serviceUrl:
          # 注册中心地址
          defaultZone: http://${eureka.instance.hostname}:8761/eureka/
    
    logging:
      level:
        # log 级别
        org.springframework.cloud.gateway: debug
    
    ---
    
    spring:
      # 配置文件名称,用来标识不同环境的配置。由 spring.profiles.active 的值来决定使用哪组配置。
      ## 综合
      profiles: route_all
      redis:
        host: localhost
        port: 6379
        database: 0
      application:
        # 应用名称
        name: gateway-master
      cloud:
        gateway:
          discovery:
            locator:
              # 是否和服务注册与发现组件结合,设置为 true 后可以直接使用应用名称调用服务
              enabled: true
          # 路由(routes:路由,它由唯一标识(ID)、目标服务地址(uri)、一组断言(predicates)和一组过滤器组成(filters)。filters 不是必需参数。)
          routes:
          # 路由标识(id:标识,具有唯一性)   综合
          - id: route_all
            # 目标服务地址(uri:地址,请求转发后的地址)
            uri: lb://gateway-service
            # 路由条件(predicates:断言,匹配 HTTP 请求内容)
            predicates:
            ## 转发地址格式为 uri/routeAll,/all 部分会被下面的过滤器给截取掉
            - Path=/all/routeAll
            ## 匹配 GET 请求
            - Method=GET
            # 过滤器(filters:过滤器,过滤规则)
            filters:
            ## 截取路径位数
            - StripPrefix=1
            ## 添加指定参数
            - AddRequestParameter=pass, yes
            ## 熔断
            - name: Hystrix
              args:
                name: fallbackcmd
                ### fallback 时调用的方法 http://localhost:8000/fallback
                fallbackUri: forward:/fallback
            ## 限流
            - name: RequestRateLimiter
              args:
                ### 限流过滤器的 Bean 名称
                key-resolver: '#{@uriKeyResolver}'
                ### 希望允许用户每秒处理多少个请求
                redis-rate-limiter.replenishRate: 1
                ### 用户允许在一秒钟内完成的最大请求数
                redis-rate-limiter.burstCapacity: 3
    
    eureka:
      instance:
        # 使用 ip 代替实例名
        prefer-ip-address: true
        # 实例的主机名
        hostname: ${spring.cloud.client.ip-address}
        # 实例的 ID 规则
        instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}
      client:
        serviceUrl:
          # 注册中心地址
          defaultZone: http://${eureka.instance.hostname}:8761/eureka/
    
    logging:
      level:
        # log 级别
        org.springframework.cloud.gateway: debug
    • 注意配置注册中心地址的端口都为 8761 也就是上面注册中心工程配置的端口
    • 每一对 '---' 符号中的配置文件都是单独的,使用 spring.profiles.active 指定
    • 每一对 '---' 符号中的配置文件都只配置了一个 route(路由)
    • route(路由)由四部分组成,其中 filters 不是必须参数
    • 唯一标识(ID)、目标服务地址(uri)、一组断言(predicates)和一组过滤器组成(filters)

     

    master-service - 简单尝试

    spring:
      # 配置文件名称,用来标识不同环境的配置。由 spring.profiles.active 的值来决定使用哪组配置。
      ## 简单尝试
      profiles: route_simple
      application:
        # 应用名称
        name: gateway-master
      cloud:
        gateway:
          discovery:
            locator:
              # 是否和服务注册与发现组件结合,设置为 true 后可以直接使用应用名称调用服务
              enabled: true
          # 路由(routes:路由,它由唯一标识(ID)、目标服务地址(uri)、一组断言(predicates)和一组过滤器组成(filters)。filters 不是必需参数。)
          routes:
          # 路由标识(id:标识,具有唯一性)   简单尝试
          - id: route_simple
            # 目标服务地址(uri:地址,请求转发后的地址)
            uri: https://www.zouwencong.com
            # 路由条件(predicates:断言,匹配 HTTP 请求内容)
            predicates:
            ## 转发地址格式为 uri/archive
            - Path=/archive

      1. 停止注册中心工程(registry-service)、服务工程 A 和服务工程 B

      2. 把 master-service - application.yml 配置文件中最上面的 spring.profiles.active 的值更改为 route_simple

      3. 上面配置文件内容意思是当访问 http://localhost:8000/archive (网关地址/archive)

          会被转发到 https://www.zouwencong.com/archive/ (uri/archive)

      4. 启动注册中心工程(registry-service)和网关工程(master-service)

      5. 项目启动成功后访问:http://localhost:8000/archive

      6. 发现页面会自动被跳转到:https://www.zouwencong.com/archive/

      7. 证明服务转发成功

     

    master-service - 截取请求

    spring:
      # 配置文件名称,用来标识不同环境的配置。由 spring.profiles.active 的值来决定使用哪组配置。
      ## 截取请求
      profiles: route_stripPrefix
      application:
        # 应用名称
        name: gateway-master
      cloud:
        gateway:
          discovery:
            locator:
              # 是否和服务注册与发现组件结合,设置为 true 后可以直接使用应用名称调用服务
              enabled: true
          # 路由(routes:路由,它由唯一标识(ID)、目标服务地址(uri)、一组断言(predicates)和一组过滤器组成(filters)。filters 不是必需参数。)
          routes:
          # 路由标识(id:标识,具有唯一性)   截取请求
          - id: route_simple
            # 目标服务地址(uri:地址,请求转发后的地址)
            uri: https://www.zouwencong.com
            # 路由条件(predicates:断言,匹配 HTTP 请求内容)
            predicates:
            ## 转发地址格式为 uri/archive,/str 部分会被下面的过滤器给截取掉
            - Path=/str/archive
            filters:
            ## 截取路径位数
            - StripPrefix=1
    
    eureka:
      instance:
        # 使用 ip 代替实例名
        prefer-ip-address: true
        # 实例的主机名
        hostname: ${spring.cloud.client.ip-address}
        # 实例的 ID 规则
        instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}
      client:
        serviceUrl:
          # 注册中心地址
          defaultZone: http://${eureka.instance.hostname}:8761/eureka/
    
    logging:
      level:
        # log 级别
        org.springframework.cloud.gateway: debug
    

      1. 停止注册中心工程(registry-service)和网关工程(master-service)

      2. 把 master-service - application.yml 配置文件中最上面的 spring.profiles.active 的值更改为 route_stripPrefix

      3. 上面配置文件内容意思是访问的路径 http://localhost:8000/str/archive (网关地址/str/archive)截取 /str 部分,

          截取后被转发到 https://www.zouwencong.com/archive/ (uri/archive)

      4. 启动注册中心工程(registry-service)和网关工程(master-service)

      5. 项目启动成功后访问:http://localhost:8000/str/archive

      6. 发现页面会自动被跳转到:https://www.zouwencong.com/archive/

      7. 证明路径被截取并服务转发成功

     

    master-service - 转发指定地址并传入参数

    spring:
      # 配置文件名称,用来标识不同环境的配置。由 spring.profiles.active 的值来决定使用哪组配置。
      ## 转发指定地址并传入参数
      profiles: route_uri
      application:
        # 应用名称
        name: gateway-master
      cloud:
        gateway:
          discovery:
            locator:
              # 是否和服务注册与发现组件结合,设置为 true 后可以直接使用应用名称调用服务
              enabled: true
          # 路由(routes:路由,它由唯一标识(ID)、目标服务地址(uri)、一组断言(predicates)和一组过滤器组成(filters)。filters 不是必需参数。)
          routes:
          # 路由标识(id:标识,具有唯一性)   转发指定地址并传入参数
          - id: route_uri
            # 目标服务地址(uri:地址,请求转发后的地址)
            uri: http://localhost:9000
            # 路由条件(predicates:断言,匹配 HTTP 请求内容)
            predicates:
            ## 匹配 GET 请求
            - Method=GET
            # 过滤器(filters:过滤器,过滤规则)
            filters:
            ## 添加指定参数
            - AddRequestParameter=name, zwc
    
    eureka:
      instance:
        # 使用 ip 代替实例名
        prefer-ip-address: true
        # 实例的主机名
        hostname: ${spring.cloud.client.ip-address}
        # 实例的 ID 规则
        instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}
      client:
        serviceUrl:
          # 注册中心地址
          defaultZone: http://${eureka.instance.hostname}:8761/eureka/
    
    logging:
      level:
        # log 级别
        org.springframework.cloud.gateway: debug

      1. 停止注册中心工程(registry-service)和网关工程(master-service)

      2. 把 master-service - application.yml 配置文件中最上面的 spring.profiles.active 的值更改为 route_uri

      3. 上面配置文件内容意思是访问的路径 http://localhost:8000/name (网关地址/name)

          会被转发到 http://localhost:9000/name(uri/name),并传入 'name=zwc' 参数(注意为 Get 请求)

      4. 启动注册中心工程(registry-service),网关工程(master-service)和服务工程 A(a-service)

      5. 项目启动成功后访问:http://localhost:8000/name

      6. 输出内容:'My name is zwc. aaa'(通过网关转发 - 参数有值)

      7. 打开新页面访问:http://localhost:9000/name

      8. 输出内容:'My name is null. aaa'(直接访问 - 参数没有值)

      9. 证明转发指定地址并传入参数成功

     

    master-service - 转发指定服务并传入参数

    spring:
      # 配置文件名称,用来标识不同环境的配置。由 spring.profiles.active 的值来决定使用哪组配置。
      ## 转发指定服务并传入参数
      profiles: route_addRequestParameter
      application:
        # 应用名称
        name: gateway-master
      cloud:
        gateway:
          discovery:
            locator:
              # 是否和服务注册与发现组件结合,设置为 true 后可以直接使用应用名称调用服务
              enabled: true
          # 路由(routes:路由,它由唯一标识(ID)、目标服务地址(uri)、一组断言(predicates)和一组过滤器组成(filters)。filters 不是必需参数。)
          routes:
          # 路由标识(id:标识,具有唯一性)   转发指定服务并传入参数
          - id: route_addRequestParameter
            # 目标服务地址(uri:地址,请求转发后的地址)
            uri: lb://gateway-service
            # 路由条件(predicates:断言,匹配 HTTP 请求内容)
            predicates:
            ## 匹配 GET 请求
            - Method=GET
            # 过滤器(filters:过滤器,过滤规则)
            filters:
            ## 添加指定参数
            - AddRequestParameter=age, three
    
    eureka:
      instance:
        # 使用 ip 代替实例名
        prefer-ip-address: true
        # 实例的主机名
        hostname: ${spring.cloud.client.ip-address}
        # 实例的 ID 规则
        instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}
      client:
        serviceUrl:
          # 注册中心地址
          defaultZone: http://${eureka.instance.hostname}:8761/eureka/
    
    logging:
      level:
        # log 级别
        org.springframework.cloud.gateway: debug

      1. 停止注册中心工程(registry-service),网关工程(master-service)和服务工程 A(a-service)

      2. 把 master-service - application.yml 配置文件中最上面的 spring.profiles.active 的值

          更改为 route_addRequestParameter

      3. 上面配置文件内容意思是访问的路径 http://localhost:8000/age (网关地址/age)

          会被转发到 http://gateway-service/age(uri/age),并传入 'age=three' 参数(注意为 Get 请求)

      4. 注意此处的配置 uri: lb://gateway-service 与之前都有所不同,之前都是指定了明确的转发地址,可以满足

          单个服务转发的需求,但是一般情况都会有多个服务,所以这里是指定的服务名称,格式为:lb://应用注册

          服务名。

      5. 启动注册中心工程(registry-service),网关工程(master-service)和服务工程 A/B(a-service、b-service)

      6. 项目启动成功后访问:http://localhost:8000/age

      7. 这时可能会报错 500.错误信息为 'Unable to find instance for gateway-service'

      8. 这种情况不要慌张,只是服务还没有被注册到注册中心,稍等片刻再访问

      9. 多次访问:http://localhost:8000/age

     10. 轮流输出内容:'I am three years old this year. aaa'  'I am three years old this year. bbb'

     11. 此时还通过网关达到了负载均衡的效果

     12. 证明转发指定服务并传入参数成功

     

    master-service - 熔断

    spring:
      # 配置文件名称,用来标识不同环境的配置。由 spring.profiles.active 的值来决定使用哪组配置。
      ## 熔断
      profiles: route_hystrix
      application:
        # 应用名称
        name: gateway-master
      cloud:
        gateway:
          discovery:
            locator:
              # 是否和服务注册与发现组件结合,设置为 true 后可以直接使用应用名称调用服务
              enabled: true
          # 路由(routes:路由,它由唯一标识(ID)、目标服务地址(uri)、一组断言(predicates)和一组过滤器组成(filters)。filters 不是必需参数。)
          routes:
          # 路由标识(id:标识,具有唯一性)   熔断
          - id: route_hystrix
            # 目标服务地址(uri:地址,请求转发后的地址)
            uri: lb://gateway-service
            # 路由条件(predicates:断言,匹配 HTTP 请求内容)
            predicates:
            ## 匹配 GET 请求
            - Method=GET
            # 过滤器(filters:过滤器,过滤规则)
            filters:
            ## 添加指定参数
            - AddRequestParameter=age, three
            ## 熔断
            - name: Hystrix
              args:
                name: fallbackcmd
                ### fallback 时调用的方法 http://localhost:8000/fallback
                fallbackUri: forward:/fallback
    
    eureka:
      instance:
        # 使用 ip 代替实例名
        prefer-ip-address: true
        # 实例的主机名
        hostname: ${spring.cloud.client.ip-address}
        # 实例的 ID 规则
        instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}
      client:
        serviceUrl:
          # 注册中心地址
          defaultZone: http://${eureka.instance.hostname}:8761/eureka/
    
    logging:
      level:
        # log 级别
        org.springframework.cloud.gateway: debug

      1. 停止注册中心工程(registry-service),网关工程(master-service)和服务工程 A/B(a-service、b-service)

      2. 把 master-service - application.yml 配置文件中最上面的 spring.profiles.active 的值更改为 route_hystrix

      3. 上面配置文件内容意思是访问的路径 http://localhost:8000/age (网关地址/age)

          会被转发到 http://gateway-service/age(uri/age),并传入 'age=three' 参数(注意为 Get 请求)

      4. 注意此处的配置 uri: lb://gateway-service 与之前都有所不同,之前都是指定了明确的转发地址,可以满足

          单个服务转发的需求,但是一般情况都会有多个服务,所以这里是指定的服务名称,格式为:lb://应用注册

          服务名。

      5. 此处还多配置了一个过滤器 '- name: Hystrix'(熔断)

      6. 当请求服务出错时,会调用 fallback,路径为:http://localhost:8000/fallback (网关地址/fallback)

      7. 此时就需要如下前端控制器

    master-service - 熔断 - controller

    package com.zwc.gateway.hystrix;
    
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    /**
     * @ClassName FallbackController
     * @Desc TODO   网关断路器
     * @Date 2019/6/23 19:33
     * @Version 1.0
     */
    @RestController
    public class FallbackController {
    
        /*
         * @ClassName FallbackController
         * @Desc TODO   网关断路器
         * @Date 2019/6/23 19:35
         * @Version 1.0
         */
        @RequestMapping("/fallback")
        public String fallback() {
            return "I'm Spring Cloud Gateway fallback.";
        }
    
    }
    

      8. 启动注册中心工程(registry-service),网关工程(master-service)和服务工程 A/B(a-service、b-service)

      9. 项目启动成功后访问:http://localhost:8000/age

     10. 输出内容:'I'm Spring Cloud Gateway fallback.'

     11. 证明熔断成功

     

    master-service - 限流(重点,解决不生效问题)

    spring:
      # 配置文件名称,用来标识不同环境的配置。由 spring.profiles.active 的值来决定使用哪组配置。
      ## 限流
      profiles: route_requestRateLimiter
      redis:
        host: localhost
        port: 6379
        database: 0
      application:
        # 应用名称
        name: gateway-master
      cloud:
        gateway:
          discovery:
            locator:
              # 是否和服务注册与发现组件结合,设置为 true 后可以直接使用应用名称调用服务
              enabled: true
          # 路由(routes:路由,它由唯一标识(ID)、目标服务地址(uri)、一组断言(predicates)和一组过滤器组成(filters)。filters 不是必需参数。)
          routes:
          # 路由标识(id:标识,具有唯一性)   限流
          - id: route_requestRateLimiter
            # 目标服务地址(uri:地址,请求转发后的地址)
            uri: lb://gateway-service
            # 路由条件(predicates:断言,匹配 HTTP 请求内容)
            predicates:
            ## 匹配 GET 请求
            - Method=GET
            # 过滤器(filters:过滤器,过滤规则)
            filters:
            ## 添加指定参数
            - AddRequestParameter=age, three
            ## 限流
            - name: RequestRateLimiter
              args:
                ### 限流过滤器的 Bean 名称
                key-resolver: '#{@uriKeyResolver}'
                ### 希望允许用户每秒处理多少个请求
                redis-rate-limiter.replenishRate: 1
                ### 用户允许在一秒钟内完成的最大请求数
                redis-rate-limiter.burstCapacity: 3
    
    eureka:
      instance:
        # 使用 ip 代替实例名
        prefer-ip-address: true
        # 实例的主机名
        hostname: ${spring.cloud.client.ip-address}
        # 实例的 ID 规则
        instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}
      client:
        serviceUrl:
          # 注册中心地址
          defaultZone: http://${eureka.instance.hostname}:8761/eureka/
    
    logging:
      level:
        # log 级别
        org.springframework.cloud.gateway: debug

      1. 停止注册中心工程(registry-service),网关工程(master-service)和服务工程 A/B(a-service、b-service)

      2. 把 master-service - application.yml 配置文件中最上面的 spring.profiles.active 的值

          更改为 route_requestRateLimiter

      3. 上面配置文件内容意思是访问的路径 http://localhost:8000/age (网关地址/age)

          会被转发到 http://gateway-service/age(uri/age),并传入 'age=three' 参数(注意为 Get 请求)

      4. 注意此处还需要配置 redis 的连接信息

      5. 注意此处是结合 redis 实现的限流,所以 filter 过滤器的 name 必须为 RequestRateLimiter

      6. 并且通过实现 KeyResolver 类来自定义限流策略,如下

    master-service - 限流 - 策略

    package com.zwc.gateway.config.filters;
    
    import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
    import org.springframework.web.server.ServerWebExchange;
    import reactor.core.publisher.Mono;
    
    /**
     * @ClassName UriKeyResolver
     * @Desc TODO   Spring Cloud Gateway 网关限流过滤器
     * @Date 2019/6/23 17:59
     * @Version 1.0
     */
    public class UriKeyResolver implements KeyResolver {
    
        /*
         * @ClassName UriKeyResolver
         * @Desc TODO   根据请求的 uri 限流
         * @Date 2019/6/29 17:25
         * @Version 1.0
         */
        @Override
        public Mono<String> resolve(ServerWebExchange exchange) {
            return Mono.just(exchange.getRequest().getURI().getPath());
        }
    
    }
    

      7. 启动本地 redis(redis-server.exe) 服务

      8. 启动注册中心工程(registry-service),网关工程(master-service)和服务工程 A/B(a-service、b-service)

      9. 项目启动成功后访问:http://localhost:8000/age

     10. 此时限流却无论如何都不生效,原因有如下两点

    ① redis-server 版本过低!我 Windows 本地是 redis-2.4.2 版本的,要用 3 以上的版本!!!

    ② 数据在 redis 中存储的时间只有几秒,所以得使用 monitor 指令来动态的观察!!!

     11. 打开 redis-cli.exe,输入命令 monitor 

     12. 快速刷新地址:http://localhost:8000/age

     13. 页面上会出现 429,redis-cli.exe 中会出现很多数据交互(request_rate_limiter.xxx 开头的 key)

     14. 证明限流成功

     

    master-service - 综合

    spring:
      # 配置文件名称,用来标识不同环境的配置。由 spring.profiles.active 的值来决定使用哪组配置。
      ## 综合
      profiles: route_all
      redis:
        host: localhost
        port: 6379
        database: 0
      application:
        # 应用名称
        name: gateway-master
      cloud:
        gateway:
          discovery:
            locator:
              # 是否和服务注册与发现组件结合,设置为 true 后可以直接使用应用名称调用服务
              enabled: true
          # 路由(routes:路由,它由唯一标识(ID)、目标服务地址(uri)、一组断言(predicates)和一组过滤器组成(filters)。filters 不是必需参数。)
          routes:
          # 路由标识(id:标识,具有唯一性)   综合
          - id: route_all
            # 目标服务地址(uri:地址,请求转发后的地址)
            uri: lb://gateway-service
            # 路由条件(predicates:断言,匹配 HTTP 请求内容)
            predicates:
            ## 转发地址格式为 uri/routeAll,/all 部分会被下面的过滤器给截取掉
            - Path=/all/routeAll
            ## 匹配 GET 请求
            - Method=GET
            # 过滤器(filters:过滤器,过滤规则)
            filters:
            ## 截取路径位数
            - StripPrefix=1
            ## 添加指定参数
            - AddRequestParameter=pass, yes
            ## 熔断
            - name: Hystrix
              args:
                name: fallbackcmd
                ### fallback 时调用的方法 http://localhost:8000/fallback
                fallbackUri: forward:/fallback
            ## 限流
            - name: RequestRateLimiter
              args:
                ### 限流过滤器的 Bean 名称
                key-resolver: '#{@uriKeyResolver}'
                ### 希望允许用户每秒处理多少个请求
                redis-rate-limiter.replenishRate: 1
                ### 用户允许在一秒钟内完成的最大请求数
                redis-rate-limiter.burstCapacity: 3
    
    eureka:
      instance:
        # 使用 ip 代替实例名
        prefer-ip-address: true
        # 实例的主机名
        hostname: ${spring.cloud.client.ip-address}
        # 实例的 ID 规则
        instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}
      client:
        serviceUrl:
          # 注册中心地址
          defaultZone: http://${eureka.instance.hostname}:8761/eureka/
    
    logging:
      level:
        # log 级别
        org.springframework.cloud.gateway: debug

      1. 停止注册中心工程(registry-service),网关工程(master-service)和服务工程 A/B(a-service、b-service)

      2. 把 master-service - application.yml 配置文件中最上面的 spring.profiles.active 的值更改为 route_all

      3. 上面配置文件内容意思是访问的路径 http://localhost:8000/all/routeAll (网关地址/all/routeAll)截取 /all 部分,

          会被转发到 http://gateway-service/routeAll(uri/routeAll),并传入 'pass=yes' 参数(注意为 Get 请求)

      4. 启动注册中心工程(registry-service),网关工程(master-service)和服务工程 A/B(a-service、b-service)

      5. 项目启动成功后访问:http://localhost:8000/all/routeAll

      6. 首先会返回 'I'm Spring Cloud Gateway fallback.',因为服务还未被注册到注册中心

      7. 然后会返回 '{"msg":"缺少凭证","code":-1}',因为配置了全局过滤器,如下

    package com.zwc.gateway.config.filters;
    
    import com.alibaba.fastjson.JSONObject;
    import org.springframework.cloud.gateway.filter.GatewayFilterChain;
    import org.springframework.cloud.gateway.filter.GlobalFilter;
    import org.springframework.core.Ordered;
    import org.springframework.http.HttpStatus;
    import org.springframework.http.server.reactive.ServerHttpRequest;
    import org.springframework.http.server.reactive.ServerHttpResponse;
    import org.springframework.web.server.ServerWebExchange;
    import reactor.core.publisher.Mono;
    import org.springframework.core.io.buffer.DataBuffer;
    
    import java.net.InetSocketAddress;
    import java.nio.charset.StandardCharsets;
    
    /**
     * @ClassName TokenFilter
     * @Desc TODO   请求认证过滤器
     * @Date 2019/6/29 17:49
     * @Version 1.0
     */
    public class TokenFilter implements GlobalFilter{
    
        @Override
        public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
            // 请求对象
            ServerHttpRequest request = exchange.getRequest();
            // 响应对象
            ServerHttpResponse response = exchange.getResponse();
    
            // 只有综合路由才添加这个全局过滤器(routesId:route_all)
            // 如果请求路径中不存在 routeAll 字符串
            if(request.getURI().toString().indexOf("routeAll") == -1){
                System.out.println("filter -> return");
                // 直接跳出
                return chain.filter(exchange);
            }
    
            // 从请求中获取 token 参数
            String token = exchange.getRequest().getQueryParams().getFirst("token");
            // 如果为空,那么将返回 401
            if (token == null || token.isEmpty()) {
    
                // 响应消息内容对象
                JSONObject message = new JSONObject();
                // 响应状态
                message.put("code", -1);
                // 响应内容
                message.put("msg", "缺少凭证");
                // 转换响应消息内容对象为字节
                byte[] bits = message.toJSONString().getBytes(StandardCharsets.UTF_8);
                DataBuffer buffer = response.bufferFactory().wrap(bits);
                // 设置响应对象状态码 401
                response.setStatusCode(HttpStatus.UNAUTHORIZED);
                // 设置响应对象内容并且指定编码,否则在浏览器中会中文乱码
                response.getHeaders().add("Content-Type", "text/plain;charset=UTF-8");
                // 返回响应对象
                return response.writeWith(Mono.just(buffer));
            }
            // 获取请求地址
            String beforePath = request.getPath().pathWithinApplication().value();
            // 获取响应状态码
            HttpStatus beforeStatusCode = response.getStatusCode();
            System.out.println("响应码:" + beforeStatusCode + ",请求路径:" + beforePath);
            // 请求前
            System.out.println("filter -> before");
            // 如果不为空,就通过
            return chain.filter(exchange).then(Mono.fromRunnable(() -> {
                // 获取请求地址
                String afterPath = request.getPath().pathWithinApplication().value();
                // 获取响应状态码
                HttpStatus afterStatusCode = response.getStatusCode();
                System.out.println("响应码:" + afterStatusCode + ",请求路径:" + afterPath);
                // 响应后
                System.out.println("filter -> after");
            }));
        }
    
    }
    

      8. 全局过滤器,不需要配置在配置文件中,作用于所有路由;只是这里在处理前做了判断,只有路径中存在

          routeAll 字符串才到后续处理;并且处理分为请求前的处理,和响应后的处理

      9. 此时在地址:http://localhost:8000/all/routeAll 中添加 token 参数

     10. 访问:http://localhost:8000/all/routeAll?token=123

     11. 轮流输出内容:'Can I pass? yes! port:9000' 和 'Can I pass? yes! port:9001'

     12. 观察 gateway 工程的控制台,会有如下内容输出

    响应码:null,请求路径:/routeAll
    filter -> before
    响应码:200,请求路径:/routeAll
    filter -> after

     13. 证明全局过滤器过滤成功

     

    service 工程 - 项目结构

     

    把多工程项目使用 IntelliJ IDEA 打开

    1. 把项目从 GitHub 中下载到你的本地
    2. 打开 IntelliJ IDEA 
    3. 点击 File -> Open
    4. 打开你下载到本地的项目目录
    5. springcloud-gateway -> springcloud-gateway-service(选择打开此工程)
    6. 打开 service 工程后
    7. 再次点击 File -> Project Structrue
    8. 选择 Modules,点击 '+' 符号
    9. 点击 Import  Module
    10. 还是打开你下载到本地的项目目录
    11. springcloud-gateway -> springcloud-gateway-commons -> pom.xml
    12. 点击 OK
    13. 点击 Next,Finish
    14. 点击 Apply,OK

     


     

    希望能够帮助到你

    over

     

     

     

    展开全文
  • 微服务gateway 简单总结

    千次阅读 2019-10-17 18:06:12
    API 网关(API Gateway)主要负责服务请求路由、组合及协议转换。下面是大家的总结: 一、最佳回答 网关的技术选型 SpringCloud-Zuul : 社区活跃,基于 SrpingCloud 完整生态, 是构建微服务体系前置网关服务的...

    用 Spring Cloud 微服务实战中,大家都知道用 Zuul 作为智能网关。API 网关(API Gateway)主要负责服务请求路由、组合及协议转换。下面是大家的总结:

    一、最佳回答

    网关的技术选型

    1. SpringCloud-Zuul :

      社区活跃,基于 SrpingCloud 完整生态, 是构建微服务体系前置网关服务的最佳选型.

    2. Kong : 基于OpenResty的 API 网关服务和网关服务管理层.

    3. 自建网关服务: 如 谈谈基于 OpenResty 的接口网关设计

    网关的设计要素

    系统级别

    • 高可用性
    • 均衡负载: 容错,防止雪崩.
    • 并发控制 : 错峰流控
    • 动态路由制定和修改

    应用级别

    • 监控统计
    • 版本控制
    • 认证 鉴权
    • 数据安全: 防篡改,参数脱敏…
    • 协议转换: 如 HTTP => RPC协议.

    其他(个人 YY)

    • 基于机器学习, 预测流量高峰.

    二、此时此刻的总结

    1. 网关(API Gateway)技术选型

      • zuul
      • kong
      • nginx+lua
    2. 网关(API Gateway)的设计要素

      • 限流:实现微服务访问流量计算,基于流量计算分析进行限流,可以定义多种限流规则。
      • 缓存:数据缓存。
      • 日志:日志记录。
      • 监控:记录请求响应数据,api耗时分析,性能监控。
      • 鉴权:权限身份认证。
      • 灰度:线上灰度部署,可以减小风险。
      • 路由:路由是API网关很核心的模块功能,此模块实现根据请求,锁定目标微服务并将请求进行转发。
    3. 简单介绍下你的网关实施方案

      • 开发语言:java + groovy,groovy的好处是网关服务不需要重启就可以动态的添加filter来实现一些功能;
      • 微服务基础框架:springboot;
      • 网关基础组件:netflix zuul;
      • 服务注册中心:consul;
      • 权限校验:jwt;
      • API监控:prometheus + grafana;
      • API统一日志收集:logback + ELK;
      • 压力测试:Jmeter;

    比如限流 你需要缓存一些限流的策略,主要是缓存网关功能用到的一些数据,不涉及业务数据。 路由主要是做转发

    三、IronCity 的总结

    目前,我们业务代码是多语言的环境,网关则是用go写的,目前主要是做到了对于HTTP和Thrift的业务服务的转发(HTTP利用了fasthttp,Thrift用的网关启动客户端调用业务服务端的形式)过滤器是环绕的,系统统一的过滤和针对API级别的过滤。虽然用了go比较轻巧,但是目前功能还很值得完善

    四、XuChuangfeng 的总结

    设计要素:#1,高可用非常重要;#2,网关需要支持动态修改路由规则;#3,与服务注册中心整合,通过注册中心实现路由转发;#4,过滤器链适配不同的路由。

    五、fudali113 的总结

    选型

    • 所使用的网关架构必须灵活,因为我们可能需要很多与我们业务相关的定制话的东西
    • 有平台背书,获取有足够的证据证明他是一个能抗的住我们需求的并发的性能
    • 根据需求选择最好的方案

      设计要素

    • 结构必须灵活,方便扩展
    • 基础的功能应该由框架提供或者抽象,比如动态路由,权限校验,限流

      我的

      我们使用zuul作为网关并对他进行了一定定制化的开发,因为我们使用springcloud技术栈,同时zuul基于filter来处理一切的结构也是非常灵活的,并且由netflix背书。我们在网关利用filter加入权限校验,统一访问日志记录,访问异常请求记录,聚合请求处理器等相关功能

    负载均衡可以通过在之前加入一个nginx或者dns解析来做,高可用可以通过keepalived加虚拟ip与nginx结合或者直接与zuul结合来做

    六、Ascend 总结

    1. 能处理一些公共的逻辑,比如获取token
    2. 能支持动态的修改路由规则
    3. 对各服务结果和异常进行统一处理后返给调用方
      目前实施了几套方案,自己封装的gateway层,准备用zuul进行替代

    七、曼陀罗 总结

    网关的技术选型

    1. SpringCloud-Zuul :社区活跃,基于 SrpingCloud 完整生态, 是构建微服务体系前置网关服务的最佳选型.
    2. Kong : 基于OpenResty的 API 网关服务和网关服务管理层.
    3. Nginx+Lua:成熟度也算可以
    4. 自建网关:成本较高

    网关(API Gateway)的设计要素(高可用,安全)

    • 性能:API高可用,负载均衡,容错机制。
    • 安全:权限身份认证、脱敏,流量清洗,后端签名(保证全链路可信调用),黑名单(非法调用的限制)。
    • 日志:日志记录(spainid,traceid)一旦涉及分布式,全链路跟踪必不可少。
    • 缓存:数据缓存。
    • 监控:记录请求响应数据,api耗时分析,性能监控。
    • 限流:流量控制,错峰流控,目前有漏桶算法、令牌桶算法也可以定制限流规则。
    • 灰度:线上灰度部署,可以减小风险。
    • 路由:动态路由规则。
    • 静态:代理

    简单介绍下你的网关实施方案

    • 微服务基础框架:springboot;
    • 网关基础组件:zuul;
    • 服务注册中心:consul;
    • API监控:prometheus + grafana or 自建;
    • API统一日志收集:时序db + ELK;
    • 压力测试:Jmeter,AB,阿里压测;

     

    展开全文
  • Spring cloud gateway 详解和配置使用(文章较长)

    万次阅读 多人点赞 2019-11-08 10:36:15
    spring cloud gateway 介绍 1. 网关是怎么演化来的 2. 网关的基本功能 3.关于Spring Cloud Gateway 4.Spring Cloud Gateway 功能特征 5.predicate简介 6.GatewayFilter 工厂介绍 7.集成Hystrix的断路器功能 ...

                  Spring cloud gateway 处理跨域问题

                  Spring cloud gateway 拦截请求404 等HTTP 状态码

                  Spring cloud gateway 修改response 截断问题,乱码问题解决 

                  Spring cloud gateway 设置https 和http同时支持

                  Spring cloud Gateway 指定执行过滤器 (在配置文件中配置所需要过滤器)

    目录

    spring cloud gateway 介绍

    1. 网关是怎么演化来的

    2. 网关的基本功能

    3.关于Spring Cloud Gateway

    4.Spring Cloud Gateway 功能特征

    5.predicate简介

    6.GatewayFilter 工厂介绍

    7.集成Hystrix的断路器功能

    8.请求限流

    pom.xml

    application.yml

    IP限流

    用户限流

    接口限流


    spring cloud gateway 介绍

     

    1. 网关是怎么演化来的

    单体应用拆分成多个服务后,对外需要一个统一入口,解耦客户端与内部服务

    img

    注:图片来自网络

    2. 网关的基本功能

    • 网关核心功能是路由转发,因此不要有耗时操作在网关上处理,让请求快速转发到后端服务上

      • 网关还能做统一的熔断、限流、认证、日志监控等 在这里插入图片描述注:图片来自网络

      可以和服务注册中心完美的整合,如:Eureka、Consul、Nacos

     

    3.关于Spring Cloud Gateway

    在SpringCloud微服务体系中,有个很重要的组件就是网关,在1.x版本中都是采用的Zuul网关;但在2.x版本中,zuul的升级一直跳票,SpringCloud最后自己研发了一个网关替代Zuul,那就是SpringCloud Gateway

    网上很多地方都说Zuul是阻塞的,Gateway是非阻塞的,这么说是不严谨的,准确的讲Zuul1.x是阻塞的,而在2.x的版本中,Zuul也是基于Netty,也是非阻塞的,如果一定要说性能,其实这个真没多大差距。

    而官方出过一个测试项目,创建了一个benchmark的测试项目:spring-cloud-gateway-bench,其中对比了:

    • Spring Cloud Gateway

    • Zuul1.x

    • Linkerd

    Proxy Avg Latency Avg Req/Sec/Thread
    gateway 6.61ms 3.24k
    linkered 7.62ms 2.82k
    zuul 12.56ms 2.09k
    none 2.09ms 11.77k

    还有一点就是Gateway是基于WebFlux的。这里引出了WebFlux名词,那什么是WebFlux?

    WebFlux 介绍

    img注:图片来自网络

    左侧是传统的基于Servlet的Spring Web MVC框架,

    传统的Web框架,比如说:struts2,springmvc等都是基于Servlet API与Servlet容器基础之上运行的,在Servlet3.1之后才有了异步非阻塞的支持。

    右侧是5.0版本新引入的基于Reactive StreamsSpring WebFlux框架,从上到下依次是Router Functions,WebFlux,Reactive Streams三个新组件。

    Router Functions: 对标@Controller,@RequestMapping等标准的Spring MVC注解,提供一套函数式风格的API,用于创建Router,HandlerFilter

    WebFlux: 核心组件,协调上下游各个组件提供响应式编程支持。

    Reactive Streams: 一种支持背压(Backpressure)的异步数据流处理标准,主流实现有RxJava和Reactor,Spring WebFlux默认集成的是Reactor。

    在Web容器的选择上,Spring WebFlux既支持像Tomcat,Jetty这样的的传统容器(前提是支持Servlet 3.1 Non-Blocking IO API),又支持像Netty,Undertow那样的异步容器。不管是何种容器,Spring WebFlux都会将其输入输出流适配成Flux<DataBuffer>格式,以便进行统一处理。

    值得一提的是,除了新的Router Functions接口,Spring WebFlux同时支持使用老的Spring MVC注解声明Reactive Controller。和传统的MVC Controller不同,Reactive Controller操作的是非阻塞的ServerHttpRequest和ServerHttpResponse,而不再是Spring MVC里的HttpServletRequest和HttpServletResponse。

    根据官方的说法,webflux主要在如下两方面体现出独有的优势

    1)非阻塞式

    其实在servlet3.1提供了非阻塞的API,WebFlux提供了一种比其更完美的解决方案。使用非阻塞的方式可以利用较小的线程或硬件资源来处理并发进而提高其可伸缩性

    2) 函数式编程端点

    老生常谈的编程方式了,Spring5必须让你使用java8,那么函数式编程就是java8重要的特点之一,而WebFlux支持函数式编程来定义路由端点处理请求。

    IO模式和IO多路复用(阻塞IO、非阻塞IO、同步IO、异步IO等概念)这里就不在阐述,因为不在本分享范围之内!

    4.Spring Cloud Gateway 功能特征

    • 基于Spring Framework 5, Project Reactor 和 Spring Boot 2.0 进行构建;

    • 动态路由:能够匹配任何请求属性;

    • 集成 Spring Cloud 服务发现功能;

    • 可以对路由指定 Predicate(断言)和 Filter(过滤器);

    • 易于编写的 Predicate(断言)和 Filter(过滤器);

    • 集成Hystrix的断路器功能;

    • 请求限流功能;

    • 支持路径重写。

    img

    注:图片来自网络

    上图中是核心的流程图,最主要的就是Route、Predicates 和 Filters 作用于特定路由

    1)Route:**路由是网关的基本构件**。它由ID、目标URI、谓词集合和过滤器集合定义。如果聚合谓词为真,则匹配路由。

    2)Predicate:**参照Java8的新特性Predicate**。这允许开发人员匹配HTTP请求中的任何内容,比如头或参数。

    3)Filter:可以在发送下游请求之前或之后修改请求和响应。

    我们为什么选择Gateway?

    一方面因为Zuul已经进入了维护阶段,而且Gateway是SpringCloud团队研发的,是亲儿子产品,值得信赖。而且很多功能Zuul都没有;用起来也非常的简单便捷。

    Gateway是基于异步非阻塞模型上进行开发的,性能方面不需要担心。虽然Netflix 早就发布了最新的 Zuul 2.x,但 Spring Cloud 貌似没有整合计划。而且Netflix相关组件都宣布进入维护期;不知前景如何?

    多方面综合考虑Gateway是很理想的网关选择。

    Spring Cloud Gateway 工作原理

    img注:该图片来自官网

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

    Filter在“pre”类型的过滤器可以做参数校验、权限校验、流量监控、日志输出、协议转换等,

    “post”类型的过滤器中可以做响应内容、响应头的修改,日志的输出,流量监控等有着非常重要的作用。

    核心逻辑就是路由转发,执行过滤器链。

    在上面的处理过程中,有一个重要的点就是讲请求和路由进行匹配,这时候就需要用到predicate,它是决定了一个请求走哪一个路由。

    5.predicate简介

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

    Spring Cloud Gateway内置了许多Predict,这些Predict的源码在org.springframework.cloud.gateway.handler.predicate包中,有兴趣可以阅读一下。现在列举各种Predicate如下图:

    img

    注:图片来自网络

    在上图中,有很多类型的Predicate,比如说时间类型的Predicated(AfterRoutePredicateFactory BeforeRoutePredicateFactory BetweenRoutePredicateFactory),当只有满足特定时间要求的请求会进入到此predicate中,并交由router处理;cookie类型的CookieRoutePredicateFactory,指定的cookie满足正则匹配,才会进入此router;以及host、method、path、querparam、remoteaddr类型的predicate,每一种predicate都会对当前的客户端请求进行判断,是否满足当前的要求,如果满足则交给当前请求处理。如果有很多个Predicate,并且一个请求满足多个Predicate,则按照配置的顺序第一个生效。

    1. After Route Predicate Factory

    After Route Predicate Factory使用的是时间作为匹配规则,只要当前时间大于设定时间,路由才会匹配请求。 application.yml

    spring:  
        cloud:    
            gateway:      
                routes:      
                - id: after_route        
                  uri: http://www.google.com        
                  predicates:        
                  - After=2018-12-25T14:33:47.789+08:00

    这个路由规则会在东8区的2018-12-25 14:33:47后,将请求都转跳到google。

    2. Before Route Predicate Factory

    Before Route Predicate Factory也是使用时间作为匹配规则,只要当前时间小于设定时间,路由才会匹配请求。 application.yml

    spring:  
        cloud:    
            gateway:      
                routes:      
                - id: before_route        
                  uri: http://www.google.com        
                  predicates:        
                  - Before=2018-12-25T14:33:47.789+08:00

    这个路由规则会在东8区的2018-12-25 14:33:47前,将请求都转跳到google。

    3. Between Route Predicate Factory

    Between Route Predicate Factory也是使用两个时间作为匹配规则,只要当前时间大于第一个设定时间,并小于第二个设定时间,路由才会匹配请求。

    application.yml

    spring:  
        cloud:   
            gateway:      
                routes:      
                - id: between_route        
                  uri: http://www.google.com        
                  predicates:        
                  - Between=2018-12-25T14:33:47.789+08:00, 2018-12-26T14:33:47.789+08:00

    这个路由规则会在东8区的2018-12-25 14:33:47到2018-12-26 14:33:47之间,将请求都转跳到google。

    4. Cookie Route Predicate Factory

    Cookie Route Predicate Factory使用的是cookie名字和正则表达式的value作为两个输入参数,请求的cookie需要匹配cookie名和符合其中value的正则。 application.yml

    spring: 
        cloud:    
            gateway:  
                routes:      
                - id: cookie_route       
                  uri: http://www.google.com        
                  predicates:        
                  - Cookie=cookiename, cookievalue

    路由匹配请求存在cookie名为cookiename,cookie内容匹配cookievalue的,将请求转发到google。

    5. Header Route Predicate Factory

    Header Route Predicate Factory,与Cookie Route Predicate Factory类似,也是两个参数,一个header的name,一个是正则匹配的value。 application.yml

    spring:  
        cloud:    
            gateway:     
                routes:      
                - id: header_route        
                  uri: http://www.google.com        
                  predicates:        
                  - Header=X-Request-Id, \d+

    路由匹配存在名为X-Request-Id,内容为数字的header的请求,将请求转发到google。

    6. Host Route Predicate Factory

    Host Route Predicate Factory使用的是host的列表作为参数,host使用Ant style匹配。 application.yml

    spring:  
        cloud:    
            gateway:      
                routes:      
                - id: host_route        
                  uri: http://www.google.com        
                  predicates:        
                  - Host=**.somehost.org,**.anotherhost.org

    路由会匹配Host诸如:www.somehost.orgbeta.somehost.orgwww.anotherhost.org等请求。

    7. Method Route Predicate Factory

    Method Route Predicate Factory是通过HTTP的method来匹配路由。 application.yml

    spring:  
        cloud:    
            gateway:      
                routes:      
                - id: method_route        
                  uri: http://www.google.com        
                  predicates:        
                  - Method=GET

    路由会匹配到所有GET方法的请求。

    8. Path Route Predicate Factory

    Path Route Predicate Factory使用的是path列表作为参数,使用Spring的PathMatcher匹配path,可以设置可选变量。 application.yml

    spring:  
        cloud:    
            gateway:      
                routes:      
                - id: host_route        
                  uri: http://www.google.com       
                  predicates:        
                  - Path=/foo/{segment},/bar/{segment}

    上面路由可以匹配诸如:/foo/1/foo/bar/bar/baz等 其中的segment变量可以通过下面方式获取:

    PathMatchInfo variables = exchange.getAttribute(URI_TEMPLATE_VARIABLES_ATTRIBUTE);
    Map<String, String> uriVariables = variables.getUriVariables();
    String segment = uriVariables.get("segment");
    

    在后续的GatewayFilter Factories就可以做对应的操作了。

    9. Query Route Predicate Factory

    Query Route Predicate Factory可以通过一个或两个参数来匹配路由,一个是查询的name,一个是查询的正则value。 application.yml

    spring:  
    	cloud:    
    		gateway:      
    			routes:      
    			- id: query_route        
    			  uri: http://www.google.com        
    			  predicates:        
    			  - Query=baz
    

    路由会匹配所有包含baz查询参数的请求。 application.yml

    spring:  
    	cloud:    
    		gateway:      
    			routes:      
    			- id: query_route       
                  uri: http://www.google.com        
                  predicates:       
                  - Query=foo, ba.
    

    路由会匹配所有包含foo,并且foo的内容为诸如:barbaz等符合ba.正则规则的请求。

    10. RemoteAddr Route Predicate Factory

    RemoteAddr Route Predicate Factory通过无类别域间路由(IPv4 or IPv6)列表匹配路由。 application.yml

    spring:  
    	cloud:    
    		gateway:    
            	routes:      
            	- id: remoteaddr_route        
            	  uri: http://www.google.com        
            	  predicates:        
            	  - RemoteAddr=192.168.1.1/24
    

    上面路由就会匹配RemoteAddr诸如192.168.1.10等请求。

    10.1 Modifying the way remote addresses are resolved

    RemoteAddr Route Predicate Factory默认情况下,使用的是请求的remote address。但是如果Spring Cloud Gateway是部署在其他的代理后面的,如Nginx,则Spring Cloud Gateway获取请求的remote address是其他代理的ip,而不是真实客户端的ip。

    考虑到这种情况,你可以自定义获取remote address的处理器RemoteAddressResolver。当然Spring Cloud Gateway也提供了基于X-Forwarded-For请求头的XForwardedRemoteAddressResolver熟悉Http代理协议的,都知道X-Forwarded-For头信息做什么的,不熟悉的可以自己谷歌了解一下。

    XForwardedRemoteAddressResolver提供了两个静态方法获取它的实例: XForwardedRemoteAddressResolver::trustAll得到的RemoteAddressResolver总是获取X-Forwarded-For的第一个ip地址作为remote address,这种方式就比较容易被伪装的请求欺骗,模拟请求很容易通过设置初始的X-Forwarded-For头信息,就可以欺骗到gateway。

    XForwardedRemoteAddressResolver::maxTrustedIndex得到的RemoteAddressResolver则会在X-Forwarded-For信息里面,从右到左选择信任最多maxTrustedIndex个ip,因为X-Forwarded-For是越往右是越接近gateway的代理机器ip,所以是越往右的ip,信任度是越高的。 那么如果前面只是挡了一层Nginx的话,如果只需要Nginx前面客户端的ip,则maxTrustedIndex取1,就可以比较安全地获取真实客户端ip。

    使用java的配置: GatewayConfig.java

    RemoteAddressResolver resolver = XForwardedRemoteAddressResolver.maxTrustedIndex(1);
    ...
        .route("direct-route", r -> r.remoteAddr("10.1.1.1", "10.10.1.1/24")        .uri("http://www.google.com")
        .route("proxied-route",r -> r.remoteAddr(resolver,  "10.10.1.1", "10.10.1.1/24")        .uri("http://www.google.com"))
    

    6.GatewayFilter 工厂介绍

     

    Route filters可以通过一些方式修改HTTP请求的输入和输出,针对某些特殊的场景,Spring Cloud Gateway已经内置了很多不同功能的GatewayFilter Factories。

    下面就来通过例子逐一讲解这些GatewayFilter Factories。

    1. AddRequestHeader GatewayFilter Factory

    AddRequestHeader GatewayFilter Factory通过配置name和value可以增加请求的header。 application.yml

    spring:  
    	cloud:    
    		gateway:   
            	routes: 
                - id: add_request_header_route  
                  uri: http://www.google.com  
                  filters:
                  - AddRequestHeader=X-Request-Foo, Bar
    

    对匹配的请求,会额外添加X-Request-Foo:Bar的header。

    2. AddRequestParameter GatewayFilter Factory

    AddRequestParameter GatewayFilter Factory通过配置name和value可以增加请求的参数。 application.yml

    spring:  
    	cloud:  
        	gateway:   
            	routes:      
            	- id: add_request_parameter_route     
                  uri: http://www.google.com     
                  filters:       
                  - AddRequestParameter=foo, bar
    

    对匹配的请求,会额外添加foo=bar的请求参数。

    3. AddResponseHeader GatewayFilter Factory

    AddResponseHeader GatewayFilter Factory通过配置name和value可以增加响应的header。 application.yml

    spring:  
    	cloud:   
        	gateway:  
            	routes:      
            	- id: add_request_header_route    
                  uri: http://www.google.com     
                  filters:        
                  - AddResponseHeader=X-Response-Foo, Bar
    

    对匹配的请求,响应返回时会额外添加X-Response-Foo:Bar的header返回。

    4. Hystrix GatewayFilter Factory

    Hystrix是Netflix实现的断路器模式工具包,The Hystrix GatewayFilter就是将断路器使用在gateway的路由上,目的是保护你的服务避免级联故障,以及在下游失败时可以降级返回。

    项目里面引入spring-cloud-starter-netflix-hystrix依赖,并提供HystrixCommand的名字,即可生效Hystrix GatewayFilter。 application.yml

    spring:  
    	cloud:    
    		gateway:      
    			routes:     
            	- id: hystrix_route      
                  uri: http://www.google.com     
                  filters:        
                  - Hystrix=myCommandName
    

    那么剩下的过滤器,就会包装在名为myCommandName的HystrixCommand中运行。

    Hystrix过滤器也是通过配置可以参数fallbackUri,来支持路由熔断后的降级处理,降级后,请求会跳过fallbackUri配置的路径,目前只支持forward:的URI协议。 application.yml

    spring:
      cloud:
        gateway:
          routes:
          - id: hystrix_route
            uri: lb://backing-service:8088
            predicates:
            - Path=/consumingserviceendpoint
            filters:
            - name: Hystrix
              args:
                name: fallbackcmd
                fallbackUri: forward:/incaseoffailureusethis
    
    

    当Hystrix降级后就会将请求转发到/incaseoffailureusethis

    整个流程其实是用fallbackUri将请求跳转到gateway内部的controller或者handler,然而也可以通过以下的方式将请求转发到外部的服务: application.yml

    spring:
      cloud:
        gateway:
          routes:
          - id: ingredients
            uri: lb://ingredients
            predicates:
            - Path=//ingredients/**
            filters:
            - name: Hystrix
              args:
                name: fetchIngredients
                fallbackUri: forward:/fallback
          - id: ingredients-fallback
            uri: http://localhost:9994
            predicates:
            - Path=/fallback
    

    以上的例子,gateway降级后就会将请求转发到http://localhost:9994

    Hystrix Gateway filter在转发降级请求时,会将造成降级的异常设置在ServerWebExchangeUtils.HYSTRIX_EXECUTION_EXCEPTION_ATTR属性中,在处理降级时也可以用到。

    比如下一节讲到的FallbackHeaders GatewayFilter Factory,就会通过上面的方式拿到异常信息,设置到降级转发请求的header上,来告知降级下游异常信息。

    通过下面配置可以设置Hystrix的全局超时信息: application.yml

    hystrix.command.fallbackcmd.execution.isolation.thread.timeoutInMilliseconds: 5000
    

    5. FallbackHeaders GatewayFilter Factory

    FallbackHeaders GatewayFilter Factory可以将Hystrix执行的异常信息添加到外部请求的fallbackUriheader上。 application.yml

    spring:
      cloud:
        gateway:
          routes:
          - id: ingredients
            uri: lb://ingredients
            predicates:
            - Path=//ingredients/**
            filters:
            - name: Hystrix
              args:
                name: fetchIngredients
                fallbackUri: forward:/fallback
          - id: ingredients-fallback
            uri: http://localhost:9994
            predicates:
            - Path=/fallback
            filters:
            - name: FallbackHeaders
              args:
                executionExceptionTypeHeaderName: Test-Header
    

    在这个例子中,当请求lb://ingredients降级后,FallbackHeadersfilter会将HystrixCommand的异常信息,通过Test-Header带给http://localhost:9994服务。

    你也可以使用默认的header,也可以像上面一下配置修改header的名字:

    • executionExceptionTypeHeaderName ("Execution-Exception-Type")

    • executionExceptionMessageHeaderName ("Execution-Exception-Message")

    • rootCauseExceptionTypeHeaderName ("Root-Cause-Exception-Type")

    • rootCauseExceptionMessageHeaderName ("Root-Cause-Exception-Message")

    6. PrefixPath GatewayFilter Factory

    The PrefixPath GatewayFilter Factor通过设置prefix参数来路径前缀。 application.yml

    spring:
      cloud:
        gateway:
          routes:
          - id: prefixpath_route
            uri: http://www.google.com
            filters:
            - PrefixPath=/mypath
    
    

    如果一个请求是/hello,通过上面路由,就会将请求修改为/mypath/hello

    7. PreserveHostHeader GatewayFilter Factory

    PreserveHostHeader GatewayFilter Factory会保留原始请求的host头信息,并原封不动的转发出去,而不是被gateway的http客户端重置。

    application.yml:

    spring:
      cloud:
        gateway:
          routes:
          - id: preserve_host_route
            uri: http://www.google.com
            filters:
            - PreserveHostHeader
    
    

    8. RequestRateLimiter GatewayFilter Factory

    RequestRateLimiter GatewayFilter Factory使用RateLimiter来决定当前请求是否允许通过,如果不允许,则默认返回状态码HTTP 429 - Too Many Requests

    RequestRateLimiter GatewayFilter可以使用一个可选参数keyResolver来做速率限制。

    keyResolverKeyResolver接口的一个实现bean,在配置里面,通过SpEL表达式#{@myKeyResolver}来管理bean的名字myKeyResolver

    KeyResolver.java.

    public interface KeyResolver {
    	Mono<String> resolve(ServerWebExchange exchange);
    }
    

    KeyResolver接口允许你使用不同的策略来得出限制请求的key,未来,官方也会推出一些KeyResolver的不同实现。

    KeyResolver默认实现是PrincipalNameKeyResolver,通过ServerWebExchange中获取Principal,并以Principal.getName()作为限流的key。

    如果KeyResolver拿不到key,请求默认都会被限制,你也可以自己配置spring.cloud.gateway.filter.request-rate-limiter.deny-empty-key:是否允许空key,spring.cloud.gateway.filter.request-rate-limiter.empty-key-status-code :空key时返回的状态码。

    RequestRateLimiter不支持捷径配置,如下面的配置是非法的

    application.properties.

    # INVALID SHORTCUT CONFIGURATION
    spring.cloud.gateway.routes[0].filters[0]=RequestRateLimiter=2, 2, #{@userkeyresolver}
    
    

    8.1 Redis RateLimiter

    基于 Stripe的redis实现方案,依赖spring-boot-starter-data-redis-reactiveSpring Boot starter,使用的是令牌桶算法。

    redis-rate-limiter.replenishRate配置的是每秒允许通过的请求数,其实就是令牌桶的填充速率。

    redis-rate-limiter.burstCapacity配置的是一秒内最大的请求数,其实就是令牌桶的最大容量,如果设置为0,则会阻塞所有请求。

    所以可以通过设置相同的replenishRateburstCapacity来实现匀速的速率控制,通过设置burstCapacity大于replenishRate来允许系统流量瞬间突发,但是对于这种情况,突发周期为burstCapacity / replenishRate秒,如果周期内有两次请求突发的情况,则第二次会有部分请求丢失,返回HTTP 429 - Too Many Requests

    application.yml.

    spring:
      cloud:
        gateway:
          routes:
          - id: requestratelimiter_route
            uri: http://www.google.com
            filters:
            - name: RequestRateLimiter
              args:
                redis-rate-limiter.replenishRate: 10
                redis-rate-limiter.burstCapacity: 20
    
    

    Config.java.

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

    上面定义了每个用户每秒10个请求的速率限制,允许20的突发流量,突发完,下一秒只允许10个请求通过了,KeyResolver定义了通过请求获取请求参数user作为key。

    你也可以实现RateLimiter接口自定义自己的请求速率限制器,在配置文件中使用SpEL表达式配置对应的bean的名字即可。

    application.yml.

    spring:
      cloud:
        gateway:
          routes:
          - id: requestratelimiter_route
            uri: http://www.google.com
            filters:
            - name: RequestRateLimiter
              args:
                rate-limiter: "#{@myRateLimiter}"
                key-resolver: "#{@userKeyResolver}"
    

    在最后有对请求限流具体介绍

    9. RedirectTo GatewayFilter Factory

    RedirectTo GatewayFilter Factory使用statusurl两个参数,其中status必须是300系列的HTTP状态码,url则是跳转的地址,会放在响应的Location的header中(http协议中转跳的header)。

    application.yml.

    spring:
      cloud:
        gateway:
          routes:
          - id: prefixpath_route
            uri: http://www.google.cn
            filters:
            - RedirectTo=302, http://www.edjdhbb.com
    
    

    上面路由会执行302重定向到http://www.edjdhbb.com。

    10. RemoveNonProxyHeaders GatewayFilter Factory

    RemoveNonProxyHeaders GatewayFilter Factory转发请求是会根据IETF的定义,默认会移除下列的http头信息:

    • Connection

    • Keep-Alive

    • Proxy-Authenticate

    • Proxy-Authorization

    • TE

    • Trailer

    • Transfer-Encoding

    • Upgrade

    你也可以通过配置spring.cloud.gateway.filter.remove-non-proxy-headers.headers来更改需要移除的header列表。

    11. RemoveRequestHeader GatewayFilter Factory

    RemoveRequestHeader GatewayFilter Factory配置header的name,即可以移除请求的header。

    application.yml.

    spring:
      cloud:
        gateway:
          routes:
          - id: removerequestheader_route
            uri: http://www.google.com
            filters:
            - RemoveRequestHeader=X-Request-Foo
    
    

    上面路由在发送请求给下游时,会将请求中的X-Request-Foo头信息去掉。

    12. RemoveResponseHeader GatewayFilter Factory

    RemoveResponseHeader GatewayFilter Factory通过配置header的name,会在响应返回时移除header。

    application.yml.

    spring:
      cloud:
        gateway:
          routes:
          - id: removeresponseheader_route
            uri: http://www.google.com
            filters:
            - RemoveResponseHeader=X-Response-Foo
    
    

    上面路由会在响应返回给gateway的客户端时,将X-Response-Foo响应头信息去掉。

    13. RewritePath GatewayFilter Factory

    RewritePath GatewayFilter Factory使用路径regexp和替换路径replacement两个参数做路径重写,两个都可以灵活地使用java的正则表达式。

    application.yml.

    spring:
      cloud:
        gateway:
          routes:
          - id: rewritepath_route
            uri: http://www.google.com
            predicates:
            - Path=/foo/**
            filters:
            - RewritePath=/foo/(?<segment>.*), /$\{segment}
    
    

    对于上面的例子,如果请求的路径是/foo/bar,则gateway会将请求路径改为/bar发送给下游。

    注:在YAML 的格式中使用$\来代替$

    14. RewriteResponseHeader GatewayFilter Factory

    RewriteResponseHeader GatewayFilter Factory的作用是修改响应返回的header内容,需要配置响应返回的header的name,匹配规则regexp和替换词replacement,也是支持java的正则表达式。

    application.yml.

    spring:
      cloud:
        gateway:
          routes:
          - id: rewriteresponseheader_route
            uri: http://www.google.com
            filters:
            - RewriteResponseHeader=X-Response-Foo, , password=[^&]+, password=***
    
    

    举个例子,对于上面的filter,如果响应的headerX-Response-Foo的内容是/42?user=ford&password=omg!what&flag=true,这个内容会修改为/42?user=ford&password=***&flag=true

    15. SaveSession GatewayFilter Factory

    SaveSession GatewayFilter Factory会在请求下游时强制执行WebSession::save方法,用在那种像Spring Session延迟数据存储的,并在请求转发前确保session状态保存情况。

    application.yml.

    spring:
      cloud:
        gateway:
          routes:
          - id: save_session
            uri: http://www.google.com
            predicates:
            - Path=/foo/**
            filters:
            - SaveSession
    

    如果你将Spring SecutirySpring Session集成使用,并想确保安全信息都传到下游机器,你就需要配置这个filter。

    16. SecureHeaders GatewayFilter Factory

    SecureHeaders GatewayFilter Factory会添加在返回响应中一系列安全作用的header,至于为什么,英文好的可以看一下这篇博客

    默认会添加这些头信息和默认内容:

    • X-Xss-Protection:1; mode=block

    • Strict-Transport-Security:max-age=631138519

    • X-Frame-Options:DENY

    • X-Content-Type-Options:nosniff

    • Referrer-Policy:no-referrer

    • Content-Security-Policy:default-src 'self' https:; font-src 'self' https: data:; img-src 'self' https: data:; object-src 'none'; script-src https:; style-src 'self' https: 'unsafe-inline'

    • X-Download-Options:noopen

    • X-Permitted-Cross-Domain-Policies:none

    如果你想修改这些头信息的默认内容,可以在配置文件中添加下面的配置:

    前缀:spring.cloud.gateway.filter.secure-headers

    上面的header对应的后缀:

    • xss-protection-header

    • strict-transport-security

    • frame-options

    • content-type-options

    • referrer-policy

    • content-security-policy

    • download-options

    • permitted-cross-domain-policies

    前后缀接起来即可,如:spring.cloud.gateway.filter.secure-headers.xss-protection-header

    17. SetPath GatewayFilter Factory

    SetPath GatewayFilter Factory采用路径template参数,通过请求路径的片段的模板化,来达到操作修改路径的母的,运行多个路径片段模板化。

    application.yml.

    spring:
      cloud:
        gateway:
          routes:
          - id: setpath_route
            uri: http://www.google.com
            predicates:
            - Path=/foo/{segment}
            filters:
            - SetPath=/{segment}
    

    对于上面的例子,如果路径是/foo/bar,则对于下游的请求路径会修改为/bar

    18. SetResponseHeader GatewayFilter Factory

    SetResponseHeader GatewayFilter Factory通过设置namevalue来替换响应对于的header。

    application.yml.

    spring:  
       cloud:  
       	gateway:      	
       		routes:      
       		- id: setresponseheader_route      
              uri: http://www.google.com      
              filters:      
              - SetResponseHeader=X-Response-Foo, Bar
    

    对于上面的例子,如果下游的返回带有头信息为X-Response-Foo:1234,则会gateway会替换为X-Response-Foo:Bar,在返回给客户端。

    19. SetStatus GatewayFilter Factory

    SetStatus GatewayFilter Factory通过配置有效的Spring HttpStatus枚举参数,可以是类似于404的这些数字,也可以是枚举的name字符串,来修改响应的返回码。

    application.yml.

    spring:
      cloud:
        gateway:
          routes:
          - id: setresponseheader_route
            uri: http://www.google.com
            filters:
            - SetResponseHeader=X-Response-Foo, Bar
    
    

    上面例子中,两种路由都会将响应的状态码设置为401。

    20. StripPrefix GatewayFilter Factory

    StripPrefix GatewayFilter Factory通过配置parts来表示截断路径前缀的数量。

    application.yml.

    spring:
      cloud:
        gateway:
          routes:
          - id: nameRoot
            uri: http://nameservice
            predicates:
            - Path=/name/**
            filters:
            - StripPrefix=2
    

    如上面例子中,如果请求的路径为/name/bar/foo,则路径会修改为/foo,即将路径的两个前缀去掉了。

    21. Retry GatewayFilter Factory

    Retry GatewayFilter Factory可以配置针对不同的响应做请求重试,可以配置如下参数:

    • retries: 重试次数

    • statuses: 需要重试的状态码,需要根据枚举 org.springframework.http.HttpStatus来配置

    • methods: 需要重试的请求方法,需要根据枚举org.springframework.http.HttpMethod来配置

    • series: HTTP状态码系列,详情见枚举org.springframework.http.HttpStatus.Series

    application.yml.

    spring:
      cloud:
        gateway:
          routes:
          - id: retry_test
            uri: http://localhost:8080/flakey
            predicates:
            - Host=*.retry.com
            filters:
            - name: Retry
              args:
                retries: 3
                statuses: BAD_GATEWAY
    

    上面例子,当下游服务返回502状态码时,gateway会重试3次。

    22. RequestSize GatewayFilter Factory

    RequestSize GatewayFilter Factory会限制客户端请求包的大小,通过参数RequestSize来配置最大上传大小,单位字节。

    application.yml.

    spring:
      cloud:
        gateway:
          routes:
          - id: request_size_route
          uri: http://localhost:8080/upload
          predicates:
          - Path=/upload
          filters:
          - name: RequestSize
            args:
              maxSize: 5000000
    

    如果请求大小超过5000kb限制,则会返回状态码413 Payload Too Large

    如果不设置这个filter,默认限制5M的请求大小。

    23. Modify Request Body GatewayFilter Factory

    官方说这个filter目前只是beta版本,API以后可能会修改。

    Modify Request Body GatewayFilter Factory可以修改请求体内容,这个只能通过java来配置。

    @Bean
    public RouteLocator routes(RouteLocatorBuilder builder) {
        return builder.routes()
            .route("rewrite_request_obj", r -> r.host("*.rewriterequestobj.org")
                .filters(f -> f.prefixPath("/httpbin")
                    .modifyRequestBody(String.class, Hello.class, MediaType.APPLICATION_JSON_VALUE,
                        (exchange, s) -> return Mono.just(new Hello(s.toUpperCase())))).uri(uri))
            .build();
    }
    
    static class Hello {
        String message;
    
        public Hello() { }
    
        public Hello(String message) {
            this.message = message;
        }
    
        public String getMessage() {
            return message;
        }
    
        public void setMessage(String message) {
            this.message = message;
        }
    }
    

    24. Modify Response Body GatewayFilter Factory

    官方说这个filter目前只是beta版本,API以后可能会修改。

    Modify Response Body GatewayFilter Factory用于修改响应返回的内容,同样只能通过java配置。

    @Bean
    public RouteLocator routes(RouteLocatorBuilder builder) {
        return builder.routes()
            .route("rewrite_response_upper", r -> r.host("*.rewriteresponseupper.org")
                .filters(f -> f.prefixPath("/httpbin")
            		.modifyResponseBody(String.class, String.class,
            		    (exchange, s) -> Mono.just(s.toUpperCase()))).uri(uri)
            .build();
    }
    

    7.集成Hystrix的断路器功能

    分布式系统环境下,服务间类似依赖非常常见,一个业务调用通常依赖多个基础服务。如下图,对于同步调用,当库存服务不可用时,商品服务请求线程被阻塞,当有大批量请求调用库存服务时,最终可能导致整个商品服务资源耗尽,无法继续对外提供服务。并且这种不可用可能沿请求调用链向上传递,这种现象被称为雪崩效应。

    img

    雪崩效应常见场景

    • 硬件故障:如服务器宕机,机房断电,光纤被挖断等。

    • 流量激增:如异常流量,重试加大流量等。

    • 缓存穿透:一般发生在应用重启,所有缓存失效时,以及短时间内大量缓存失效时。大量的缓存不命中,使请求直击后端服务,造成服务提供者超负荷运行,引起服务不可用。

    • 程序BUG:如程序逻辑导致内存泄漏,JVM长时间FullGC等。

    • 同步等待:服务间采用同步调用模式,同步等待造成的资源耗尽。

    雪崩效应应对策略

    针对造成雪崩效应的不同场景,可以使用不同的应对策略,没有一种通用所有场景的策略,参考如下:

    • 硬件故障:多机房容灾、异地多活等。

    • 流量激增:服务自动扩容、流量控制(限流、关闭重试)等。

    • 缓存穿透:缓存预加载、缓存异步加载等。

    • 程序BUG:修改程序bug、及时释放资源等。

    • 同步等待:资源隔离、MQ解耦、不可用服务调用快速失败等。资源隔离通常指不同服务调用采用不同的线程池;不可用服务调用快速失败一般通过熔断器模式结合超时机制实现。

    综上所述,如果一个应用不能对来自依赖的故障进行隔离,那该应用本身就处在被拖垮的风险中。 因此,为了构建稳定、可靠的分布式系统,我们的服务应当具有自我保护能力,当依赖服务不可用时,当前服务启动自我保护功能,从而避免发生雪崩效应。本文将重点介绍使用Hystrix解决同步等待的雪崩问题。

    断路器工作原理

    服务端的服务降级逻辑会因为hystrix命令调用依赖服务超时而触发,也就是说调用服务超时会进入断路回调逻辑处理。但是即使这样,受限于Hystrix超时时间的问题,调用依然会有可能产生堆积。

    这个时候断路器就会发挥作用。这里涉及到断路器的三个重要参数:

    快照时间窗

    断路器确定是否打开需要统计一些请求和错误数据,而统计的时间范围就是快照时间窗,默认为最近的10秒。

    请求总数下限

    在快照时间窗内,必须满足请求总数下限才有资格熔断。默认为20,意味着在10秒内,如果该hystrix命令的调用次数不足20,即使所有的请求都超时或者其他原因失败,断路器都不会打开。

    错误百分比下限

    当请求总数在快照时间窗口内超过了下限,比如发生了30次调用,如果在这30次调用中有16次发生了超时异常,也就是超过了50%错误百分比,在默认设定50%下限情况下,这时候就会将断路器打开。

    因此,断路器打开的条件是:在时间快照窗口期(默认为10s)内,至少发生20次服务调用,并且服务调用错误率超过50%。

    不满足条件时断路器并不会打开,服务调用错误只会触发服务降级,也就是调用fallback函数,每个请求时间延迟就是近似hystrix的超时时间。如果将超时时间设置为5秒,那么每个请求都要延迟5每秒才会返回。当断路器在10秒内发现请求总数超过20并且错误率超过50%,这时候断路器会打开。之后再有请求调用的时候,将不会调用主逻辑,而是直接调用降级逻辑,这个时候就不会等待5秒之后才会返回fallback。通过断路器实现自动发现错误并将降级逻辑切换为主逻辑,减少响应延迟的效果。

    在断路器打开之后,处理逻辑并没有结束,此时降级逻辑已经被切换为主逻辑了,那么原来的主逻辑要如何恢复呢?实际上hystrix也实现了这一点:当断路器打开,对主逻辑进行熔断之后,hystrix会启动一个休眠时间窗,在这个时间窗内,降级逻辑是临时的主逻辑,当休眠时间窗到期,断路器将进入半开状态,释放一次请求到原来的主逻辑,如果此次请求正常返回,那么断路器将进行闭合,主逻辑恢复,如果这次请求依然有问题,断路器继续进入打开状态,休眠时间窗重新计时。

    换句话说,断路器每隔一段时间进行一次重试,看看原来的主逻辑是否可用,可用就关闭,不可用就继续打开。

    通过上面的机制,hystrix的断路器实现了对依赖资源故障的处理,对降级策略的自动切换以及对主逻辑的自动恢复。这使得我们的微服务在依赖外部服务或资源的时候得到了非常好的保护,同时对于一些具备降级逻辑的业务需求可以实现自动化的切换和恢复,相比于设置开关由监控和运维来进行切换的传统实现方式显得更为智能和高效。

    集成spring cloud gateway

    maven依赖

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

    yml配置文件配置

    spring:
        cloud:
            gateway:
              discovery:
                locator:
                  enabled: true
              default-filters:
                - StripPrefix=1
                - name: Hystrix
                  args:
                      name: fallback
                      fallbackUri: forward:/fallback
              routes:
                #基础架构服务
                  - id: orgnization-wx
                    uri: lb:http://orgnization-wx
                    predicates:
                      - Path=/structure/**
    

    fallback 实例

    import org.springframework.http.HttpStatus;
    import org.springframework.http.ResponseEntity;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    /**
     * @author 荡漾
     * @title: PermissionFiler
     * @projectName cmp
     * @description: TODO
     * @date 2019/10/25  10:24
     */
    @RestController
    @RequestMapping("/fallback")
    public class FallbackController {
    
        @RequestMapping("")
        public ResponseEntity fallback(){
            return ResponseEntity.status(HttpStatus.SERVICE_UNAVAILABLE).body("服务暂不可用!!!!");
        }
    }
    

    8.请求限流

     

    在高并发的系统中,往往需要在系统中做限流,一方面是为了防止大量的请求使服务器过载,导致服务不可用,另一方面是为了防止网络攻击。

    一般开发高并发系统常见的限流有:限制总并发数(比如数据库连接池、线程池)、限制瞬时并发数(如 nginx 的 limit_conn 模块,用来限制瞬时并发连接数)、限制时间窗口内的平均速率(如 Guava 的 RateLimiter、nginx 的 limit_req 模块,限制每秒的平均速率);其他还有如限制远程接口调用速率、限制 MQ 的消费速率。另外还可以根据网络连接数、网络流量、CPU 或内存负载等来限流。

    限流算法

    计数器

    简单的做法是维护一个单位时间内的 计数器,每次请求计数器加1,当单位时间内计数器累加到大于设定的阈值,则之后的请求都被拒绝,直到单位时间已经过去,再将 计数器 重置为零。此方式有个弊端:如果在单位时间1s内允许100个请求,在10ms已经通过了100个请求,那后面的990ms,只能眼巴巴的把请求拒绝,我们把这种现象称为“突刺现象”。

    常用的更平滑的限流算法有两种:漏桶算法令牌桶算法。下面介绍下二者。

    漏桶算法

    漏桶算法思路很简单,水(请求)先进入到漏桶里,漏桶以一定的速度出水(接口有响应速率),当水流入速度过大会直接溢出(访问频率超过接口响应速率),然后就拒绝请求,可以看出漏桶算法能强行限制数据的传输速率。

     

    img

    可见这里有两个变量,一个是桶的大小,支持流量突发增多时可以存多少的水(burst),另一个是水桶漏洞的大小(rate)。因为漏桶的漏出速率是固定的参数,所以,即使网络中不存在资源冲突(没有发生拥塞),漏桶算法也不能使流突发(burst)到端口速率。因此,漏桶算法对于存在突发特性的流量来说缺乏效率。

    令牌桶算法

    令牌桶算法 和漏桶算法 效果一样但方向相反的算法,更加容易理解。随着时间流逝,系统会按恒定 1/QPS 时间间隔(如果 QPS=100,则间隔是 10ms)往桶里加入 Token(想象和漏洞漏水相反,有个水龙头在不断的加水),如果桶已经满了就不再加了。新请求来临时,会各自拿走一个 Token,如果没有 Token 可拿了就阻塞或者拒绝服务。

     

    img

    令牌桶的另外一个好处是可以方便的改变速度。一旦需要提高速率,则按需提高放入桶中的令牌的速率。一般会定时(比如 100 毫秒)往桶中增加一定数量的令牌,有些变种算法则实时的计算应该增加的令牌的数量。

    限流实现

    在 Spring Cloud Gateway 上实现限流是个不错的选择,只需要编写一个过滤器就可以了。有了前边过滤器的基础,写起来很轻松。

    Spring Cloud Gateway 已经内置了一个RequestRateLimiterGatewayFilterFactory,我们可以直接使用。

    目前RequestRateLimiterGatewayFilterFactory的实现依赖于 Redis,所以我们还要引入spring-boot-starter-data-redis-reactive。

    pom.xml

    <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>
    

    application.yml

    server:
      port: 8080
    spring:
      cloud:
        gateway:
          routes:
            - id: limit_route
              uri: http://httpbin.org:80/get
              predicates:
              - After=2019-02-26T00:00:00+08:00[Asia/Shanghai]
              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
        database: 0
    

    在上面的配置文件,配置了 redis的信息,并配置了RequestRateLimiter的限流过滤器,该过滤器需要配置三个参数:

    • burstCapacity:令牌桶总容量。

    • replenishRate:令牌桶每秒填充平均速率。

    • key-resolver:用于限流的键的解析器的 Bean 对象的名字。它使用 SpEL 表达式根据#{@beanName}从 Spring 容器中获取 Bean 对象。

    IP限流

    获取请求用户ip作为限流key。

    @Bean
    public KeyResolver hostAddrKeyResolver() {
        return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getHostName());
    }
    

    用户限流

    获取请求用户id作为限流key。

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

    接口限流

    获取请求地址的uri作为限流key。

    @Bean
    KeyResolver apiKeyResolver() {
        return exchange -> Mono.just(exchange.getRequest().getPath().value());
    }
    

     

     

     

    展开全文
  • GateWay三大核心概念:断言(Predicate),路由(Route),过滤(Filter) 路由,断言配置 server: port: 9527 spring: application: name: cloud-gateway cloud: gateway: discovery: locator: enabled: true ...
  • 服务网关(Gateway) 搭建网关服务 本案例中使用spring boot的版本为2.0.3.RELEASE,spring cloud版本为Finchley.RELEASE。在中涉及到了三个工程, 分别为注册中心eureka-server、服务提供者service-hi、 服务网关...
  • Gateway--概述

    2020-03-18 20:16:59
    Gateway Cloud全家桶中有个很重要的组件就是网关,在1.x版本中都是采用Zuul网关。但是在2.x版本中,zuul的升级一直跳票,SpringCloud最后自己研发了一个网关代替Zuul,就是SpringCloud Gatewaygateway就是原zuul1....
  • Gateway 为 0.0.0.0

    千次阅读 2019-10-28 09:28:49
    后三条是自动生成的,因为是直连的网段,不需要...这两条记录中的gateway并没有意义,Flags那一列中有G时才会使用Gateway。这两条路由并没有这样的标志,由于它们是本地的,匹配这些条目的数据包会直接通过Iface列中...
  • 微服务gateway介绍

    万次阅读 2018-04-15 17:35:25
    API 网关(API Gateway)主要负责服务请求路由、组合及协议转换。下面是大家的总结:一、最佳回答网关的技术选型SpringCloud-Zuul :社区活跃,基于 SrpingCloud 完整生态, 是构建微服务体系前置网关服务的最佳选型....
  • 网关(Gateway)详解

    万次阅读 多人点赞 2018-03-01 18:00:54
     网关(Gateway)又称网间连接器、协议转换器。网关在网络层以上实现网络互连,是最复杂的网络互连设备,仅用于两个高层协议不同的网络互连。网关既可以用于广域网互连,也可以用于局域网互连。 网关是一种充当转换...
  • gateway配置路由主要有两种方式,一种是用yml配置文件,一种是写代码里,这两种方式都是不支持动态配置的。如: 下面就来看看gateway是如何加载这些配置信息的。 1 路由初始化 无论是yml还是代码,这些配置最终...
  • Spring Cloud Gateway初体验

    万次阅读 多人点赞 2018-11-06 18:55:37
    https://www.fangzhipeng.com/springcloud/2018/11/06/sc-f-gateway1/ 本文出自方志朋的博客 这篇文章讲述了如何简单地使用Spring Cloud Gateway,来源于Spring Cloud官方案例,地址...
  • Gateway的使用案例

    万次阅读 2020-07-01 03:18:22
    所有微服务的调用需要先经过网管微服务,...-- spring-cloud-starter-gateway --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gate
  • spring cloud gateway之filter篇

    万次阅读 多人点赞 2018-12-17 21:45:21
    在上一篇文章详细的介绍了Gateway的Predict,Predict决定了请求由哪一个路由处理,在路由处理之前,需要经过“pre”类型的过滤器处理,处理返回响应之后,可以由“post”类型的过滤器处理。 filter的作用和生命周期 ...
  • SpringCloudGateway+Nacos 集成应用 1. 应用集成(配置中心+应用中心) 参见(SpringCloud+Nacos 配置中心与注册中心应用) 2. 启动服务 3. API文档访问 4. 动态路由 只需要修改对应的配置文件即可,nacos会发起刷新 ...
  • Spring Cloud Gateway 之Predict篇

    万次阅读 多人点赞 2018-12-09 12:53:44
    Spring Cloud gateway工作流程 在之前的文章的Spring Cloud Gateway初体验中,大家已经对Spring Cloud Gateway的功能有一个初步的认识,网关作为一个系统的流量的入口,有着举足轻重的作用,通常的作用如下: 协议...
  • 502 Bad Gateway服务器作为网关或者代理时,为了完成请求访问下一个服务器,但该服务器返回了非法的应答。 解决办法是:再刷新一下网页或清理一下电脑的缓冲文件在打开你想打开的网页就好了. 一般情况下,这种办法是...
  • 微服务网关实战——Spring Cloud Gateway

    万次阅读 多人点赞 2019-05-24 16:02:31
    作为Netflix Zuul的替代者,Spring Cloud Gateway是一款非常实用的微服务网关,在Spring Cloud微服务架构体系中发挥非常大的作用。本文对Spring Cloud Gateway常见使用场景进行了梳理,希望对微服务开发人员提供一些...
  • 微服务网关Zuul和Gateway的区别

    万次阅读 多人点赞 2019-08-15 21:26:49
    版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。 ... 微服务系列(一)聊聊服务网关 前几年随着分布式架构的演变,微服务开始兴起,自然也产生了一系列支持微服务的...
  • Gateway网关---Filter过滤器

    万次阅读 2020-07-01 13:08:49
    官网关于过滤器的文档地址https://cloud.spring.io/spring-cloud-gateway/2.2.x/reference/html/#gatewayfilter-factories ... gateway: routes: - id: add_request_header_route uri: https://example.org

空空如也

1 2 3 4 5 ... 20
收藏数 231,800
精华内容 92,720
关键字:

gateway