11. Spring Cloud Zuul网关,route路由详解(Finchley版本)

一.前言

1.介绍

  • 在微服务中如果没有网关,一个客户端完成一个业务动作,可能需要调用多个微服务接口,而且每个微服务都需要安全认证,加大了客户端的复杂性。
  • zuul是一个客户端和服务端之间的中间层,客户端所有的请求流量都经过zuul做分发,zuul代理了后端的微服务,对于客户端来说屏蔽了后端微服务调用的复杂性;当后端微服务进行业务调整,只需要在zuul中调整路由规则就可以了,客户端和服务端得到了良好解耦合
  • Zuul也是一款由Netflix开发的微服务网关开源软件,和Netflix开发的Eureka,Ribbon和Hystrix配合使用
  • Zuul主要功能为路由器和过滤器,这篇主要介绍路由功能

2.项目准备

  • 项目地址完整例子传送门
  • 此篇文章用到项目模块:


    11. Spring Cloud Zuul网关,route路由详解(Finchley版本)_第1张图片
  • 模块介绍:
    1. eureka-server-standalone: 提供注册中心的服务
    2. zuul-gateway:提供zuul网关功能,注册到eureka服务中心
    3. zuul-consumer:提供接口调用,具有hystrix熔断功能,和ribbon负载均衡功能,注册到eureka服务中心

二.创建zuul服务

  • Spring Cloud集成Zuul代理,可以默认代理注册中心的服务。从而避免了后端每个微服务都需要独立管理CORS和身份验证问题。

1.官网资料

  • Zuul使用
  • Netflix / Zuul

2.创建 zuul-gateway项目

  • 在启动类中ZuulGatewayApplication.java
@EnableZuulProxy
@SpringCloudApplication
public class ZuulGatewayApplication {
   public static void main(String[] args) {
       SpringApplication.run(ZuulGatewayApplication.class, args);
   }
}

加入@EnableZuulProxy表示此项目启动zuul代理功能
加入@SpringCloudApplication表示此项目启动断路由,eureka注册功能

  • 在pom.xml中
   
        
            org.springframework.cloud
            spring-cloud-starter-netflix-zuul
        
        
            org.springframework.cloud
            spring-cloud-starter-netflix-eureka-client
        
    

引入zuuleureka-client依赖,其中zuul包含了hystrixactuatorribbon等功能,见下图

11. Spring Cloud Zuul网关,route路由详解(Finchley版本)_第2张图片

  • 配置文件application.yml
spring:
  application:
    name: Zuul-Gateway
server:
  port: 9001
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/
management:
  endpoints:
    web:
      exposure:
        include: '*'

management.endpoints.web.exposure.include:打开actuator的监控端口,,默认只打开了healthinfo的监控监控点*代表全部打开,此举是用于查看/routes接口,返回此zuul代理了多少服务,以及路由规则;如下:

  • 启动验证
    1.依次启动eureka-server-standalone端口为8760, zuul-gateway端口为9001
    2.zuu项目有对外暴露的actuator端点

    /routes:获取zuul项目的代理服务列表
    /routes/details:zuul项目的代理服务详情

    3.访问http://localhost:9001/actuator/routes,可见如下,只代理了自己的服务

    { "/zuul-gateway/**": "zuul-gateway"}
    

    4.也可以查看详情localhost:9001/actuator/routes/details

    {
    "/zuul-gateway/**": {
        "id": "zuul-gateway",
        "fullPath": "/zuul-gateway/**",
        "location": "zuul-gateway",
        "path": "/**",
        "prefix": "/zuul-gateway",
        "retryable": false,
        "customSensitiveHeaders": false,
        "prefixStripped": true
    }
    }
    

3.创建 zuul-consumer项目

  • 提供接口调用,注册到eureka服务中心,具有hystrix熔断功能,和ribbon负载均衡功能

  • 在启动类中ZuulConsumerApplication.java

@SpringCloudApplication
@RestController
public class ZuulConsumerApplication {

   public static void main(String[] args) {
       SpringApplication.run(ZuulConsumerApplication.class, args);
   }

   @Qualifier("eurekaRegistration")
   @Autowired
   private Registration registration;

   @GetMapping("getInstanceServiceIdAndPort")
   public String  getInstanceServiceIdAndPort(){
       String serviceId = registration.getServiceId();
       int port = registration.getPort();
       return serviceId+":"+port;
   }

   @GetMapping("getInstanceServiceIdAndPortWithThrowError")
   @HystrixCommand(fallbackMethod = "rollBack")
   public String  getInstanceServiceIdAndPortWithThrowError(){
       int port = registration.getPort();
      throw  new RuntimeException("go away!!"+"and  port is : "+port);
   }
   public String  rollBack(Throwable e){
       return "throw error is : "+e.getMessage();
   }

}

