1、zuul路由网关

1、概述介绍

1、官网资料

  • https://github.com/Netflix/zuul/wiki/Getting-Started
  • https://cloud.spring.io/spring-cloud-static/spring-cloud-netflix/2.2.1.RELEASE/reference/html/#router-and-filter-zuul

    2、是什么

    Zuul是一种提供动态路由、监视、弹性、安全性等功能的边缘服务。
    Zuul是Netflix出品的一个基于JVM路由和服务端的负载均衡器。
    image.png
    API网关为微服务架构中的服务提供了统一的访问入口,客户端通过API网关访问相关服务。API网关的定义类似于设计模式中的门面模式,它相当于整个微服务架构中的门面,所有客户端的访问都通过它来进行路由及过滤。它实现了请求路由、负载均衡、校验过滤、服务容错、服务聚合等功能。
    image.png
    image.png

  • Zuul包含了如下最主要的功能:

    • 代理+路由+过滤三大功能

      3、作用

  • 路由

  • 过滤
  • 负载均衡
    • 网关为入口,由网关与微服务进行交互,所以网关必须要实现负载均衡的功能;
    • 网关会获取微服务注册中心里面的服务连接地址,再配合一些算法选择其中一个服务地址,进行处理业务。
    • 这个属于客户端侧的负载均衡,由调用方去实现负载均衡逻辑。
    • image.png
  • 灰度发布

    • 又称金丝雀发布
    • 起源是,矿井工人发现,金丝雀对瓦斯气体很敏感,矿工会在下井之前,先放一只金丝雀到井中,如果金丝雀不叫了,就代表瓦斯浓度高。
    • image.png
    • 在灰度发布开始后,先启动一个新版本应用,但是并不直接将流量切过来,而是测试人员对新版本进行线上测试,启动的这个新版本应用,就是我们的金丝雀。如果没有问题,那么可以将少量的用户流量导入到新版本上,然后再对新版本做运行状态观察,收集各种运行时数据,如果此时对新旧版本做各种数据对比,就是所谓的A/B测试。新版本没什么问题,那么逐步扩大范围、流量,把所有用户都迁移到新版本上面来。

      2、路由基本配置

      1、功能

      路由功能负责将外部请求转发到具体的服务实例上去,是实现统一访问入口的基础

      2、新建cloud-zuul-gateway9527

      1、修改pom

  • 注意这个网关是不需要引入spring-boot-start-web的包的 ```xml <?xml version=”1.0” encoding=”UTF-8”?> <project xmlns=”http://maven.apache.org/POM/4.0.0

    1. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    2. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

      <artifactId>cloud2020</artifactId>
      <groupId>com.daijunyi</groupId>
      <version>1.0-SNAPSHOT</version>
    

    4.0.0 cloud-zuul-gateway9527 org.springframework.cloud spring-cloud-starter-netflix-eureka-client org.springframework.cloud spring-cloud-starter-netflix-zuul org.springframework.boot spring-boot-starter-actuator org.springframework.boot spring-boot-devtools runtime true org.projectlombok lombok true org.springframework.boot spring-boot-starter-test test

<a name="wTsHC"></a>
#### 2、添加yaml
```yaml
server:
  port: 9527

spring:
  application:
    name: cloud-zuul-gateway

eureka:
  client:
    service-url:
      defaultZone: http://www.eureka7001.com:7001/eureka,http://www.eureka7002.com:7002/eureka
  instance:
    instance-id: gateway-9527.com
    prefer-ip-address: true

3、hosts修改

mac下
sudo vim /etc/hosts

127.0.0.1       myzuul.com

