zoukankan      html  css  js  c++  java
  • 【读后感】Netty 系列之 Netty 高性能之道

    【读后感】Netty 系列之 Netty 高性能之道 - 相比 Mina 怎样 ?

    太阳火神的漂亮人生 (http://blog.csdn.net/opengl_es)

    本文遵循“署名-非商业用途-保持一致”创作公用协议

    转载请保留此句:太阳火神的漂亮人生 -  本博客专注于 敏捷开发及移动和物联设备研究:iOS、Android、Html5、Arduino、pcDuino否则,出自本博客的文章拒绝转载或再转载,谢谢合作。


    【读后感】
    不知道这是什么节奏,或许人家早就春意盎然了。仅仅是我方才感觉到而已!

    研究 Mina 的过程中,偶然发现了 Netty,有人说 Mina 好久不更新了,而 Netty 一直很活跃。
    这仅仅能说。
    Netty 在快速的完好其中,
    至于 Mina。是没有后劲儿了呢,还是已经很完好了,不须要再继续更新,这个到是不得而知,
    至少眼下看。还不错,
    相比 Netty 的大数据、大并发、高效率。。。

    还有什么。请移步下文,自品其详吧!


    Netty系列之Netty高性能之道

    1. 背景

    1.1. 惊人的性能数据

    近期一个圈内朋友通过私信告诉我,通过使用Netty4 + Thrift压缩二进制编解码技术。他们实现了10W TPS(1K的复杂POJO对象)的跨节点远程服务调用。相比于传统基于Java序列化+BIO(同步堵塞IO)的通信框架,性能提升了8倍多。

    其实。我对这个数据并不感到吃惊,依据我5年多的NIO编程经验,通过选择合适的NIO框架,加上高性能的压缩二进制编解码技术。精心的设计Reactor线程模型,达到上述性能指标是全然有可能的。

    以下我们就一起来看下Netty是怎样支持10W TPS的跨节点远程服务调用的。在正式開始解说之前,我们先简介下Netty。

    1.2. Netty基础入门

    Netty是一个高性能、异步事件驱动的NIO框架,它提供了对TCP、UDP和文件传输的支持,作为一个异步NIO框架,Netty的全部IO操作都是异步非堵塞的,通过Future-Listener机制,用户能够方便的主动获取或者通过通知机制获得IO操作结果。

    作为当前最流行的NIO框架,Netty在互联网领域、大数据分布式计算领域、游戏行业、通信行业等获得了广泛的应用,一些业界著名的开源组件也基于Netty的NIO框架构建。

    2. Netty高性能之道

    2.1. RPC调用的性能模型分析

    2.1.1. 传统RPC调用性能差的三宗罪

    网络传输方式问题:传统的RPC框架或者基于RMI等方式的远程服务(过程)调用採用了同步堵塞IO,当client的并发压力或者网络时延增大之后,同步堵塞IO会因为频繁的wait导致IO线程常常性的堵塞,因为线程无法高效的工作,IO处理能力自然下降。

    以下,我们通过BIO通信模型图看下BIO通信的弊端:

    图2-1 BIO通信模型图

    採用BIO通信模型的服务端。通常由一个独立的Acceptor线程负责监听client的连接,接收到client连接之后为client连接创建一个新的线程处理请求消息,处理完毕之后,返回应答消息给client,线程销毁,这就是典型的一请求一应答模型。

    该架构最大的问题就是不具备弹性伸缩能力。当并发訪问量添加后,服务端的线程个数和并发訪问数成线性正比,因为线程是JAVA虚拟机很宝贵的系统资源,当线程数膨胀之后,系统的性能急剧下降,随着并发量的继续添加,可能会发生句柄溢出、线程堆栈溢出等问题。并导致server终于宕机。

    序列化方式问题:Java序列化存在例如以下几个典型问题:

    1) Java序列化机制是Java内部的一种对象编解码技术。无法跨语言使用;比如对于异构系统之间的对接,Java序列化后的码流须要能够通过其他语言反序列化成原始对象(副本),眼下很难支持。

    2) 相比于其他开源的序列化框架。Java序列化后的码流太大,不管是网络传输还是持久化到磁盘,都会导致额外的资源占用。

    3) 序列化性能差(CPU资源占用高)。

    线程模型问题:因为採用同步堵塞IO,这会导致每一个TCP连接都占用1个线程,因为线程资源是JVM虚拟机很宝贵的资源。当IO读写堵塞导致线程无法及时释放时。会导致系统性能急剧下降,严重的甚至会导致虚拟机无法创建新的线程。

    2.1.2. 高性能的三个主题

    1) 传输:用什么样的通道将数据发送给对方。BIO、NIO或者AIO,IO模型在很大程度上决定了框架的性能。

    2) 协议:採用什么样的通信协议,HTTP或者内部私有协议。协议的选择不同。性能模型也不同。

    相比于公有协议,内部私有协议的性能通常能够被设计的更优。

    3) 线程:数据报怎样读取?读取之后的编解码在哪个线程进行,编解码后的消息怎样派发,Reactor线程模型的不同。对性能的影响也很大。

    图2-2 RPC调用性能三要素

    2.2. Netty高性能之道

    2.2.1. 异步非堵塞通信

    在IO编程过程中。当须要同一时候处理多个client接入请求时。能够利用多线程或者IO多路复用技术进行处理。

    IO多路复用技术通过把多个IO的堵塞复用到同一个select的堵塞上,从而使得系统在单线程的情况下能够同一时候处理多个client请求。与传统的多线程/多进程模型比。I/O多路复用的最大优势是系统开销小。系统不须要创建新的额外进程或者线程,也不须要维护这些进程和线程的执行,减少了系统的维护工作量,节省了系统资源。

    JDK1.4提供了对非堵塞IO(NIO)的支持,JDK1.5_update10版本号使用epoll替代了传统的select/poll,极大的提升了NIO通信的性能。

    JDK NIO通信模型例如以下所看到的:

    图2-3 NIO的多路复用模型图

    与Socket类和ServerSocket类相相应。NIO也提供了SocketChannel和ServerSocketChannel两种不同的套接字通道实现。这两种新增的通道都支持堵塞和非堵塞两种模式。堵塞模式使用很easy。可是性能和可靠性都不好。非堵塞模式正好相反。

    开发者一般能够依据自己的须要来选择合适的模式,一般来说。低负载、低并发的应用程序能够选择同步堵塞IO以减少编程复杂度。可是对于高负载、高并发的网络应用,须要使用NIO的非堵塞模式进行开发。

    Netty架构依照Reactor模式设计和实现。它的服务端通信序列图例如以下:

    图2-3 NIO服务端通信序列图

    client通信序列图例如以下:

    图2-4 NIOclient通信序列图

    Netty的IO线程NioEventLoop因为聚合了多路复用器Selector。能够同一时候并发处理成百上千个clientChannel,因为读写操作都是非堵塞的,这就能够充分提升IO线程的执行效率。避免因为频繁IO堵塞导致的线程挂起。

    另外,因为Netty採用了异步通信模式,一个IO线程能够并发处理N个client连接和读写操作。这从根本上攻克了传统同步堵塞IO一连接一线程模型。架构的性能、弹性伸缩能力和可靠性都得到了极大的提升。

    2.2.2. 零拷贝

    许多用户都听说过Netty具有“零拷贝”功能,可是具体体如今哪里又说不清楚,本小节就具体对Netty的“零拷贝”功能进行解说。

    Netty的“零拷贝”主要体如今例如以下三个方面:

    1) Netty的接收和发送ByteBuffer採用DIRECT BUFFERS,使用堆外直接内存进行Socket读写,不须要进行字节缓冲区的二次拷贝。

    假设使用传统的堆内存(HEAP BUFFERS)进行Socket读写。JVM会将堆内存Buffer拷贝一份到直接内存中。然后才写入Socket中。相比于堆外直接内存。消息在发送过程中多了一次缓冲区的内存拷贝。

    2) Netty提供了组合Buffer对象,能够聚合多个ByteBuffer对象。用户能够像操作一个Buffer那样方便的对组合Buffer进行操作,避免了传统通过内存拷贝的方式将几个小Buffer合并成一个大的Buffer。

    3) Netty的文件传输採用了transferTo方法。它能够直接将文件缓冲区的数据发送到目标Channel,避免了传统通过循环write方式导致的内存拷贝问题。

    以下,我们对上述三种“零拷贝”进行说明,先看Netty 接收Buffer的创建:

    图2-5 异步消息读取“零拷贝”

    每循环读取一次消息,就通过ByteBufAllocator的ioBuffer方法获取ByteBuf对象,以下继续看它的接口定义:

    图2-6 ByteBufAllocator 通过ioBuffer分配堆外内存

    当进行Socket IO读写的时候。为了避免从堆内存拷贝一份副本到直接内存,Netty的ByteBuf分配器直接创建非堆内存避免缓冲区的二次拷贝,通过“零拷贝”来提升读写性能。

    以下我们继续看另外一种“零拷贝”的实现CompositeByteBuf,它对外将多个ByteBuf封装成一个ByteBuf,对外提供统一封装后的ByteBuf接口。它的类定义例如以下:

    图2-7 CompositeByteBuf类继承关系

    通过继承关系我们能够看出CompositeByteBuf实际就是个ByteBuf的包装器。它将多个ByteBuf组合成一个集合,然后对外提供统一的ByteBuf接口,相关定义例如以下:

    图2-8 CompositeByteBuf类定义

    加入ByteBuf,不须要做内存拷贝,相关代码例如以下:

    图2-9 新增ByteBuf的“零拷贝”

    最后,我们看下文件传输的“零拷贝”:

    图2-10 文件传输“零拷贝”

    Netty文件传输DefaultFileRegion通过transferTo方法将文件发送到目标Channel中,以下重点看FileChannel的transferTo方法,它的API DOC说明例如以下:

    图2-11 文件传输 “零拷贝”

    对于许多操作系统它直接将文件缓冲区的内容发送到目标Channel中,而不须要通过拷贝的方式。这是一种更加高效的传输方式,它实现了文件传输的“零拷贝”。

    2.2.3. 内存池

    随着JVM虚拟机和JIT即时编译技术的发展,对象的分配和回收是个很轻量级的工作。

    可是对于缓冲区Buffer,情况却稍有不同。特别是对于堆外直接内存的分配和回收。是一件耗时的操作。为了尽量重用缓冲区,Netty提供了基于内存池的缓冲区重用机制。以下我们一起看下Netty ByteBuf的实现:

    图2-12 内存池ByteBuf

    Netty提供了多种内存管理策略。通过在启动辅助类中配置相关參数,能够实现差异化的定制。

    以下通过性能測试,我们看下基于内存池循环利用的ByteBuf和普通ByteBuf的性能差异。

    用例一,使用内存池分配器创建直接内存缓冲区:

    图2-13 基于内存池的非堆内存缓冲区測试用例

    用例二,使用非堆内存分配器创建的直接内存缓冲区:

    图2-14 基于非内存池创建的非堆内存缓冲区測试用例

    各执行300万次,性能对照结果例如以下所看到的:

    图2-15 内存池和非内存池缓冲区写入性能对照

    性能測试表明。採用内存池的ByteBuf相比于朝生夕灭的ByteBuf,性能高23倍左右(性能数据与使用场景强相关)。

    以下我们一起简单分析下Netty内存池的内存分配:

    图2-16 AbstractByteBufAllocator的缓冲区分配

    继续看newDirectBuffer方法,我们发现它是一个抽象方法,由AbstractByteBufAllocator的子类负责具体实现。代码例如以下:

    图2-17 newDirectBuffer的不同实现

    代码跳转到PooledByteBufAllocator的newDirectBuffer方法,从Cache中获取内存区域PoolArena,调用它的allocate方法进行内存分配:

    图2-18 PooledByteBufAllocator的内存分配

    PoolArena的allocate方法例如以下:

    图2-18 PoolArena的缓冲区分配

    我们重点分析newByteBuf的实现。它相同是个抽象方法,由子类DirectArena和HeapArena来实现不同类型的缓冲区分配,因为測试用例使用的是堆外内存。

    图2-19 PoolArena的newByteBuf抽象方法

    因此重点分析DirectArena的实现:假设没有开启使用sun的unsafe,则

    图2-20 DirectArena的newByteBuf方法实现

    执行PooledDirectByteBuf的newInstance方法。代码例如以下:

    图2-21 PooledDirectByteBuf的newInstance方法实现

    通过RECYCLER的get方法循环使用ByteBuf对象,假设是非内存池实现,则直接创建一个新的ByteBuf对象。从缓冲池中获取ByteBuf之后,调用AbstractReferenceCountedByteBuf的setRefCnt方法设置引用计数器,用于对象的引用计数和内存回收(相似JVM垃圾回收机制)。

    2.2.4. 高效的Reactor线程模型

    常常使用的Reactor线程模型有三种,分别例如以下:

    1) Reactor单线程模型。

    2) Reactor多线程模型。

    3) 主从Reactor多线程模型

    Reactor单线程模型,指的是全部的IO操作都在同一个NIO线程上面完毕,NIO线程的职责例如以下:

    1) 作为NIO服务端。接收client的TCP连接;

    2) 作为NIOclient,向服务端发起TCP连接;

    3) 读取通信对端的请求或者应答消息。

    4) 向通信对端发送消息请求或者应答消息。

    Reactor单线程模型示意图例如以下所看到的:

    图2-22 Reactor单线程模型

    因为Reactor模式使用的是异步非堵塞IO,全部的IO操作都不会导致堵塞,理论上一个线程能够独立处理全部IO相关的操作。从架构层面看,一个NIO线程确实能够完毕其承担的职责。比如,通过Acceptor接收client的TCP连接请求消息。链路建立成功之后,通过Dispatch将相应的ByteBuffer派发到指定的Handler上进行消息解码。用户Handler能够通过NIO线程将消息发送给client。

    对于一些小容量应用场景,能够使用单线程模型。

    可是对于高负载、大并发的应用却不合适。主要原因例如以下:

    1) 一个NIO线程同一时候处理成百上千的链路,性能上无法支撑,即便NIO线程的CPU负荷达到100%,也无法满足海量消息的编码、解码、读取和发送;

    2) 当NIO线程负载过重之后,处理速度将变慢,这会导致大量client连接超时,超时之后往往会进行重发。这更加重了NIO线程的负载。终于会导致大量消息积压和处理超时,NIO线程会成为系统的性能瓶颈;

    3) 可靠性问题:一旦NIO线程意外跑飞,或者进入死循环。会导致整个系统通信模块不可用,不能接收和处理外部消息,造成节点故障。

    为了解决这些问题,演进出了Reactor多线程模型。以下我们一起学习下Reactor多线程模型。

    Rector多线程模型与单线程模型最大的差别就是有一组NIO线程处理IO操作,它的原理图例如以下:

    图2-23 Reactor多线程模型

    Reactor多线程模型的特点:

    1) 有专门一个NIO线程-Acceptor线程用于监听服务端,接收client的TCP连接请求。

    2) 网络IO操作-读、写等由一个NIO线程池负责,线程池能够採用标准的JDK线程池实现。它包括一个任务队列和N个可用的线程,由这些NIO线程负责消息的读取、解码、编码和发送;

    3) 1个NIO线程能够同一时候处理N条链路。可是1个链路仅仅相应1个NIO线程,防止发生并发操作问题。

    在绝大多数场景下,Reactor多线程模型都能够满足性能需求。可是,在极特殊应用场景中,一个NIO线程负责监听和处理全部的client连接可能会存在性能问题。比如百万client并发连接。或者服务端须要对client的握手消息进行安全认证,认证本身很损耗性能。在这类场景下,单独一个Acceptor线程可能会存在性能不足问题,为了解决性能问题,产生了第三种Reactor线程模型-主从Reactor多线程模型。

    主从Reactor线程模型的特点是:服务端用于接收client连接的不再是个1个单独的NIO线程。而是一个独立的NIO线程池。

    Acceptor接收到clientTCP连接请求处理完毕后(可能包括接入认证等)。将新创建的SocketChannel注冊到IO线程池(sub reactor线程池)的某个IO线程上,由它负责SocketChannel的读写和编解码工作。

    Acceptor线程池仅仅仅仅用于client的登陆、握手和安全认证。一旦链路建立成功,就将链路注冊到后端subReactor线程池的IO线程上,由IO线程负责兴许的IO操作。

    它的线程模型例如以下图所看到的:

    图2-24 Reactor主从多线程模型

    利用主从NIO线程模型,能够解决1个服务端监听线程无法有效处理全部client连接的性能不足问题。因此。在Netty的官方demo中,推荐使用该线程模型。

    其实,Netty的线程模型并非固定不变,通过在启动辅助类中创建不同的EventLoopGroup实例并通过适当的參数配置,就能够支持上述三种Reactor线程模型。

    正是因为Netty 对Reactor线程模型的支持提供了灵活的定制能力,所以能够满足不同业务场景的性能诉求。

    2.2.5. 无锁化的串行设计理念

    在大多数场景下,并行多线程处理能够提升系统的并发性能。可是。假设对于共享资源的并发訪问处理不当。会带来严重的锁竞争,这终于会导致性能的下降。为了尽可能的避免锁竞争带来的性能损耗,能够通过串行化设计,即消息的处理尽可能在同一个线程内完毕。期间不进行线程切换,这样就避免了多线程竞争和同步锁。

    为了尽可能提升性能,Netty採用了串行无锁化设计,在IO线程内部进行串行操作。避免多线程竞争导致的性能下降。表面上看,串行化设计似乎CPU利用率不高。并发程度不够。可是。通过调整NIO线程池的线程參数,能够同一时候启动多个串行化的线程并行执行。这样的局部无锁化的串行线程设计相比一个队列-多个工作线程模型性能更优。

    Netty的串行化设计工作原理图例如以下:

    图2-25 Netty串行化工作原理图

    Netty的NioEventLoop读取到消息之后,直接调用ChannelPipeline的fireChannelRead(Object msg),仅仅要用户不主动切换线程,一直会由NioEventLoop调用到用户的Handler,期间不进行线程切换。这样的串行化处理方式避免了多线程操作导致的锁的竞争。从性能角度看是最优的。

    2.2.6. 高效的并发编程

    Netty的高效并发编程主要体如今例如以下几点:

    1) volatile的大量、正确使用;

    2) CAS和原子类的广泛使用;

    3) 线程安全容器的使用;

    4) 通过读写锁提升并发性能。

    假设大家想了解Netty高效并发编程的细节。能够阅读之前我在微博分享的《多线程并发编程在 Netty 中的应用分析》。在这篇文章中对Netty的多线程技巧和应用进行了具体的介绍和分析。

    2.2.7. 高性能的序列化框架

    影响序列化性能的关键因素总结例如以下:

    1) 序列化后的码流大小(网络带宽的占用)。

    2) 序列化&反序列化的性能(CPU资源占用);

    3) 是否支持跨语言(异构系统的对接和开发语言切换)。

    Netty默认提供了对Google Protobuf的支持,通过扩展Netty的编解码接口。用户能够实现其他的高性能序列化框架,比如Thrift的压缩二进制编解码框架。

    以下我们一起看下不同序列化&反序列化框架序列化后的字节数组对照:

    图2-26 各序列化框架序列化码流大小对照

    从上图能够看出,Protobuf序列化后的码流仅仅有Java序列化的1/4左右。正是因为Java原生序列化性能表现太差,才催生出了各种高性能的开源序列化技术和框架(性能差仅仅是其中的一个原因,还有跨语言、IDL定义等其他因素)。

    2.2.8. 灵活的TCP參数配置能力

    合理设置TCP參数在某些场景下对于性能的提升能够起到显著的效果,比如SO_RCVBUF和SO_SNDBUF。假设设置不当。对性能的影响是很大的。以下我们总结下对性能影响比較大的几个配置项:

    1) SO_RCVBUF和SO_SNDBUF:通常建议值为128K或者256K;

    2) SO_TCPNODELAY:NAGLE算法通过将缓冲区内的小封包自己主动相连,组成较大的封包,阻止大量小封包的发送堵塞网络,从而提高网络应用效率。

    可是对于时延敏感的应用场景须要关闭该优化算法;

    3) 软中断:假设Linux内核版本号支持RPS(2.6.35以上版本号),开启RPS后能够实现软中断,提升网络吞吐量。RPS依据数据包的源地址,目的地址以及目的和源端口,计算出一个hash值。然后依据这个hash值来选择软中断执行的cpu。从上层来看。也就是说将每一个连接和cpu绑定,并通过这个hash值,来均衡软中断在多个cpu上。提升网络并行处理性能。

    Netty在启动辅助类中能够灵活的配置TCP參数。满足不同的用户场景。相关配置接口定义例如以下:

    图2-27 Netty的TCP參数配置定义

    2.3. 总结

    通过对Netty的架构和性能模型进行分析。我们发现Netty架构的高性能是被精心设计和实现的,得益于高质量的架构和代码,Netty支持10W TPS的跨节点服务调用并非件十分困难的事情。

    3. 作者简介

    李林锋。2007年毕业于东北大学,2008年进入华为公司从事高性能通信软件的设计和开发工作,有6年NIO设计和开发经验,精通Netty、Mina等NIO框架。Netty中国社区创始人。《Netty权威指南》作者。

    联系方式:新浪微博 Nettying 微信:Nettying


    感谢张龙对本文的审校,郭蕾对本文的策划。

    给InfoQ中文站投稿或者參与内容翻译工作,请邮件至editors@cn.infoq.com。也欢迎大家通过新浪微博(@InfoQ)或者腾讯微博(@InfoQ)关注我们。并与我们的编辑和其他读者朋友交流。

    告诉我们您的想法

    社区评论Watch Thread

    採用内存池的ByteBuf相比于朝生夕灭的ByteBuf,性能高23倍左右2014年5月30日 10:43 by Zhang Yuan

    之所以会这样,是因为ByteBUffer可能是从Native Memory分配出来的。


    所以分配和回收效率要远低于在Java Heap上的对象

    Good2014年5月31日 02:31 by 孙 奇辉

    顶,请继续多写!

    Re: 採用内存池的ByteBuf相比于朝生夕灭的ByteBuf。性能高23倍左右2014年5月31日 03:34 by 林锋 李

    是的。

    所以ByteBuffer的最优使用方法是:
    1)网络IO读写,直接与Socket打交道的使用直接内存;
    2)其他的用途的ByteBuffer。建议直接使用ByteBuffer。



    虽然基于堆内存分配的ByteBuffer性能已经很高。可是大块缓冲区的开辟和回收依旧很损耗性能,
    假设为每条消息都创建一个ByteBuffer。用完就马上回收,这不是一个好的策略,所以Netty开发和提供了ByteBuffer 内存池。

    Re: Good2014年5月31日 03:35 by 林锋 李

    谢谢鼓舞。大家对实战型的干货还是很渴求的。后面我会继续分享一些Netty的干货!

    2014年6月2日 11:21 by yan yan

    顶。继续期待兴许的文章。

    支持。须要深入了解netty2014年6月3日 10:30 by 刘 鹏

    支持。正准备升级netty从3到4.x

    Re: 支持,须要深入了解netty2014年6月3日 02:14 by 林锋 李

    从Netty 3升级到4还是有一些小麻烦,接口层面变更的有点多,无法前向兼容。架构也重构了下。添加了一些功能,改动了一些接口设计。

    升级中假设遇到什么疑难问题,也能够发邮件给我讨论下,我打算将来有空写一篇具体点的升级指南。

    Re: 赞2014年6月3日 02:18 by 林锋 李

    多谢。这些都是从实践中提炼出来的,所以对于自己的框架设计也有指导意义。

    node.js2014年6月3日 05:18 by he rn

    能否分析一下node.js是否也能做到这些?

    Re: node.js2014年6月4日 11:36 by 林锋 李

    这个能够由精通node.js的朋友们结合具体的性能数据和业务场景分析下。

    Ding2014年6月5日 01:27 by qingyi xu

    近期在做的一个远程RPC框架也是使用的 Netty 作为底层通信框架,当前使用Netty3性能已经很不错了,不知道升级Netty4后还有多大的惊喜!

    Re: Ding2014年6月5日 10:47 by 林锋 李

    能够这样说,有 "惊" 也有 "喜" ,相信你升级的时候就会有深切体会了。

    Re: node.js2014年6月5日 04:11 by zhang frank

    NodeJS採用的是“Reactor多线程模型”,即一个Acceptor线程负责接收请求。全部的IO操作由系统IO线程池完毕。而且Node针对不同平台的IO策略进行了优化,在windows下是用IOCP,而*nix下採用的是自己定义的IO线程池。

    Good2014年6月5日 07:28 by 穆 晓林

    1) SO_RCVBUF和SO_SNDBUF:通常建议值为128K或者256K;
    为什么要设置这么大的缓冲区呢,保持1000tcp链接能否够觉得(256k+128K)*1000的内存

    Re: node.js2014年6月5日 09:57 by 林锋 李

    嗯。IO线程模型几乎相同。只是Netty的IO线程模型能够由用户定制,支持多种模式。Netty也做了许多底层的优化。比如优化了Selector的选择键列表,它有一些性能开关。

    只是过分追求性能也是把双刃剑,比如Netty直接利用了一些JDK提供商相关的特性。如sun的Unsafe。

    Re: Good2014年6月5日 10:09 by 林锋 李

    这样设置的原因是为了有效的提升性能,具体的原因不解释了,你能够去了解下相关知识。
    关于内存的问题,有两种解决的方法:
    1) 依据实际的组网计算内存。JDK的内存上限未必一定要设置成4G或者8G;
    2) 内存缓冲区能够使用内存池,消费完放回池子,不是每条链路都一直占用这么多内存。



    实际上你说的问题不存在,原因例如以下:
    1. 假设是长连接,1000个TCP,意味着1000个节点的集群组网。国内除了阿里等互联网巨头。谁有这么大的集群组网?
    2. 假设是短连接。处理完毕链路就会关闭,资源释放,buffer是不会被某条链路长期持有的;
    3. 集群情况下,消息是分发到多个节点上的。
    4. 内存池的应用。

    实际上,你改小,依照这个公式,那我 10W个链路,100W个链路。内存还是不够,你改小也没用。

    不够就加内存呗。假设server内存不足。那就说明支持不了这么多链路。

    Re: Good2014年6月5日 10:09 by 林锋 李

    这样设置的原因是为了有效的提升性能。具体的原因不解释了。你能够去了解下相关知识。
    关于内存的问题,有两种解决的方法:
    1) 依据实际的组网计算内存。JDK的内存上限未必一定要设置成4G或者8G;
    2) 内存缓冲区能够使用内存池,消费完放回池子。不是每条链路都一直占用这么多内存。

    实际上你说的问题不存在。原因例如以下:
    1. 假设是长连接。1000个TCP,意味着1000个节点的集群组网,国内除了阿里等互联网巨头。谁有这么大的集群组网?
    2. 假设是短连接,处理完毕链路就会关闭,资源释放,buffer是不会被某条链路长期持有的。
    3. 集群情况下,消息是分发到多个节点上的。
    4. 内存池的应用。

    实际上,你改小,依照这个公式,那我 10W个链路,100W个链路。内存还是不够,你改小也没用。不够就加内存呗,假设server内存不足,那就说明支持不了这么多链路。

    Re: Good2014年6月5日 10:09 by 林锋 李

    这样设置的原因是为了有效的提升性能,具体的原因不解释了,你能够去了解下相关知识。
    关于内存的问题,有两种解决的方法:
    1) 依据实际的组网计算内存,JDK的内存上限未必一定要设置成4G或者8G。
    2) 内存缓冲区能够使用内存池,消费完放回池子,不是每条链路都一直占用这么多内存。

    实际上你说的问题不存在,原因例如以下:
    1. 假设是长连接,1000个TCP。意味着1000个节点的集群组网,国内除了阿里等互联网巨头,谁有这么大的集群组网?
    2. 假设是短连接。处理完毕链路就会关闭,资源释放。buffer是不会被某条链路长期持有的;
    3. 集群情况下,消息是分发到多个节点上的;
    4. 内存池的应用。

    实际上,你改小,依照这个公式,那我 10W个链路,100W个链路,内存还是不够,你改小也没用。不够就加内存呗。假设server内存不足,那就说明支持不了这么多链路。

    Re: Good2014年6月5日 10:09 by 林锋 李

    这样设置的原因是为了有效的提升性能。具体的原因不解释了。你能够去了解下相关知识。
    关于内存的问题。有两种解决的方法:
    1) 依据实际的组网计算内存,JDK的内存上限未必一定要设置成4G或者8G;
    2) 内存缓冲区能够使用内存池,消费完放回池子,不是每条链路都一直占用这么多内存。

    实际上你说的问题不存在,原因例如以下:
    1. 假设是长连接,1000个TCP,意味着1000个节点的集群组网。国内除了阿里等互联网巨头,谁有这么大的集群组网?
    2. 假设是短连接,处理完毕链路就会关闭,资源释放,buffer是不会被某条链路长期持有的。
    3. 集群情况下,消息是分发到多个节点上的;
    4. 内存池的应用。



    实际上,你改小。依照这个公式。那我 10W个链路,100W个链路,内存还是不够,你改小也没用。

    不够就加内存呗,假设server内存不足,那就说明支持不了这么多链路。

    Re: Good2014年6月5日 10:09 by 林锋 李

    这样设置的原因是为了有效的提升性能。具体的原因不解释了,你能够去了解下相关知识。
    关于内存的问题。有两种解决的方法:
    1) 依据实际的组网计算内存,JDK的内存上限未必一定要设置成4G或者8G;
    2) 内存缓冲区能够使用内存池,消费完放回池子。不是每条链路都一直占用这么多内存。



    实际上你说的问题不存在,原因例如以下:
    1. 假设是长连接,1000个TCP,意味着1000个节点的集群组网,国内除了阿里等互联网巨头,谁有这么大的集群组网?
    2. 假设是短连接,处理完毕链路就会关闭,资源释放,buffer是不会被某条链路长期持有的;
    3. 集群情况下,消息是分发到多个节点上的。
    4. 内存池的应用。

    实际上,你改小。依照这个公式。那我 10W个链路,100W个链路,内存还是不够,你改小也没用。不够就加内存呗。假设server内存不足,那就说明支持不了这么多链路。

    不好意思,刚才点击回复没有反应。我连续点了多次,没想到居然反复发了5份,杯具啊。

    2014年6月5日 10:41 by 林锋 李

    如题,也没有滤重功能......

    求推荐2014年6月9日 04:16 by qingyi xu

    博主有没有Netty4或者最新的5的学习书籍?Netty迁移中须要注意的。也包括Netty新版本号的新特性介绍的

    Re: 求推荐2014年6月11日 09:21 by 林锋 李

    网上有一些Netty 3到 Netty4的 API差异对照,感兴趣你能够看下。
    实际上,Netty 3升级到 4后架构进行了重构和优化。假设你想升级到4。还是须要认真学习下 Netty 4。
    眼下,系统介绍 Netty 4和 Netty5的书籍不多。眼下市场上有两本。



    1. Netty in Action: 英文版的。亚马逊能够买到。大概500元左右;
    2. Netty权威指南,6月份刚出版,在互动、亚马逊、当当、京东等能够预定。预计6月中下旬能发货。



    还有最后一个途径就是阅读源代码。这个须要具备三个条件:1. 有一定的NIO编程经验。2. 实际应用过Netty;3. 喜欢钻研源代码。

    对于“Reactor主从多线程模型”不太理解2014年6月20日 06:23 by 徐 小虾

    在上面的“Reactor主从多线程模型”中有几个线程池?会生成一个ServerSocketChannel还是多个ServerSocketChannel呢?

    做为client 使用socket短链接有必要使用NIO吗?2014年6月26日 12:22 by kai shen

    我刚接触网络编程不久,之前仅仅知道MINA。想问一下jetty更主流些吗? 还有我们系统接收socket报文后还要通过 socket 请求另外一个系统,然后依据请求结果返回给client请求的处理结果。

    採用的都是短链接,我们即做服务端又做client,服务端我们用mina client就用的jdk 的类。请问client有必要也用Nio吗?有什么优点吗?对于短链接来讲

    Re: 对于“Reactor主从多线程模型”不太理解2014年6月27日 11:47 by 林锋 李

    你的问题很好,看来你对NIO编程还是比較熟悉的。

    主从多线程模型中有1个线程池。仅仅有一个Acceptor线程用于SocketChannel接入。然后将其投递到本线程组其他的可用线程中处理兴许的接入认证、黑白名单校验、加解密、编解码等操作,因为这些操作须要一定的时间,因为由独立的线程负责,否则Acceptor线程无法及时处理其他的接入。

    这样的模型的ServerSocketChannel仅仅有一个。挂载在Acceptor线程上。



    该模型通常常使用于海量的client接入和推送系统中。

    Re: 做为client 使用socket短链接有必要使用NIO吗?2014年6月27日 11:50 by 林锋 李

    Jetty是轻量级的HTTP协议栈和Web容器,比較流行。

    不管服务端还是client,都须要操作IO,假设对方处理速度比較慢,常常超时,而你的超时时间又无法设置太短。就会导致你的client通信线程常常挂住,可靠性比較差。因此建议你使用NIO。

    Re: 採用内存池的ByteBuf相比于朝生夕灭的ByteBuf。性能高23倍左右2014年7月4日 10:37 by Jesse Q

    菜鸟一枚,请教一个问题:在堆外分配的内存是由full gc 来释放的?,那么假设堆的内存比較充足的时候长时间不触发full gc。是不是堆外的内存就被占用着,是不是意味着堆外的机器内存将会耗光?

    Re: 採用内存池的ByteBuf相比于朝生夕灭的ByteBuf,性能高23倍左右2014年7月4日 10:59 by 林锋 李

    这篇文章写得很清楚。建议你能够參考下:blog.csdn.net/xieyuooo/article/details/7547435



  • 相关阅读:
    HDU 1269 迷宫城堡
    HDU 4771 Stealing Harry Potter's Precious
    HDU 4772 Zhuge Liang's Password
    HDU 1690 Bus System
    HDU 2112 HDU Today
    HDU 1385 Minimum Transport Cost
    HDU 1596 find the safest road
    HDU 2680 Choose the best route
    HDU 2066 一个人的旅行
    AssetBundle管理机制(下)
  • 原文地址:https://www.cnblogs.com/tlnshuju/p/7122910.html
Copyright © 2011-2022 走看看