1.简介

06 Zuul网关 - 图1

2.Zuul加入后的架构

06 Zuul网关 - 图2
不管是来自于客户端(PC或移动端)的请求,还是服务内部调用。一切对服务的请求都会经过Zuul这个网关,然后再由网关来实现 鉴权、动态路由等等操作。Zuul就是我们服务的统一入口。

3.快速入门

创建gateway模块

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5. <parent>
  6. <artifactId>cloud-demo</artifactId>
  7. <groupId>com.keyi.demo</groupId>
  8. <version>1.0.0-SNAPSHOT</version>
  9. </parent>
  10. <modelVersion>4.0.0</modelVersion>
  11. <artifactId>gateway</artifactId>
  12. <dependencies>
  13. <dependency>
  14. <groupId>org.springframework.cloud</groupId>
  15. <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
  16. </dependency>
  17. </dependencies>
  18. </project>

启动类

  1. @EnableZuulProxy // 开启网关代理
  2. @SpringBootApplication
  3. public class GatewayApplication {
  4. public static void main(String[] args) {
  5. SpringApplication.run(GatewayApplication.class);
  6. }
  7. }

yml

  1. server:
  2. port: 10010
  3. spring:
  4. application:
  5. name: gateway

编写路由规则

我们需要用Zuul来代理user-service服务, 先看下服务状态:
06 Zuul网关 - 图3
ip为 127.0.0.1 端口为8081
映射规则:

  1. zuul:
  2. routes:
  3. user-service: # 这里是路由id,随意写
  4. path: /user/** # 这里是映射路径
  5. url: http://127.0.0.1:8081 # 映射路径对应的实际url地址

我们将符合path规则的一切请求,都代理到 url参数指定的地址
本例中,我们将 /user-service/**开头的请求,代理到http://127.0.0.1:8081

启动测试:

访问的路径中需要加上配置规则的映射路径,我们访问:http://127.0.0.1:8081/user/1
所有映射为: http://localhost:10010/user/user/1
06 Zuul网关 - 图4

4.面向服务的路由

在刚才的路由规则中,我们把路径对应的服务地址写死了,如果同一个服务有多个实例的话,显然不合理.
应该根据服务的名称,去Eureka注册中心查找 服务对应的所有实例列表,然后进行动态路由才对!

添加Eureka依赖

  1. <dependency>
  2. <groupId>org.springframework.cloud</groupId>
  3. <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
  4. </dependency>

修改配置文件,通过服务名称获取

  1. eureka:
  2. client:
  3. service-url:
  4. defaultZone: http://127.0.0.1:10086/eureka
  5. zuul:
  6. routes:
  7. user-service:
  8. path: /user/**
  9. serviceId: user-service

启动测试

再次启动,这次Zuul进行代理时,会利用Ribbon进行负载均衡访问:
06 Zuul网关 - 图5
日志中可以看到使用了负载均衡器:
06 Zuul网关 - 图6

5.简化路由配置

在刚才的配置中,我们的规则为

  1. zuul:
  2. routes:
  3. 自定义的路由名:
  4. path: /xxx/**
  5. serviceId: user-service

在大多数情况下,我们自定义的路由名往往和服务名会写成一样,因此Zuul就提供了一种简化的配置语法,省去了对服务名称的配置

  1. 语法:
  2. zuul:
  3. routes:
  4. serviceId: path
  5. 例子:
  6. zuul:
  7. routes:
  8. user-service: /user/**

6.默认的路由规则

Zuul已经为我们指定了默认的路由规则:
默认情况下,一切服务的映射路径就是服务名本身。
例如服务名为:order-service,则默认的映射路径就是:/order-service/**
也就是说, 刚才的映射规则,不配置也是行得通的

7.路由前缀与忽略

全局前缀

  1. zuul:
  2. prefix: /api # 添加路由前缀
  3. routes:
  4. user-service: /user/**

通过zuul.prefix=/api来指定了路由的前缀,这样在发起请求时,路径就要以/api开头。
api/user-service/user/1 将会被代理到 /user-service/user/1

忽略前缀

  1. zuul:
  2. routes:
  3. user-service:
  4. path: /user/**
  5. serviceId: user-service
  6. strip-prefix: false # 取消去除映射前缀

原地址: /user/user/1
现地址: /user/1

忽略自动映射服务

  1. zuul:
  2. ignored-services:
  3. - consumer-demo

8.过滤器

Zuul作为网关的其中一个重要功能,就是实现请求的鉴权。而这个动作我们往往是通过Zuul提供的过滤器来实现的。

ZuulFilter

ZuulFilter是过滤器的顶级父类。在这里我们看一下其中定义的4个最重要的方法:

  1. public abstract ZuulFilter implements IZuulFilter{
  2. abstract public String filterType();
  3. abstract public int filterOrder();
  4. boolean shouldFilter();// 来自IZuulFilter
  5. Object run() throws ZuulException;// IZuulFilter
  6. }

shouldFilter:返回一个Boolean值,判断该过滤器是否需要执行。返回true执行,返回false不执行。
run:过滤器的具体业务逻辑。
filterType:返回字符串,代表过滤器的类型。包含以下4种:

  • pre:请求在被路由之前执行
  • routing:在路由请求时调用
  • post:在routing和errror过滤器之后调用
  • error:处理请求时发生错误调用

filterOrder:通过返回的int值来定义过滤器的执行顺序,数字越小优先级越高。

过滤器执行生命周期:

这张是Zuul官网提供的请求生命周期图,清晰的表现了一个请求在各个过滤器的执行顺序。
06 Zuul网关 - 图7
所有内置过滤器列表:
06 Zuul网关 - 图8