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

  • 相关阅读:
    final
    职场语句
    故事
    三个关键字
    关于重读字母去掉的代码
    Java书
    docker私库harbor的搭建
    配置允许匿名用户登录访问vsftpd服务,进行文档的上传下载、文档的新建删除等操作
    docker容器内外相互拷贝数据
    docker
  • 原文地址:https://www.cnblogs.com/cjsblog/p/9525720.html
Copyright © 2020-2023  润新知