Netty与Voovan并发性能对比

Stella981
• 阅读 1233

Netty: 大名鼎鼎, Javaer 人尽皆知的优秀框架,作为曾今的使用者对 netty 的作者也有无限的崇拜之情.对于 netty 的特点和优势这里不在多言,以免言多必失,大家可以问度娘.嘿嘿

Voovan:  Voovan奉行简约、优雅,其核心功能则是异步通信,同时还包含了动态编译、反射、ORM、Http 服务和客户端、websocket 服务和客户端、JSON 的序列化以及日志等一款综合性工具框架。

既然 Voovan 和 Netty 都是已 socket 通信作为核心的通信框架.这里我们对 Voovan 和 Netty 做一个性能对比的测试,同时我们对编码也进行对比,来看看两款框架有什么神奇的区别。

异同点:

     1.都支持 TLS、SSL 加密。

     2.都支持 TCP、UDP 通信模型。

     3.都使用异步事件驱动。

     4.都实现了 HTTP、WEBSOCKET 协议的支持。

     5.Voovan 比 Netty 多了一个消息分割类,具体看后面的介绍 。

     6.Voovan 框架额外实现了一个 Web 服务。    

     7.文档方面两个框架都有着较为丰富的文档,只是 Netty 文档多为英文,而 Voovan 由于是国人开发,多为中文文档.

     8.Netty 提供了较多的协议的默认实现.

     9.Voovan 提供了额外的更多的工具类的支持.

一、主机环境

资源有限使用虚拟机进行性能测试

     OS              Ubuntu 16.04
     CPU            Intel(R) Core(TM) i5-6500 CPU @ 3.20GHz
     CPUCount   4核
     内存            512M
     JDK            OpenJDK  1.8.0_111-8u111-b14-2 @ ubuntu0.16.04.2-b14
命令          ab -c 100 -n 10000 http://10.0.0.102:2808?/

二、测试说明

     测试目的: 对比 Voovan 和 Netty 在并发场景下能够支撑的并发连接数.

     测试工具: Apache bench

     原料:Netty 4.1.8 、 Voovan1.0-RC-1

     为避免自己编码的压测工具带来各种风险,同时也为了使测试结果更加公平、真实、可信。测试方法如下:

          1. 使用 ab 进行压力测试 

         2. Voovan 和 Netty 两个框架分别模拟 Http 服务,在接受到 HTTP 请求后不进行解析,直接返回相同的 Http 响应后关闭连接。

         3. 每次响应都关闭连接,保证不会因 HTTP 的 KeepAlive 头带来的长连接影响测试结果的准确性。

三、测试代码

Voovan主类: AioPerformTest

public static void main(String[] args) throws IOException { AioServerSocket serverSocket = new AioServerSocket("0.0.0.0",28081,5000); serverSocket.filterChain().add(new StringFilter()); //配置过滤器 serverSocket.handler(new PerformTestHandler()); //配置业务类 serverSocket.messageSplitter(new PerformTestSpliter()); // 配置消息截断器 serverSocket.start(); //开启监听 } ........

Voovan业务类 PerformTestHandler:

public class PerformTestHandler implements IoHandler {

private String responseStr ;

public PerformTestHandler(){
    responseStr  =  "HTTP/1.1 200 OK\\r\\n" +
              "Date: Wed, 10 Jun 2009 11:22:58 GMT\\r\\n" +
              "Server: Microsoft-IIS/6.0\\r\\n" +
              "X-Powered-By: ASP.NET\\r\\n" +
              "Content-Length: 2\\r\\n" +
              "Content-Type: text/html\\r\\n" +
              "Cache-control: private\\r\\n\\r\\n"+
              "OK\\r\\n\\r\\n";
}

@Override
public Object onReceive(IoSession session, Object obj) {
    return responseStr;
}

@Override
public void onSent(IoSession session, Object obj) {
    session.close(); //关闭连接
}

........

}

Netty主类:

        netty 的业务累使用了内联类的方式写入到主类中了,以下代码的主体来自 netty 官网

package org.voovan.test.netty;

import io.netty.bootstrap.ServerBootstrap; import io.netty.buffer.ByteBuf; import io.netty.channel.*; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioServerSocketChannel;

/** * 类文字命名 * * @author helyho *

* Voovan Framework. * WebSite: https://github.com/helyho/Voovan * Licence: Apache v2 License */ public class NettyServer {

public static void main(String\[\] args) throws InterruptedException {
    EventLoopGroup bossGroup = new NioEventLoopGroup();
    EventLoopGroup workerGroup = new NioEventLoopGroup();
    try {
        ServerBootstrap b = new ServerBootstrap();
        b.group(bossGroup, workerGroup)
                .channel(NioServerSocketChannel.class)
                .childHandler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    public void initChannel(SocketChannel ch) throws Exception {
                        ch.pipeline().addLast(new DiscardServerHandler());
                    }
                })
                .option(ChannelOption.SO\_BACKLOG, 1024)
                .childOption(ChannelOption.SO\_KEEPALIVE, true);

        ChannelFuture f = b.bind(28080).sync();

        f.channel().closeFuture().sync();
    } finally {
        workerGroup.shutdownGracefully();
        bossGroup.shutdownGracefully();
    }
}

public static class DiscardServerHandler extends ChannelInboundHandlerAdapter {
    private String retVal;

