Zuul介紹


1.  Zuul是什么


Zuul是所有從設備和web站點到Netflix流媒體應用程序后端請求的前門。作為一個邊緣服務應用程序,Zuul被構建來支持動態路由、監視、彈性和安全性。它還可以根據需要將請求路由到多個Amazon自動伸縮組。

 

2.  為什么用Zuul


Zuul使用了一系列不同類型的過濾器,使我們能夠快速靈活地將功能應用到服務中。這些過濾器幫助我們執行以下功能:

  • 身份驗證和安全性 : 識別每個資源的身份驗證需求,並拒絕不滿足它們的請求
  • 監控 : 在邊緣跟蹤有意義的數據和統計數據,以便給我們一個准確的生產視圖
  • 動態路由 : 動態路由請求到不同的后端集群
  • 壓力測試 : 逐漸增加集群的流量,以評估性能
  • 限流 : 為每種請求類型分配容量,並丟棄超過限制的請求
  • 靜態響應處理 : 直接在邊緣構建一些響應,而不是將它們轉發到內部集群

 

3.  在Netflix上是如何使用Zuul的


 

4.  Zuul是如何工作的


4.1.  Zuul 2.0架構

Zuul的核心業務邏輯是過濾器。它們能夠執行非常大范圍的操作,並且可以在請求-響應生命周期的不同階段運行。如下圖所示:

  • Inbound Filters : 路由到 Origin 之前執行,可以用於身份驗證、路由和裝飾請求
  • Endpoint Filters : 可用於返回靜態響應,否則內置的ProxyEndpoint過濾器將請求路由到Origin
  • Outbound Filters : 從Origin那里獲取響應后執行,可以用於度量、裝飾用戶的響應或添加自定義header

有兩種類型的過濾器:sync 和 async。因為Zuul是運行在一個事件循環之上的,因此從來不要在過濾中阻塞。如果你非要阻塞,可以在一個異步過濾器中這樣做,並且在一個單獨的線程池上運行,否則可以使用同步過濾器。

4.2.  Zuul 1.0 請求生命周期

5.  過濾器


過濾器是Zuul的核心功能。它們負責應用程序的業務邏輯,可以執行各種任務。

  • Type : 通常定義過濾器應用在哪個階段
  • Async : 定義過濾器是同步還是異步
  • Execution Order : 執行順序
  • Criteria : 過濾器執行的條件
  • Action : 如果條件滿足,過濾器執行的動作

Zuul提供了一個動態讀取、編譯和運行這些過濾器的框架。過濾器之間不直接通信,而是通過每個請求特有的RequestContext共享狀態。

5.1.  Incoming

Incoming過濾器在請求被代理到Origin之前執行。這通常是執行大部分業務邏輯的地方。例如:認證、動態路由、速率限制、DDoS保護、指標。

5.2.  Endpoint

Endpoint過濾器負責基於incoming過濾器的執行來處理請求。Zuul有一個內置的過濾器(ProxyEndpoint),用於將請求代理到后端服務器,因此這些過濾器的典型用途是用於靜態端點。例如:健康檢查響應,靜態錯誤響應,404響應。

5.3.  Outgoing

Outgoing過濾器在從后端接收到響應以后執行處理操作。通常情況下,它們更多地用於形成響應和添加指標,而不是用於任何繁重的工作。例如:存儲統計信息、添加/剝離標准標題、向實時流發送事件、gziping響應。

5.4.  過濾器類型

下面是與一個請求典型的生命周期對應的標准的過濾器類型:

  • PRE : 路由到Origin之前執行
  • ROUTING : 路由到Origin期間執行
  • POST : 請求被路由到Origin之后執行
  • ERROR : 發生錯誤的時候執行

 

6.  示例


6.1.  2.0示例

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

https://github.com/Netflix/zuul/tree/2.1/zuul-sample

6.1.  1.0示例

6.1.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">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.cjs.example</groupId>
    <artifactId>cjs-springcloud-example</artifactId>
    <packaging>pom</packaging>
    <version>1.0-SNAPSHOT</version>
    <modules>
        <module>route-book</module>
        <module>route-gateway</module>
    </modules>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.4.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <spring-cloud.version>Finchley.SR1</spring-cloud.version>

        <lombok.version>1.18.2</lombok.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <!-- Spring Cloud -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <!-- Lombok -->
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>${lombok.version}</version>
                <scope>provided</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

</project>

6.1.2.  book工程

<?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>cjs-springcloud-example</artifactId>
        <groupId>com.cjs.example</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>route-book</artifactId>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

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

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

RouteBookApplication.java

package com.cjs.example;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@SpringBootApplication
public class RouteBookApplication {

    @RequestMapping("/hello")
    public String hello() {
        return "hello";
    }

    @RequestMapping("/hi")
    public String hi() {
        return "hi";
    }

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

application.properties

spring.application.name=book
server.port=8090

6.1.3.  gateway工程

<?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>cjs-springcloud-example</artifactId>
        <groupId>com.cjs.example</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>route-gateway</artifactId>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

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

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

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

RouteGatewayApplication.java

package com.cjs.example;

import com.cjs.example.filter.SimpleFilter;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
import org.springframework.context.annotation.Bean;

/**
 * http://localhost:8080/books/hello
 * http://localhost:8080/books/hi
 */

@EnableZuulProxy
@SpringBootApplication
public class RouteGatewayApplication {

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

    @Bean
    public SimpleFilter simpleFilter() {
        return new SimpleFilter();
    }
}

SimpleFilter.java

package com.cjs.example.filter;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import lombok.extern.slf4j.Slf4j;

import javax.servlet.http.HttpServletRequest;

/**
 * Zuul有4中標准的過濾器類型:
 *      pre 過濾器,在請求被路由之前執行
 *      route 過濾器,在路由請求的時候執行
 *      post 過濾器,請求被路由以后執行
 *      error 過濾器,如果在處理請求的過程中發生錯誤,則執行
 *
 *
 * 繼承com.netflix.zuul.ZuulFilter的Bean就是一個filter
 */

@Slf4j
public class SimpleFilter extends ZuulFilter {

    /**
     * 過濾器類型,在這種情況下可選值是:pre 或者 route
     */
    @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 ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        log.info("Method: {}, URL: {}", request.getMethod(), request.getRequestURL());
        return null;
    }
}

application.properties

server.port=8080

#Spring Cloud Zuul將自動設置路徑到應用
#在本例中,因為我們設置zuul.routes.books.url=http://localhost:8090,所以Zuul將代理/books的請求到http://localhost:8090
zuul.routes.books.url=http://localhost:8090

ribbon.eureka.enabled=false

 

7.  參考


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

https://springcloud.cc/

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM