基于Zuul2.0搭建微服务网关以及和NGINX的测试对比

前言

听说Netflix把基于Netty框架的Zuul2.0也开源了,由于之前研究过一段时间的Zuul,虽然很喜欢但在测试中表现的不尽如人意,只能忍痛割爱,选用Nginx了,这次Zuul升级果断再来试一试,再顺便把Zuul2.0和Nginx初步对比着测试一下,供大家参考。

基于Zuul2.0搭建微服务网关

Zuul简介

Zuul 是在云平台上提供动态路由,监控,弹性,安全等边缘服务的框架。Zuul 相当于是设备和 Netflix 流应用的 Web 网站后端所有请求的前门。,这次Zuul的升级最大的亮点是基于Netty框架的异步机制重构的,性能应该有不少提升,让我们拭目以待。
16年那阵对于Zuul1.0的测试结果是默认配置下并发只能支持到几百的量级,远不是同期Nginx的对手。

服务搭建

SpringCloud的东西使用起来还是比较简单的,首先是构建工程,可以通过https://start.spring.io/来生成相应的工程,注意把Zuul选上就可以了。下面是我的pom.xml。
我的依赖比较多,其实大家没必要把robbin和fegin也加进来。

<?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.zw.se2</groupId>
    <artifactId>gateway</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>gateway</name>
    <description>Router for uav replace nginx</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.1.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.RC1</spring-cloud.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-config</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.session</groupId>
            <artifactId>spring-session-core</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.3</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

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

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-resources-plugin</artifactId>
                <version>3.0.1</version>
                <executions>
                    <execution>
                        <id>copy-conf</id>
                        <phase>package</phase>
                        <goals>
                            <goal>copy-resources</goal>
                        </goals>
                        <configuration>
                            <encoding>UTF-8</encoding>
                            <outputDirectory>${project.build.directory}/ext/conf</outputDirectory>
                            <resources>
                                <resource>
                                    <directory>ext/conf</directory>
                                    <includes>
                                        <include>logback.xml</include>
                                    </includes>
                                    <filtering>true</filtering>
                                </resource>
                            </resources>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.jacoco</groupId>
                <artifactId>jacoco-maven-plugin</artifactId>
                <version>0.7.5.201505241946</version>
                <executions>
                    <execution>
                        <id>default-prepare-agent</id>
                        <goals>
                            <goal>prepare-agent</goal>
                        </goals>
                    </execution>
                    <execution>
                        <id>default-prepare-agent-integration</id>
                        <goals>
                            <goal>prepare-agent-integration</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>com.spotify</groupId>
                <artifactId>docker-maven-plugin</artifactId>
                <version>0.4.3</version>
                <configuration>
                    <imageName>hy_uav_gateway</imageName>
                    <dockerDirectory>src/main/docker</dockerDirectory>
                    <resources>
                        <resource>
                            <targetPath>/</targetPath>
                            <directory>${project.build.directory}</directory>
                            <include>${project.build.finalName}.jar</include>
                            <include>ext/conf/logback.xml</include>
                        </resource>
                    </resources>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <repositories>
        <repository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/milestone</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
    </repositories>


</project>

然后是启动类。Application.java

package com.zw.se2.gateway;

import com.zw.se2.hy.uav.gateway.post.LoginResponseFilter;
import com.zw.se2.hy.uav.gateway.post.LogoutResponseFilter;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
import org.springframework.context.annotation.Bean;

/**
 * @author zew
 */