实现getInstanceServiceIdAndPort:用于提供获取本机实例和端口的接口服务
实现getInstanceServiceIdAndPortWithThrowError:模拟熔断回退
注入Registration:获取本地的一些信息

  • 在pom.xml中
  
        
            org.springframework.cloud
            spring-cloud-starter-netflix-eureka-client
        
        
            org.springframework.boot
            spring-boot-starter-actuator
        
        
            org.springframework.cloud
            spring-cloud-starter-netflix-hystrix
        
        
            org.springframework.boot
            spring-boot-starter-web
        
    
  • 配置文件application.yml
spring:
  application:
    name: Zuul-Consumer
server:
  port: 9003
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/
management:
  endpoints:
    web:
      exposure:
        include: '*'

management.endpoints.web.exposure.include:打开actuator的监控端口,默认只打开了healthinfo的监控监控点*代表全部打开

4. 验证代理

  • 依次启动eureka-server-standalone端口为8760, zuul-gateway端口为9001, zuul-consumer启动2个实例端口分别为9002,9003

  • 访问http://localhost:9001/actuator/routes,可见如下,代理了自己的服务zuul-gateway的同时也代理了 zuul-consumer

    {
    "/zuul-gateway/**": "zuul-gateway",
    "/zuul-consumer/**": "zuul-consumer"
    }
    

    也可以查看详情localhost:9001/actuator/routes/details

    {
        "/zuul-gateway/**": {
            "id": "zuul-gateway",
            "fullPath": "/zuul-gateway/**",
            "location": "zuul-gateway",
            "path": "/**",
            "prefix": "/zuul-gateway",
            "retryable": false,
            "customSensitiveHeaders": false,
            "prefixStripped": true
        },
        "/zuul-consumer/**": {
            "id": "zuul-consumer",
            "fullPath": "/zuul-consumer/**",
            "location": "zuul-consumer",
            "path": "/**",
            "prefix": "/zuul-consumer",
            "retryable": false,
            "customSensitiveHeaders": false,
            "prefixStripped": true
        }
    }
    
  • 验证代理的ribbon负载均衡,和hystrix熔断保护功能
    1.默认情况下zuul有自己的路由规则

    • 会将/zuul-consumer/**转发到zuul-consumer服务的接口上,通过调用/routes也可以清晰的看到

    2.访问代理接口http://localhost:9001/zuul-consumer/getInstanceServiceIdAndPort
    返回端口轮询切换,代表ribbon负载均衡正常工作

    • Zuul-Consumer:9002
    • Zuul-Consumer:9003
3.访问代理接口`http://localhost:9001/zuul-consumer/getInstanceServiceIdAndPortWithThrowError`,返回降级信息代表`hystrix`降级正常运行
>throw error is : go away!!and  port is : 9002

三. 路由配置

1.使用url方式映射路由

  • 直接使用pathurl地址路由到具体服务
  • zuul-gateway的配置文件application.yml中,添加
    zuul:
      routes:
        user-defined-zuul-a:
          path: /zuul-api-a/**
          url: http://localhost:9002
        user-defined-zuul-b:
          path: /zuul-api-b/**
          url: http://localhost:9003
    
  1. user-defined-zuul-auser-defined-zuul-b是自定义key,/zuul-api-a/**的请求会被路由到http://localhost:9002服务
  2. 访问/routes/details可见代理详情
    {
        "/zuul-api/**": {
            "id": "zuul",
            "fullPath": "/zuul-api/**",
            "location": "http://localhost:9002",
            "path": "/**",
            "prefix": "/zuul-api",
            "retryable": false,
            "customSensitiveHeaders": false,
            "prefixStripped": true
        },
        "/zuul-gateway/**": {
            "id": "zuul-gateway",
            "fullPath": "/zuul-gateway/**",
            "location": "zuul-gateway",
            "path": "/**",
            "prefix": "/zuul-gateway",
            "retryable": false,
            "customSensitiveHeaders": false,
            "prefixStripped": true
        },
        "/zuul-consumer/**": {
            "id": "zuul-consumer",
            "fullPath": "/zuul-consumer/**",
            "location": "zuul-consumer",
            "path": "/**",
            "prefix": "/zuul-consumer",
            "retryable": false,
            "customSensitiveHeaders": false,
            "prefixStripped": true
        }
    }
    
  3. 调用接口验证访问,zuul网关服务http://localhost:9001/zuul-api-b/getInstanceServiceIdAndPort,返回代理信息

    Zuul-Consumer:9003

  4. 注意:此种方式不会触发ribbon负载均衡和hystrix熔断功能

2. 使用服务id方式进行路由

  • 直接使用pathserviceId服务路由到具体服务,具有ribbon负载均衡和hystrix熔断功能

  • zuul-gateway的配置文件application.yml中,添加

    zuul:
      routes:
        user-defined-zuul-c:
          path: /zuul-api-c/**
          serviceId : Zuul-Consumer
    
    1. user-defined-zuul-c是自定义key,/zuul-api-c/**的请求会被路由到服务名称是Zuul-Consumer的微服务
    2. 访问/routes可见代理
            {
            "/zuul-api-c/**": "Zuul-Consumer",
            "/zuul-gateway/**": "zuul-gateway",
            "/zuul-consumer/**": "zuul-consumer"
            }
    
  • 上述配置可简写为

    zuul:
      routes:
          Zuul-Consumer: /zuul-api-c/**
    
    1. 直接使用servcieId:url的形式

3. 默认路由&忽略指定服务列表

  • 如果我们不进行自定义配置,则zuul有自己的默认路由规则,如下:
    "/zuul-gateway/**": "zuul-gateway",
    "/zuul-consumer/**": "zuul-consumer"
    
    1. 当我们访问zuul网关的zuul-gateway/hello就会路由到具体的微服务/hello接口上
  • 有时我们需要有zuul代理某个微服务,这时就需要忽略指定微服务代理
  • 我们先查看一下,使用默认路由的代理情况,现在我们启动的项目如下Zuul-Gateway网关,ZuulConsumer接口服务,EurekaServerStandalone注册中心,访问zuul的/actuator/routes端点接口,得到如下代理路由:
    "/zuul-gateway/**": "zuul-gateway",
    "/zuul-consumer/**": "zuul-consumer"
    
  • zuul-gateway的配置文件application.yml中,添加忽略配置,忽略zuul-gateway微服务
    zuul:
      ignoredServices: 'zuul-gateway'
    
  • 重启再次访问/actuator/routes,可见 zuul-gateway不再被代理
    {
        "/zuul-consumer/**": "zuul-consumer"
    }
    
    1. 设置为zuul.ignored-services=*的时候将关闭所有默认路由配置规则

4. 路由优先级

  • 路由规则是根据先后定义从上到下,假如某个请求路径可以和多个路由配置规则相匹配的话,Zuul根据匹配的先后顺序来决定最终使用哪个路由配置,例如如下配置
    zuul:
      routes:
          Zuul-Consumer: /zuul-api-c/**
          Zuul-Consumer2: /zuul-api-c/a/**
    
  • 访问/zuul-api-c/a/xx,不会转发到Zuul-Consumer2服务上,会在Zuul-Consumer查找相关接口,若没有,返回404错误码

5.路由前缀 & 本地转发

  • 使用zuul.prefix属性给全体路由添加前缀
    zuul:
        prefix: /api
    
    访问actuator/routes可见所有代理都添加了前缀
    {
    "/api/zuul-consumer2/**": "zuul-consumer2",
    "/api/zuul-gateway/**": "zuul-gateway",
    "/api/zuul-consumer/**": "zuul-consumer"
    }
    
  • zuul不仅可以将请求转发到其他服务身上,也可以将请求转发到自己本身
    1. 在zuul配置文件中,添加如下配置

          zuul:
            routes:
              api:
                path: /api-d/**
                url: forward:/
      
      • url: forward:/:代表跳转到本zuul服务的/路径下所有接口
    2. 在Zuul-Gateway添加接口服务

      @EnableZuulProxy
      @SpringCloudApplication
      @RestController
      public class ZuulGatewayApplication {
          public static void main(String[] args) {
              SpringApplication.run(ZuulGatewayApplication.class, args);
          }
          @Autowired
          private Registration registration;
      
          @GetMapping("hello")
          public String  getInstanceServiceIdAndPort(){
              String serviceId = registration.getServiceId();
              int port = registration.getPort();
              return serviceId+":"+port;
          }
      }
      
    3. 验证,访问http://localhost:9001/api-d/hello 返回

      Zuul-Gateway:9001

6.头部过滤 & 重定向

  • 在使用Zuul网关的时候你可能会遇到Cookie丢失的情况,这是因为默认情况下Zuul会过滤掉HTTP请求头中的一些敏感信息,不会向后传播,默认值为:

    private Set sensitiveHeaders = new LinkedHashSet(Arrays.asList("Cookie", "Set-Cookie", "Authorization"));
    
  • 这些敏感信息通过下面的配置设定,设置全局

    zuul:
    sensitive-headers: Cookie,Set-Cookie,Authorization
    
  • 设置某一个代理服务

    zuul:
      routes:
        users:
          path: /myusers/**
          sensitiveHeaders: Cookie,Set-Cookie,Authorization
          url: https://downstream
    
  • 关闭头部过滤,sensitiveHeaders设置为空就可以了

     zuul:
      routes:
        users:
          path: /myusers/**
          sensitiveHeaders:
          url: https://downstream
    
  • 重定向host处理设置问题,使用如下配置解决

    zuul:
      add-host-header: true
    

    上一篇:Spring Cloud Hystrix聚集监控信息,Turbine详解(Finchley版本)

你可能感兴趣的:(11. Spring Cloud Zuul网关,route路由详解(Finchley版本))