4、主启动类

  • 添加@EnableZuulProxy ```java package com.daijunyi;

import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.zuul.EnableZuulProxy;

@SpringBootApplication @EnableZuulProxy public class ZuulGateway9527 { public static void main(String[] args) { SpringApplication.run(ZuulGateway9527.class,args); } }

<a name="KTMwO"></a>
#### 5、测试
启动Eureka 2台集群,并且启动2个服务8001和8002<br />![image.png](https://cdn.nlark.com/yuque/0/2021/png/12971636/1630572468551-83cb0745-59e0-4c2a-84ef-989ee2eb562e.png#clientId=ubf9da582-a53b-4&from=paste&height=112&id=u8b872ddd&margin=%5Bobject%20Object%5D&name=image.png&originHeight=224&originWidth=832&originalType=binary&ratio=1&size=39179&status=done&style=none&taskId=u2088698b-5895-4f84-a0e3-b67ef1f5a9d&width=416)

- 启动cloud-provider-payment8001和cloud-provider-payment8002两个服务提供类

![image.png](https://cdn.nlark.com/yuque/0/2021/png/12971636/1630572515821-10354af6-cff2-4970-a803-1294a7b1c58e.png#clientId=ubf9da582-a53b-4&from=paste&height=514&id=uc5c3e63e&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1028&originWidth=2824&originalType=binary&ratio=1&size=209827&status=done&style=none&taskId=u886db1b2-ce65-499f-98f9-621b3925db6&width=1412)

- 启动路由cloud-zuul-gateway9527
   - ![image.png](https://cdn.nlark.com/yuque/0/2021/png/12971636/1630572599816-741fabfd-fc50-40a4-adbf-94266a00eca1.png#clientId=ubf9da582-a53b-4&from=paste&height=557&id=u1c2a546b&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1114&originWidth=2844&originalType=binary&ratio=1&size=229526&status=done&style=none&taskId=ue53f621a-579a-4aff-88c4-2406c682afb&width=1422)
- 访问
   - 不使用路由访问8001服务
      - [http://localhost:8001/payment/get/1](http://localhost:8001/payment/get/1)
      - ![image.png](https://cdn.nlark.com/yuque/0/2021/png/12971636/1630572661113-b08d93db-01a1-4a2d-b50b-b345a4b6d564.png#clientId=ubf9da582-a53b-4&from=paste&height=96&id=u873af32a&margin=%5Bobject%20Object%5D&name=image.png&originHeight=192&originWidth=1432&originalType=binary&ratio=1&size=30607&status=done&style=none&taskId=u8f7c1848-606f-44c9-b742-57598f78e36&width=716)
   - 使用路由访问
      - zuul映射配置+注册中心注册后对外暴露的服务名称+rest调用地址
      - [http://myzuul.com:9527/cloud-payment-service/payment/get/1](http://myzuul.com:9527/cloud-payment-service/payment/get/1)
      - ![image.png](https://cdn.nlark.com/yuque/0/2021/png/12971636/1630573823957-7f5230bf-dc39-48ec-9d35-894ab7ccd318.png#clientId=ubf9da582-a53b-4&from=paste&height=72&id=u19b9f9a9&margin=%5Bobject%20Object%5D&name=image.png&originHeight=144&originWidth=1342&originalType=binary&ratio=1&size=32383&status=done&style=none&taskId=u7abe37fd-d92d-4414-a358-7eb9108f837&width=671)
<a name="veSRW"></a>
## 3、**路由访问映射规则**
<a name="VJCI0"></a>
### 1、创建工程microservicecloud-zuul-gateway-9527

- 并且工程的主名称修改为
```java
@SpringBootApplication
@EnableZuulProxy
public class MicroserviceCloudZuulGateway9527 {
    public static void main(String[] args) {
        SpringApplication.run(MicroserviceCloudZuulGateway9527.class,args);
    }
}
  • 修改yaml ```yaml server: port: 9527

spring: application: name: microservicecloud-zuul-gateway

eureka: client: service-url: defaultZone: http://www.eureka7001.com:7001/eureka,http://www.eureka7002.com:7002/eureka instance: instance-id: gateway-9527.com prefer-ip-address: true

![image.png](https://cdn.nlark.com/yuque/0/2021/png/12971636/1630575199883-67c2ba20-02ab-41c5-a563-8d3084c53815.png#clientId=ubf9da582-a53b-4&from=paste&height=386&id=u98581f07&margin=%5Bobject%20Object%5D&name=image.png&originHeight=772&originWidth=2644&originalType=binary&ratio=1&size=163036&status=done&style=none&taskId=u1abf6c72-4065-4b3e-9456-7fb1492dea2&width=1322)
<a name="p9dyQ"></a>
### 2、代理名称

- 修改yaml文件
```yaml
zuul:
  routes: # 路由映射配置
    mypayment.serviceId: cloud-payment-service
    mypayment.path: /weixin/**
  • 会发现问题以下两个路径都可以访问,但是我们不想要访问这个默认的路径
  • 访问原路径
  • 访问新的路径

  • 如果不想使用默认的路由规则,可以添加以下配置来忽略默认路由配置

  • 修改yaml

    • 增加ignored-services配置
    • 多个一起配置的话可以使用
      • ignored-services: “*”
        zuul:
        ignored-services: cloud-payment-service
        routes: # 路由映射配置
        mypayment.serviceId: cloud-payment-service
        mypayment.path: /weixin/**
        
  • 访问原地址

  • 访问新地址

  • 修改yaml

    • prefix 添加 前缀api
      zuul:
      ignored-services: cloud-payment-service
      routes: # 路由映射配置
      mypayment.serviceId: cloud-payment-service
      mypayment.path: /weixin/**
      prefix: /api
      
  • 访问新地址

  • spring-boot-starter-actuator

    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    

    2、修改yaml

    # 开启查看路由的端点
    management:
    endpoints:
      web:
        exposure:
          include: 'routes'
    

    3、访问路径

  • http://localhost:9527/actuator/routes

  • image.png

    5、过滤器

    1、简介

    过滤功能负责对请求过程进行额外的处理,是请求校验过滤及服务聚合的基础。

    2、过滤器的生命周期

    image.png

    3、ZuulFilter(Java抽象类,实现该类进行拦截)

    1、过滤类型

  • pre:在请求被路由到目标服务前执行,比如权限校验、打印日志等功能;

  • routing:在请求被路由到目标服务时执行
  • post:在请求被路由到目标服务后执行,比如给目标服务的响应添加头信息,收集统计数据等功能;
  • error:请求在其他阶段发生错误时执行。

    2、过滤顺序

  • 数字小的先执行

    3、过滤是否开启

  • shouldFilter方法为true走

    4、案例Case

  • 前置过滤器,用于在请求路由到目标服务前打印请求日志

  • 创建PreLogFilter ```java package com.daijunyi.filter.zuul;

import com.netflix.zuul.ZuulFilter; import com.netflix.zuul.context.RequestContext; import com.netflix.zuul.exception.ZuulException; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest; import java.util.Date;

@Component @Slf4j public class PreLogFilter extends ZuulFilter { @Override public String filterType() { return “pre”; }

@Override
public int filterOrder() {
    return 1;
}

@Override
public boolean shouldFilter() {
    return true;
}

@Override
public Object run() throws ZuulException {
    RequestContext requestContext = RequestContext.getCurrentContext();
    HttpServletRequest request = requestContext.getRequest();
    String host = request.getRemoteHost();
    String method = request.getMethod();
    String uri = request.getRequestURI();
    log.info("=====> Remote host:{},method:{},uri:{}", host, method, uri);
    System.out.println("********"+new Date().getTime());
    return null;
}

}


- 访问
   - [http://myzuul.com:9527/api/weixin/payment/get/1](http://myzuul.com:9527/api/weixin/payment/get/1)
   - 控制台打印日志
```shell
2021-09-02 17:56:51.809  INFO 39752 --- [nio-9527-exec-2] com.daijunyi.filter.zuul.PreLogFilter    : =====> Remote host:127.0.0.1,method:GET,uri:/api/weixin/payment/get/1
********1630576611810

1、还可以在yaml中配置是否对这个类进行开启

  • true为关闭拦截
  • false为开启拦截
    zuul:
    #对该顾虑器进行拦截开关
    PreLogFilter:
      pre:
        disable: true
    

    2、Gateway

1、概述简介

1、官网

1、上一代zuul 1.X

https://github.com/Netflix/zuul/wiki

2、当前gateway

https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.1.RELEASE/reference/html/

2、是什么

1、概述

  • Gateway是在Spring生态系统之上构建的API网关服务, 基于Spring 5, Spring Boot 2和Project Reactor等技术。
  • Gateway旨在提供一种简单而有效的方式来对API进行路由,以及提供一 些强大的过滤器功能,例如:熔断、限流、重试等
  • SpringCloud Gateway是Spring Cloud的一个全新项目,纡Spring 5.0+ Spring Boot 2.0和Project Reactor等技术开发的网关,它旨在为微服务架构提供一种简单有效的统- 的API路由管理方式。
  • SpringCloud Gateway作为Spring Cloud生态系统中的网关,目标是替代Zuul,在Spring Cloud 2.0以上版本中,没有对新版本的Zuul 2.0以上最新高性能版本进行集成,仍然还是使用的Zuul 1.x非Reactor模式的老版本。而为了提升网关的性能, SpringCloud Gateway是基于WebFlux框架实现的,而WebFlux框架底层则使用了高性能的Reactor模式通信框架Netty。
  • Spring Cloud Gateway的目标提供统一的路由方式且基于Filter 链的方式提供了网关基本的功能,例如:安全,监控/指标,和限流。

    2、总结

    Spring Cloud Gateway 使用的Webflux中的reactor-netty响应式编程组件,底层使用了Netty通讯框架

  • 源码架构

  • image.png

    3、作用

  • 反向代理

  • 鉴权
  • 流量控制
  • 熔断
  • 日志监控
  • 4、微服务架构中网关在哪里

    image.png

    5、有了Zuul了怎么又出来了gateway

    1、我们为什么选择Gatway?

  • 1.neflix不太靠谱,zuul2.0一直跳票,迟迟不发布

    • 一方面因为Zuul1.0已经进入 了维护阶段,而且Gateway是SpringCloud团队研发的, 是亲儿子产品,值得信赖。“而且很多功能ZuuI都没有用起来也非常的简单便捷。Gateway是基于异步非阻塞模型上进行开发的,性能方面不需要担心。虽然Netflix早就发布 了最新的Zuul 2.x,但Spring Cloud貌似没有整合计划。而且Netflix相关组件 都宣布进入维护期;不知前景如何?多方面综合考虑Gateway是很理想的网关选择。
  • 2.SpringCloud Gateway具有如下特性
    • 基于Spring Framework 5, Project Relactor和Spring Boot 2.0进行构建;
    • 动态路由:能够匹配任何请求属性;
    • 可以对路由指定Predicate (断言)和Filter (过滤器) ;
    • 集成Hystrix的断路器功能;
    • 集成Spring Cloud服务发现功能;
    • 易于编写的Predicate (断言)和Filter (过滤器) ;
    • 请求限流功能;
    • 支持路径重写。
  • 3.SpringCloud Gateway与Zuul的区别

    • 在SpringCloud Finchley正式版之前,Spring Cloud推荐的网关是Netflix提供的Zuul:
    • 1、Zuul1.x, 是一个基于阻塞I/ O的API Gateway
    • 2、Zuul 1.x基于Servlet 2.5使用阻塞架构它不支持任何长连接(如WebSocket) Zuul的设计模式和Nginx较像,每次|/ O操作都是从工作线程中选择一个执行, 请求线程被阻塞到工作线程完成,但是差别是Nginx用C++实现,Zuul 用Java实现,而JVM本身会有第一次加载较慢的情况,使得Zuul的性能相对较差。
    • 3、Zuul 2.x理念更先进,想基于Netty非阻塞和支持长连接,但SpringCloud目前还没有整合。 Zuul 2.x的性能较Zuul 1.x 有较大提升。在性能方面,根据官方提供的基准测试,Spring Cloud Gateway的RPS (每秒请求数)是Zuul的1. 6倍。
    • 4、Spring Cloud Gateway建立在Spring Framework 5、Project Reactor和Spring Boot2之上,使用非阻塞APl。
    • 5、Spring Cloud Gateway还持WebSocket,并且与Spring紧密集成拥有更好的开发体验

      2、Zuul1.x模型

  • Springcloud中所集成的Zuul版本,采用的是Tomcat容器,使用的是传统的Servlet I0处理模型。

  • Servlet的生命周期?servlet由servlet container进行生命周期管理。
  • container启动时构造servlet对象并调用servlet init)进行初始化;
  • container运行时接受请求,并为每个请求分配一个线程 (一般从线程池中获取空闲线程)然后调用service()。
  • container关闭时调用servlet destory()销毁servlet;

image.png

  • 上述模式的缺点:

    • servlet是一个简单的网络IO模型, 当请求进入servlet container时,servlet container就会为其绑定一个线程,在并发不高的场景下这种模型是适用的。但是一旦高并发(比如抽风用jemeter压),线程数量就会上涨,而线程资源代价是昂贵的( 上线文切换,内存消耗大)严重影响请求的处理时间。
    • 在一些简单业务场景下,不希望为每个request分配一个线程, 只需要1个或几个线程就能应对极大并发的请求,这种业务场景下servlet模型没有优势
    • 所以Zuul 1.X是基于servlet之上的一个阻塞式处理模型,即spring实现 了处理所有request请求的一个servlet (DispatcherServlet) 并由该servlet阻塞式处理处理。所以Springcloud Zuul无法摆脱servlet模型的弊端

      3、GateWay模型

  • 传统的Web框架,比如说: struts2, springmvc等都是 基于Servlet API与Servlet容器基础之上运行的。

  • 但是在Servlet3.1之后有了异步非阻塞的支持。而WebFlux是一个 典型非阻塞异步的框架,它的核心是基于Reactor的相关AP|实现的。相对于传统的web框架来说,它可以运行在诸如Netty, Undertow及 支持Servlet3.1的容器上。非阻塞式+函数式编程(Spring5必须让你使用java8)
  • Spring WebFlux是Spring 5.0引入的新的响应式框架,区别于Spring MVC,它不需要依赖Servlet API,它是完全异步非阻塞的,并且基于Reactor来实现响应式流规范。

    2、三大核心概念

    1、Route(路由)

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

    2、Predicate(断言)

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

    3、Filter(过滤)

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

    4、总结

    image.png

  • web请求,通过一些匹配条件, 定位到真正的服务节点。并在这个转发过程的前后,进行一些精细化控制。

  • predicate就是我们的匹配条件;而filter, 就可以理解为一个无所不能的拦哉器。有了这两个元素.再加上目标uri,就可以实现-个具体的路由了

    3、Gateway工作流程

    1、官网

    image.png

  • 客户端向Spring Cloud Gateway发出请求。然后在Gateway Handler Mapping中找到与请求相匹配的路由,将其发送到Gateway Web Handler。

  • Handler再通过指定的过滤器链来将请求发送到我们实际的服务执行业务逻辑,然后返回。过滤器之间用虚线分开是因为过滤器可能会在发送代理请求之前( “pre” )或之后( “post” )执行业务逻辑。
  • Filter在”pre” 类型的过滤器可以做参数校验、权限校验、流量监控、日志输出、协议转换等,在”post”类型的过滤器中可以做响应内容、响应头的修改,日志的输出,流量监控等有着非常重要的作用。

    2、核心逻辑

    路由转发+执行过滤器链

    4、入门配置

    1、cloud-gateway-gateway9527

    1、配置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">
      <parent>
          <artifactId>cloud2020</artifactId>
          <groupId>com.daijunyi</groupId>
          <version>1.0-SNAPSHOT</version>
      </parent>
      <modelVersion>4.0.0</modelVersion>
    
      <artifactId>cloud-gateway-gateway9527</artifactId>
    
      <dependencies>
          <!--新增gateway-->
          <dependency>
              <groupId>org.springframework.cloud</groupId>
              <artifactId>spring-cloud-starter-gateway</artifactId>
          </dependency>
          <dependency>
              <groupId>com.daijunyi</groupId>
              <artifactId>cloud-api-commons</artifactId>
              <version>1.0-SNAPSHOT</version>
          </dependency>
    
          <dependency>
              <groupId>org.springframework.cloud</groupId>
              <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
          </dependency>
          <dependency>
              <groupId>org.springframework.cloud</groupId>
              <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
          </dependency>
    
          <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-devtools</artifactId>
              <scope>runtime</scope>
              <optional>true</optional>
          </dependency>
    
          <dependency>
              <groupId>org.projectlombok</groupId>
              <artifactId>lombok</artifactId>
              <optional>true</optional>
          </dependency>
          <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter-test</artifactId>
              <scope>test</scope>
          </dependency>
    
      </dependencies>
    </project>
    

    2、修改yaml

    server:
    port: 9527
    spring:
    application:
      name: cloud-gateway
    cloud:
      gateway:
        routes:
          - id: payment_routh #路由的ID,没有固定规则但要求唯一,建议配合服务名
            uri: http://localhost:8001   #匹配后提供服务的路由地址
            predicates:
              - Path=/payment/get/**   #断言,路径相匹配的进行路由
    
          - id: payment_routh2
            uri: http://localhost:8001
            predicates:
              - Path=/lb/**   #断言,路径相匹配的进行路由
    eureka:
    instance:
      hostname: cloud-gateway-service
    client:
      service-url:
        register-with-eureka: true
        fetch-registry: true
        defaultZone: http://www.eureka7001.com:7001/eureka,http://www.eureka7002.com:7002/eureka
    

    3、主启动类

    ```java package com.daijunyi;

import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

@SpringBootApplication @EnableEurekaClient public class CloudGateway9527 { public static void main(String[] args) { SpringApplication.run(CloudGateway9527.class, args); } }

<a name="B3kzl"></a>
#### 4、测试

- 访问[http://localhost:9527/payment/get/1](http://localhost:9527/payment/get/1)
   - ![image.png](https://cdn.nlark.com/yuque/0/2021/png/12971636/1630632816685-884fd435-fbf4-41dd-aecd-900caa334dfa.png#clientId=ub1d6741a-1ed3-4&from=paste&height=72&id=u4044ad07&margin=%5Bobject%20Object%5D&name=image.png&originHeight=144&originWidth=1292&originalType=binary&ratio=1&size=27063&status=done&style=none&taskId=ub35ebdea-22f7-49bb-8d66-bb2372bf5ab&width=646)
- 访问[http://localhost:9527/lb/port](http://localhost:9527/lb/port)
   - ![image.png](https://cdn.nlark.com/yuque/0/2021/png/12971636/1630632923430-0ea41f71-5cc0-4249-9adb-d4af242b812c.png#clientId=ub1d6741a-1ed3-4&from=paste&height=86&id=u9d672962&margin=%5Bobject%20Object%5D&name=image.png&originHeight=172&originWidth=692&originalType=binary&ratio=1&size=12582&status=done&style=none&taskId=u7283425e-b291-482b-a5e7-1bacd7d6e25&width=346)
<a name="e9Sxr"></a>
### 2、Gateway网关路由有两种配置方式
<a name="hUYye"></a>
#### 1、在配置文件yml中配置

- 见前面步骤
<a name="msmvd"></a>
#### 2、代码中注入RouteLocator的Bean

- 路由转发百度国内新闻网址
   - [http://news.baidu.com/guoji](http://news.baidu.com/guoji)
   - [http://news.baidu.com/guonei](http://news.baidu.com/guonei)
   - [http://news.baidu.com/mil](http://news.baidu.com/mil)
- cloud-gateway-gateway9527
   - 添加GatewayConfig
```java
package com.daijunyi.config;

import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class GatewayConfig {

    @Bean
    public RouteLocator customRouteLocator(RouteLocatorBuilder routeLocatorBuilder) {
        RouteLocatorBuilder.Builder routes = routeLocatorBuilder.routes();
        routes.route("path_rote_guoji", r -> r.path("/guoji").uri("http://news.baidu.com/guoji")).build();
        routes.route("path_rote_guonei", r -> r.path("/guonei").uri("http://news.baidu.com/guonei")).build();
        routes.route("path_rote_mil", r -> r.path("/mil").uri("http://news.baidu.com/mil")).build();
        return routes.build();
    }

}
  • 测试访问

  • 默认情况下Gateway会根据注册中心的服务列表,以注册中心上微服务名为路径创建动态路由进行转发,从而实现动态路由的功能

    1、修改yaml

  • cloud.discovery.locator.enabled开启从注册中心服务发现

  • 地址配置为服务中心的地址uri: lb://cloud-payment-service
  • 需要注意的是uri的协议为lb,表示启用Gateway的负载均衡功能。
  • lb://serviceName是spring cloud gateway在微服务中自动为我们创建的负载均衡uri

    server:
    port: 9527
    spring:
    application:
      name: cloud-gateway
    cloud:
      #开启从 注 册 中心 动态创 建路由的功能,利用微服 务 名 进 行路由
      discovery:
        locator:
          enabled: true
      gateway:
        routes:
          - id: payment_routh #路由的ID,没有固定规则但要求唯一,建议配合服务名
            #uri: http://localhost:8001   #匹配后提供服务的路由地址
            uri: lb://cloud-payment-service
            predicates:
              - Path=/payment/get/**   #断言,路径相匹配的进行路由
    
          - id: payment_routh2
            #uri: http://localhost:8001
            uri: lb://cloud-payment-service
            predicates:
              - Path=/lb/**   #断言,路径相匹配的进行路由
    eureka:
    instance:
      hostname: cloud-gateway-service
    client:
      service-url:
        register-with-eureka: true
        fetch-registry: true
        defaultZone: http://www.eureka7001.com:7001/eureka,http://www.eureka7002.com:7002/eureka
    

    2、测试

  • 访问http://localhost:9527/payment/get/1

    • image.png
    • image.png
  • 访问http://localhost:9527/lb/port

    • image.png
    • image.png

      6、Predicate的使用

      1、简介

      启动我们的路由项目
  • 发现打印如下日志

    2021-09-03 09:53:09.972  INFO 3735 --- [  restartedMain] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [After]
    2021-09-03 09:53:09.972  INFO 3735 --- [  restartedMain] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [Before]
    2021-09-03 09:53:09.972  INFO 3735 --- [  restartedMain] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [Between]
    2021-09-03 09:53:09.972  INFO 3735 --- [  restartedMain] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [Cookie]
    2021-09-03 09:53:09.972  INFO 3735 --- [  restartedMain] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [Header]
    2021-09-03 09:53:09.972  INFO 3735 --- [  restartedMain] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [Host]
    2021-09-03 09:53:09.972  INFO 3735 --- [  restartedMain] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [Method]
    2021-09-03 09:53:09.972  INFO 3735 --- [  restartedMain] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [Path]
    2021-09-03 09:53:09.972  INFO 3735 --- [  restartedMain] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [Query]
    2021-09-03 09:53:09.973  INFO 3735 --- [  restartedMain] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [ReadBodyPredicateFactory]
    2021-09-03 09:53:09.973  INFO 3735 --- [  restartedMain] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [RemoteAddr]
    2021-09-03 09:53:09.973  INFO 3735 --- [  restartedMain] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [Weight]
    2021-09-03 09:53:09.973  INFO 3735 --- [  restartedMain] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [CloudFoundryRouteService]
    

    2、Route Predicate Factories这个是什么东东?

    https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#gateway-request-predicates-factories
    image.png

    3、常用的Route Predicate

    image.png

    1、After Route Predicate

    image.png

  • 使用如下代码可以打印出自己时区的时间格式

    ZonedDateTime zonedDateTime = ZonedDateTime.now();
    System.out.println(zonedDateTime);
    

    2、Before Route Predicate

    ```yaml

  • After=2020-03-08T10:59:34.102+08:00[Asia/Shanghai]
  • Before=2020-03-08T10:59:34.102+08:00[Asia/Shanghai]

    <a name="gBZft"></a>
    #### 3、Between Route Predicate
    ```yaml
     - Between=2020-03-08T10:59:34.102+08:00[Asia/Shanghai], 2020-03-08T10:59:34.102+08:00[Asia/Shanghai]
    

    4、Cookie Route Predicate

    image.png

  • 加入curl返回中文乱码

  • Cookie=username,atguigu #并且Cookie是username=zhangshuai才能访问 ```

    5、Header Route Predicate

    image.png ```yaml
  • Header=X-Request-Id, \d+ #请求头中要有X-Request-Id属性并且值为整数的正则表达式

    ![image.png](https://cdn.nlark.com/yuque/0/2021/png/12971636/1630635624410-c5d54e7c-cd01-4596-8ec2-ea6b5d478a42.png#clientId=ue193ba3d-36d1-4&from=paste&height=412&id=u10d62b4b&margin=%5Bobject%20Object%5D&name=image.png&originHeight=824&originWidth=1982&originalType=binary&ratio=1&size=807061&status=done&style=none&taskId=u3b515943-a394-4c87-96e4-5552d021037&width=991)<br />![image.png](https://cdn.nlark.com/yuque/0/2021/png/12971636/1630635635224-2c861597-d0de-4e35-a7ec-681279667bb9.png#clientId=ue193ba3d-36d1-4&from=paste&height=277&id=uc7a9f9b2&margin=%5Bobject%20Object%5D&name=image.png&originHeight=554&originWidth=2020&originalType=binary&ratio=1&size=534702&status=done&style=none&taskId=u396d7abc-614d-4116-a56b-07488fa493f&width=1010)
    <a name="Wtcte"></a>
    #### 6、Host Route Predicate
    ```yaml
    - Host=**.atguigu.com
    

    7、Method Route Predicate

      - Method=GET
    

    8、Path Route Predicate

  • 路径匹配我们最初用的就是这个

    predicates:
    - Path=/lb/**   #断言,路径相匹配的进行路由
    

    9、Query Route Predicate

    - Query=username, \d+ #要有参数名称并且是正整数才能路由
    

    10、小总结

  • 说白了,Predicate就是为了实现一组匹配规则,让请求过来找到对应的Route进行处理 ```yaml server: port: 9527 spring: application: name: cloud-gateway cloud: gateway:

    discovery:
      locator:
        enabled: true  #开启从注册中心动态创建路由的功能,利用微服务名进行路由
    routes:
      - id: payment_routh #路由的ID,没有固定规则但要求唯一,建议配合服务名
        #uri: http://localhost:8001   #匹配后提供服务的路由地址
        uri: lb://cloud-payment-service
        predicates:
          - Path=/payment/get/**   #断言,路径相匹配的进行路由
      - id: payment_routh2
        #uri: http://localhost:8001   #匹配后提供服务的路由地址
        uri: lb://cloud-payment-service
        predicates:
          - Path=/payment/lb/**   #断言,路径相匹配的进行路由
          #- After=2020-03-08T10:59:34.102+08:00[Asia/Shanghai]
          #- Cookie=username,zhangshuai #并且Cookie是username=zhangshuai才能访问
          #- Header=X-Request-Id, \d+ #请求头中要有X-Request-Id属性并且值为整数的正则表达式
          #- Host=**.atguigu.com
          #- Method=GET
          #- Query=username, \d+ #要有参数名称并且是正整数才能路由
    

    eureka: instance: hostname: cloud-gateway-service client: service-url:

    register-with-eureka: true
    fetch-registry: true
    defaultZone: http://eureka7001.com:7001/eureka
    
<a name="REQLM"></a>
## 7、Filter的使用
<a name="HdQgl"></a>
### 1、简介
![image.png](https://cdn.nlark.com/yuque/0/2021/png/12971636/1630647632559-e1f4efe8-0b57-4156-a3af-a922b1f61bb2.png#clientId=ue193ba3d-36d1-4&from=paste&height=248&id=u0c91c122&margin=%5Bobject%20Object%5D&name=image.png&originHeight=496&originWidth=2200&originalType=binary&ratio=1&size=581390&status=done&style=none&taskId=u2473ce39-28bf-4f9e-92a3-a673c78415b&width=1100)
<a name="twDQz"></a>
### 2、Spring Cloud Gateway的Filter 
<a name="Hbo2K"></a>
#### 1、生命周期

- pre 
   - 在业务逻辑之前
- post
   - 在业务逻辑之后
<a name="Nw6fc"></a>
#### 2、种类

- GatewayFilter(单一)
   - [https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#gatewayfilter-factories](https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#gatewayfilter-factories)
   - 31种
   - ![image.png](https://cdn.nlark.com/yuque/0/2021/png/12971636/1630647792553-656b9744-ec76-4c13-b045-9d4f4c026e21.png#clientId=ue193ba3d-36d1-4&from=paste&height=446&id=ub08feaa1&margin=%5Bobject%20Object%5D&name=image.png&originHeight=892&originWidth=804&originalType=binary&ratio=1&size=111381&status=done&style=none&taskId=u1e147b5a-efee-44cf-8e53-4ce79590649&width=402)
- Global Filters(全局)
   - [https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#global-filters](https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#global-filters)
   - 9种
   - ![image.png](https://cdn.nlark.com/yuque/0/2021/png/12971636/1630647832395-b62583e9-7c23-4b33-99d8-6e8399254738.png#clientId=ue193ba3d-36d1-4&from=paste&height=607&id=u35a5399a&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1214&originWidth=2840&originalType=binary&ratio=1&size=411556&status=done&style=none&taskId=u554c05da-fb62-400b-9592-10e75d97763&width=1420)
<a name="bM9fO"></a>
### 3、自定义过滤器(全局)
<a name="pG6aP"></a>
#### 1、两个主要接口介绍

- impiemerts  
   - GlobalFilter 
   - Ordered
<a name="tDDQH"></a>
#### 2、作用

- 全局日志记录
- 统一网关鉴权
<a name="ZQviQ"></a>
#### 3、添加代码

- GlobalGatewayFilter
```java
package com.daijunyi.filter;

import org.springframework.cloud.gateway.filter.GatewayFilter;
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.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

@Component
public class GlobalGatewayFilter implements GlobalFilter, Ordered {

    //具体实现代码的过滤方法
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        boolean username = exchange.getRequest().getQueryParams().containsKey("username");
        if (!username){
            exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);
            Mono<Void> voidMono = exchange.getResponse().setComplete();
            return voidMono;
        }
        return chain.filter(exchange);
    }

    //数值越小优先级越高
    @Override
    public int getOrder() {
        return 0;
    }
}

4、测试