前言
听说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的参数没有调优,测试时还跑着其他程序等等,所以欢迎大家讨论。