    public DiscardServerHandler(){
        retVal = "HTTP/1.1 200 OK\\r\\n" +
                "Server: Voovan-WebServer/V1.0-RC-1\\r\\n" +
                "Connection: keep-alive\\r\\n" +
                "Content-Length: 2\\r\\n" +
                "Date: Thu, 05 Jan 2017 04:55:20 GMT\\r\\n" +
                "Content-Type: text/html\\r\\n"+
                "\\r\\n"+
                "OK\\r\\n\\r\\n";
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        //byte\[\] buffer = new byte\[((ByteBuf) msg).readableBytes()\];
        //((ByteBuf) msg).readBytes(buffer);
        //System.out.println(new String(buffer));
        //((ByteBuf) msg).clear();
        ((ByteBuf) msg).release();

        ByteBuf bf = ctx.alloc().buffer(retVal.length());
        bf.writeBytes(retVal.getBytes());
        ctx.writeAndFlush(bf);
        ctx.close();
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { // (4)
        // Close the connection when an exception is raised.
        cause.printStackTrace();
        ctx.close();
    }
}

}

以上完整的测试代码均在https://git.oschina.net/helyho/Voovan可以找到。

2017-07-01: 有网友质疑采用 ctx.alloc()方式没有从 Bytebuf 池中获取.经过调试截图如下:

        Netty与Voovan并发性能对比

PooledByteBufAllocator 对象是用来分配bytebuf池中非堆内存的,所以通ctx.alloc().buffer(retVal.length());的方式实际上是从bytebuf池中获取的 bytebuf。

四、代码比对

     首先请以初学者的角度来看待以上两段代码:

     1.Voovan 仅仅5行代码就可以完成对 Socket 的初始化工作,每行代码都有他独立的作用,结构清晰易懂.Netty 则最少需要8行代码来实现而且包含一个内联类,对于初学者来说可能理解有些难度多数初学者就是复制粘贴直接使用。

     2.Voovan 框架通过 PerformTestSpliter 消息分割类将消息转换成你期望的类型,这样在 IoHandler的实现类中的OnRecive 事件中可以直接使用.Netty 则需要在接收事件中进行处理.其实提供消息分割器的目的是为了优雅的解决粘包的问题。

     3.Voovan 和 Netty 都提供过滤链来对消息进行处理,但 Voovan 的过滤链是在消息分割类之后是可以有针对性的过滤一个有效且完成的报文。

     4.Voovan 和 Netty 都采用了自管理线程池能根据业务情况自动扩充线程池的大小。

    基于以上的代码做了一个简单的对比分析,两个框架在目的和功能上具有相通性,采用了不同的方法进行实现。

五、测试步骤

    1.首先进行5次预热,以保证框架的线程池管理达到最优状态

    2.接着,连续运行10次并记录结果。

    3.首先测试 Voovan 框架,测试完成后,等待3分钟后进行 Netty 框架的测试

    由于机器是虚拟机所以各项ab的参数设置的并不高,但好在两个测试程序运行在同样的环境中,并使用同样的参数进行测试,横向对比的结果还是可靠的

六、数据说话

下面我们来看看测试数据:

框架

第一次

第二次

第三次

第四次

第五次

第六次

第七次

第八次

第九次

第十次

平均

Voovan

18734.1

18573.97

18990.18

19394.95

18946.86

16115.36

14878.41

18410.92

21638.65

19569.17

18525.257

Netty

19382.62

18808.45

19255.73

12422.08

20086.29

20176.91

19604.92

19338.77

14812.84

16474.74

18036.335

通过上表可以看出:

Voovan 框架在10次测试后平均并发数据为: 18525

Netty 框架在10次测试后平均并发数据为: 18036

两个框架在并发性能上差异为:489,平均导10次每次的差异约为49,鉴于我们进行测试的总请求量是10000,这个差异可能是机器的各种不可控因素导致的差异,个人认为是可以忽略的.并不影响两个框架的整体性能。

性能曲线分析:

橙色的线条是 Netty 的数据

蓝色的线条是 Voovan 的数据

Netty与Voovan并发性能对比

可以看到 Voovan 的出现了一次较大的向下波动,Netty 出现了两次较大的向下波动.具体波动原因不得而知,推测可能是虚拟机较弱,因 GC 导致,由于只有10次测试的样本并所以不能通过较大的波动次数来评判框架的好坏。

总的来说两个框架在并发性能上应该是处于相同级别的,或者说都具有优秀的并发性能。

最后各位童鞋,你们怎么看呢?

有兴趣了解 Voovan 的朋友可以移步【Voovan】

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
4个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Wesley13 Wesley13
3年前
Voovan开发指南 (一) Socket服务端开发
Voovan框架介绍Voovan开源项目启动于2015年,始于自己在使用Netty和Mina时有较多难以理解的部分,同时在使用过程中遇到对粘包等问题的困扰,后来经过不断的对源码的学习以及对java异步通信的深入理解发现自java1.7以后JDK提供了更优秀的异步通信模型AIO,随后决定自己参照AIO模型重新造一个轮子。并
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
3年前
Voovan开发指南 (二) Socket客户端开发
Voovan框架介绍Voovan开源项目启动于2015年,始于自己在使用Netty和Mina时有较多难以理解的部分,同时在使用过程中遇到对粘包等问题的困扰,后来经过不断的对源码的学习以及对java异步通信的深入理解发现自java1.7以后JDK提供了更优秀的异步通信模型AIO,随后决定自己参照AIO模型重新造一个轮子。并
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
10个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这