@EnableZuulProxy
@SpringBootApplication
public class GatewayApplication {


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

服务配置

相信开发过Spring体系工程的人都知道配置是重点。
下面是appliation.properties

#服务端口
server.port=8919
#静态资源路由配置
zuul.routes.ui-js.path=/**/**.js
zuul.routes.ui-js.serviceId=reborn-ui-server
zuul.routes.ui-html.path=/**/**.html
zuul.routes.ui-html.serviceId=reborn-ui-server
#Demo1的路由配置
zuul.routes.demo1.path=/**/demo1/**
zuul.routes.demo1.serviceId=reborn-demo1-server
zuul.routes.demo1.sensitiveHeaders="*"
#Demo2的路由配置
zuul.routes.demo2.path=/**/demo2/**
zuul.routes.demo2.serviceId=reborn-demo2-server
zuul.routes.demo2.sensitiveHeaders="*"
#服务名
spring.application.name=demo-gateway-server
#是否转发后是否还带有转发特征的字符
zuul.stripPrefix=false

#将 hystrix 的超时时间禁用掉
hystrix.command.default.execution.timeout.enabled=false
#session存储
spring.session.store-type=none

关于这个配置值得多说几句:
1.其实Zuul也可以做静态资源的代理,但由于缺乏缓存等关键能力还是不太合适的,要是对于性能不是很关心的可以试试。
2.Zuul 2.0和1.0的配置并没有太大的变化.
3.注意stripPrefix这个参数,这个参数的代表的意义是转发后还带不带转发表示字符
具体如下,原始的url是http://zuulIp:zuulPort/test/demo1/hello,
如果这个参数设置为true,那么对于Demo1的服务而言,它受到的请求url就是http://demo1Ip:demo1Port/test/hello
如果这个参数设置为false,那么对于Demo1的服务而言,它受到的请求url就是http://demo1Ip:demo1Port/test/demo1/hello
别忘了,SpringCloud还有注册中心和配置中心的配置,bootstrap.yaml

eureka:
  client:
    service-url:
        defaultZone: http://localhost:8797/eureka
spring:
  cloud:
    config:
      uri: http://localhost:8888
      profile: dev
      name: config

与NGINX的对比测试

测试环境

硬件环境:
CPU:E5 1.2G Hz
内存:32G,但负载50%
没有固态硬盘。
软件:
java:jdk 8
Zuul:版本2.0
nginx:1.13.8
OS:windows 10

Nginx的配置,nginx.conf

#user  www www;
worker_processes 2;
worker_rlimit_nofile 65535;

events
{
  worker_connections 65535;
}

http
{
 include      mime.types;
  default_type application/octet-stream;

  server_names_hash_bucket_size 128;
  client_header_buffer_size 32k;
  large_client_header_buffers 4 32k;
  client_max_body_size 8m;

  sendfile on;
  tcp_nopush    on;
  keepalive_timeout 0;
  tcp_nodelay on;

  fastcgi_connect_timeout 300;
  fastcgi_send_timeout 300;
  fastcgi_read_timeout 300;
  fastcgi_buffer_size 64k;
  fastcgi_buffers 4 64k;
  fastcgi_busy_buffers_size 128k;
  fastcgi_temp_file_write_size 128k;


  ##cache##
  proxy_connect_timeout 5;
  proxy_read_timeout 60;
  proxy_send_timeout 5;
  proxy_buffer_size 16k;
  proxy_buffers 4 64k;
  proxy_busy_buffers_size 128k;
  proxy_temp_file_write_size 128k;
  proxy_temp_path /home/temp_dir;
  proxy_cache_path /home/cache levels=1:2 keys_zone=cache_one:200m inactive=1d max_size=30g;
  ##end##

  gzip   on;
  gzip_min_length   1k;
  gzip_buffers  4 8k;
  gzip_http_version 1.1;
  gzip_types  text/plain application/x-JavaScript text/css application/xml;
  gzip_disable "MSIE [1-6]\.";

  log_format access  '$remote_addr - $remote_user [$time_local]"$request" '
            '$status $body_bytes_sent "$http_referer" '
            '"$http_user_agent" $http_x_forwarded_for';

  upstream demo{ 
       server localhost:8791;
       server 10.0.4.3:8791;
       server 10.0.4.217:8791;
  }

  server {
       listen      8988 default;
       server_name zw.uav.com;


       #前端服务
       location ~ home* {
             proxy_pass http://demo;
       }


  }
}

对于Zuul的配置上面已经给出了。
在注册中心上注册了三个Demo1的服务,也就是Nginx对应的那三个。
对了测试工具选用的Jmeter。
nginx代理8988端口,zuul代理8919端口,后面测试结果都是端口标识的。

测试结果

直接访问

上面三个测试用的demo1服务,直接访问的测试结果如下图所示。
这里写图片描述
吞吐量超过3000。

并发200

Nginx:
这里写图片描述
Zuul:
这里写图片描述

并发500

Nginx:
这里写图片描述
Zuul:
这里写图片描述

并发900,循环5次和10次

Nginx:
这里写图片描述
Zuul:
这里写图片描述

总结

1.测试结果显示由于异步机制的引入,Zuul 2.0比1.0的性能还是提高了不少的,
2.Zuul 2.0跟1.0都有一个问题就是面对突然的并发提高表现并不是特别好,需要一点适应的时间
3.在900测试停下的原因是无论是nginx和zuul都已经开始出现错误(error>0),再进一步测试也没有太大价值。
4.由于技术水平和测试条件有限,不少地方还是有待完善,比如Nginx的参数没有调优,测试时还跑着其他程序等等,所以欢迎大家讨论。

猜你喜欢

转载自blog.csdn.net/zhaoenweiex/article/details/80295024