默认
发表评论 4
想开发IM:买成品怕坑?租第3方怕贵?找开源自已撸?别走弯路了... 找站长给点建议
Netty 4.x学习(一):ByteBuf详解
阅读(231932) | 评论(4) 收藏5 淘帖1 赞1

前言


程序员喜欢说一句话:「不要重复造轮子」,但是程序员又不太会践行这句话。这倒也不是坏事,程序员一般而言看他人代码都不会太爽,这也可能是导致程序员的世界有各式各样的轮子的原因吧。

ByteBuf与Java NIO Buffer


ByteBuf则是Java NIO Buffer的新轮子,官方列出了一些ByteBuf的特性:
  • 需要的话,可以自定义buffer类型;
  • 通过组合buffer类型,可实现透明的zero-copy;
  • 提供动态的buffer类型,如StringBuffer一样,容量是按需扩展;
  • 无需调用flip()方法;
  • 常常「often」比ByteBuffer快。

参考地址:Rich Buffer Data Structure

ByteBuf的实现类详解


ByteBuf提供了一些较为丰富的实现类,逻辑上主要分为两种:HeapByteBuf和DirectByteBuf,实现机制则分为两种:PooledByteBuf和UnpooledByteBuf,除了这些之外,Netty还实现了一些衍生ByteBuf(DerivedByteBuf),如:ReadOnlyByteBuf、DuplicatedByteBuf以及SlicedByteBuf。

ByteBuf实现类的类图如下:
Netty 4.x学习(一):ByteBuf详解_imgr.jpeg
HeapByteBuf和DirectByteBuf区别在于Buffer的管理方式:HeapByteBuf由Heap管理,Heap是Java堆的意思,内部实现直接采用byte[] array;DirectByteBuf使用是堆外内存,Direct应是采用Direct I/O之意,内部实现使用java.nio.DirectByteBuffoer。

PooledByteBuf和UnpooledByteBuf,UnpooledByteBuf实现就是普通的ByteBuf了,PooledByteBuf是4.x之后的新特性,稍后再说。

DerivedByteBuf是ByteBuf衍生类,实现采用装饰器模式对原有的ByteBuf进行了一些封装。ReadOnlyByteBuf是某个ByteBuf的只读引用;DuplicatedByteBuf是某个ByteBuf对象的引用;SlicedByteBuf是某个ByteBuf的部分内容。

SwappedByteBuf和CompositedByteBuf我觉得也算某种程度的衍生类吧,SwappedByteBuf封装了一个ByteBuf对象和ByteOrder对象,实现某个ByteBuf对象序列的逆转;CompositedByteBuf内部实现了一个ByteBuf列表,称之为组合ByteBuf,由于不懂相关的技术业务,无法理解该类的存在意义(官方解释:A user can save bulk memory copy operations using a composite buffer at the cost of relatively expensive random access.)。这两个类从逻辑上似乎完全可以继承于DerivedByteBuf,Trustin大神为啥如此设计呢?

简要的ByteBuf的实现机制


Netty 4.x学习(一):ByteBuf详解_bytebuf-priciple.png
ByteBuf有两个指针,readerIndex和writerIndex,用以控制buffer数组的读写。读逻辑较为简单,不考虑边界的情况下,就是 return array[readerIndex++]; 。

这里简要分析一下HeapByteBuf的读逻辑:
  1. AbstractByteBuf.ensureWritable(minWritableBytes);
  2. calculateNewCapacity(writerIndex + minWritableBytes)
  • 2.1 判断是否超过可写入容量 maxCapacity – writerIndex
  • 2.2 超过则抛异常,否则计算新容量 writerIndex + minWritableBytes
  • 2.3 判断是否超过设定阈值(4MB),超过每次增加按阈值(4MB)递增,否则
  • 2.4 初始大小为64字节(newCapacity),新容量超过newCapacity则翻倍,直到newCapacity大于新容量为止
  • 2.5 返回Min(newCapacity, maxCapacity);
  3. UnpooledHeapByteBuf.capacity(newCapacity);
  • 3.1 确保可访问,有一个引用计数的机制,引用计数为0,则抛异常(ensureAccessible)
  • 3.2 常规操作:判断是否越界
  • 3.3 如果newCapacity比原容量大,则直接创建新数组,并设置。否则
  • 3.4 如果readerIndex小于新容量,将readable bytes拷贝至新的数组,反之将readerIndex和writerIndex均设置为newCapacity。
  4. setByte(writerIndex++, value)
  • 4.1 确保可访问
  • 4.2 设置

ByteBuf的特殊机制


Pooled机制

4.x开发了Pooled Buffer,实现了一个高性能的buffer池,分配策略则是结合了buddy allocation和slab allocation的jemalloc变种,代码在io.netty.buffer.PoolArena。暂未深入研读。

官方说提供了以下优势:
  • 频繁分配、释放buffer时减少了GC压力;
  • 在初始化新buffer时减少内存带宽消耗(初始化时不可避免的要给buffer数组赋初始值);
  • 及时的释放direct buffer。

当然,官方也说了不保证没有内存泄露,所以默认情况下还是采用的UnpooledByteBufAllocator。5.x还处于beta版,看它的「new and* noteworthy」文档也没说有啥变化,哈哈哈哈,查看最新的「new and noteworthy」文档,PooledByteBufAllocator已经设置为默认的Allocator。

Reference Count机制

ByteBuf的生命周期管理引入了Reference Count的机制,感觉让我回到了CPP时代。可以通过简单的继承SimpleChannelInboundHandler实现自动释放reference count。SimpleChannelInboundHandler的事件方法如下,在消费完毕msg后,可以AutoRelease之:
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
    boolean release = true;
    try {
        if (acceptInboundMessage(msg)) {
            @SuppressWarnings("unchecked")
            I imsg = (I) msg;
            messageReceived(ctx, imsg);
        } else {
            release = false;
            ctx.fireChannelRead(msg);
        }
    } finally {
        if (autoRelease && release) {
            ReferenceCountUtil.release(msg);
        }
    }
}

这一小节可以单独拎出来和Pooled放在一起深入研读研读,有兴趣的可以先看看官方文档:Reference counted objects

Zero Copy机制

Zero-copy与传统意义的zero-copy不太一样。传统的zero-copy是IO传输过程中,数据无需中内核态到用户态、用户态到内核态的数据拷贝,减少拷贝次数。而Netty的zero-copy则是完全在用户态,或者说传输层的zero-copy机制,可以参考下图。由于协议传输过程中,通常会有拆包、合并包的过程,一般的做法就是System.arrayCopy了,但是Netty通过ByteBuf.slice以及Unpooled.wrappedBuffer等方法拆分、合并Buffer无需拷贝数据。

如何实现zero-copy的呢。slice实现就是创建一个SlicedByteBuf对象,将this对象,以及相应的数据指针传入即可,wrappedBuffer实现机制类似。
Netty 4.x学习(一):ByteBuf详解_bytebuf-combine-slice-buffer.png
参考地址:http://netty.io/3.5/guide/#architecture.5.4

全站即时通讯技术资料分类


[1] 网络编程基础资料:
《TCP/IP详解 - 第11章·UDP:用户数据报协议》
《TCP/IP详解 - 第17章·TCP:传输控制协议》
《TCP/IP详解 - 第18章·TCP连接的建立与终止》
《TCP/IP详解 - 第21章·TCP的超时与重传》
《技术往事:改变世界的TCP/IP协议(珍贵多图、手机慎点)》
《通俗易懂-深入理解TCP协议(上):理论基础》
《通俗易懂-深入理解TCP协议(下):RTT、滑动窗口、拥塞处理》
《理论经典:TCP协议的3次握手与4次挥手过程详解》
《理论联系实际:Wireshark抓包分析TCP 3次握手、4次挥手过程》
《计算机网络通讯协议关系图(中文珍藏版)》
《UDP中一个包的大小最大能多大?》
《P2P技术详解(一):NAT详解——详细原理、P2P简介》
《P2P技术详解(二):P2P中的NAT穿越(打洞)方案详解》
《P2P技术详解(三):P2P技术之STUN、TURN、ICE详解》
《通俗易懂:快速理解P2P技术中的NAT穿透原理》
《高性能网络编程(一):单台服务器并发TCP连接数到底可以有多少》
《高性能网络编程(二):上一个10年,著名的C10K并发连接问题》
《高性能网络编程(三):下一个10年,是时候考虑C10M并发问题了》
《高性能网络编程(四):从C10K到C10M高性能网络应用的理论探索》
《不为人知的网络编程(一):浅析TCP协议中的疑难杂症(上篇)》
《不为人知的网络编程(二):浅析TCP协议中的疑难杂症(下篇)》
《不为人知的网络编程(三):关闭TCP连接时为什么会TIME_WAIT、CLOSE_WAIT》
《不为人知的网络编程(四):深入研究分析TCP的异常关闭》
《不为人知的网络编程(五):UDP的连接性和负载均衡》
《不为人知的网络编程(六):深入地理解UDP协议并用好它》
《网络编程懒人入门(一):快速理解网络通信协议(上篇)》
《网络编程懒人入门(二):快速理解网络通信协议(下篇)》
《网络编程懒人入门(三):快速理解TCP协议一篇就够》
《网络编程懒人入门(四):快速理解TCP和UDP的差异》
《Netty干货分享:京东京麦的生产级TCP网关技术实践总结》
>> 更多同类文章 ……

[2] NIO异步网络编程资料:
《Java新一代网络编程模型AIO原理及Linux系统AIO介绍》
《有关“为何选择Netty”的11个疑问及解答》
《开源NIO框架八卦——到底是先有MINA还是先有Netty?》
《选Netty还是Mina:深入研究与对比(一)》
《选Netty还是Mina:深入研究与对比(二)》
《NIO框架入门(一):服务端基于Netty4的UDP双向通信Demo演示》
《NIO框架入门(二):服务端基于MINA2的UDP双向通信Demo演示》
《NIO框架入门(三):iOS与MINA2、Netty4的跨平台UDP双向通信实战》
《NIO框架入门(四):Android与MINA2、Netty4的跨平台UDP双向通信实战》
《Netty 4.x学习(一):ByteBuf详解》
《Netty 4.x学习(二):Channel和Pipeline详解》
《Netty 4.x学习(三):线程模型详解》
《Apache Mina框架高级篇(一):IoFilter详解》
《Apache Mina框架高级篇(二):IoHandler详解》
《MINA2 线程原理总结(含简单测试实例)》
《Apache MINA2.0 开发指南(中文版)[附件下载]》
《MINA、Netty的源代码(在线阅读版)已整理发布》
《解决MINA数据传输中TCP的粘包、缺包问题(有源码)》
《解决Mina中多个同类型Filter实例共存的问题》
《实践总结:Netty3.x升级Netty4.x遇到的那些坑(线程篇)》
《实践总结:Netty3.x VS Netty4.x的线程模型》
《详解Netty的安全性:原理介绍、代码演示(上篇)》
《详解Netty的安全性:原理介绍、代码演示(下篇)》
《详解Netty的优雅退出机制和原理》
《NIO框架详解:Netty的高性能之道》
《Twitter:如何使用Netty 4来减少JVM的GC开销(译文)》
《绝对干货:基于Netty实现海量接入的推送服务技术要点》
《Netty干货分享:京东京麦的生产级TCP网关技术实践总结》
>> 更多同类文章 ……

[3] 有关IM/推送的通信格式、协议的选择:
《简述传输层协议TCP和UDP的区别》
《为什么QQ用的是UDP协议而不是TCP协议?》
《移动端即时通讯协议选择:UDP还是TCP?》
《如何选择即时通讯应用的数据传输格式》
《强列建议将Protobuf作为你的即时通讯应用数据传输格式》
《全方位评测:Protobuf性能到底有没有比JSON快5倍?》
《移动端IM开发需要面对的技术问题(含通信协议选择)》
《简述移动端IM开发的那些坑:架构设计、通信协议和客户端》
《理论联系实际:一套典型的IM通信协议设计详解》
《58到家实时消息系统的协议设计等技术实践分享》
《详解如何在NodeJS中使用Google的Protobuf》
>> 更多同类文章 ……

[4] 有关IM/推送的心跳保活处理:
《应用保活终极总结(一):Android6.0以下的双进程守护保活实践》
《应用保活终极总结(二):Android6.0及以上的保活实践(进程防杀篇)》
《应用保活终极总结(三):Android6.0及以上的保活实践(被杀复活篇)》
《Android进程保活详解:一篇文章解决你的所有疑问》
《Android端消息推送总结:实现原理、心跳保活、遇到的问题等》
《深入的聊聊Android消息推送这件小事》
《为何基于TCP协议的移动端IM仍然需要心跳保活机制?》
《微信团队原创分享:Android版微信后台保活实战分享(进程保活篇)》
《微信团队原创分享:Android版微信后台保活实战分享(网络保活篇)》
《移动端IM实践:实现Android版微信的智能心跳机制》
《移动端IM实践:WhatsApp、Line、微信的心跳策略分析》
>> 更多同类文章 ……

[5] 有关WEB端即时通讯开发:
《新手入门贴:史上最全Web端即时通讯技术原理详解》
《Web端即时通讯技术盘点:短轮询、Comet、Websocket、SSE》
《SSE技术详解:一种全新的HTML5服务器推送事件技术》
《Comet技术详解:基于HTTP长连接的Web端实时通信技术》
《新手快速入门:WebSocket简明教程》
《WebSocket详解(一):初步认识WebSocket技术》
《WebSocket详解(二):技术原理、代码演示和应用案例》
《WebSocket详解(三):深入WebSocket通信协议细节》
《socket.io实现消息推送的一点实践及思路》
《LinkedIn的Web端即时通讯实践:实现单机几十万条长连接》
《Web端即时通讯技术的发展与WebSocket、Socket.io的技术实践》
《Web端即时通讯安全:跨站点WebSocket劫持漏洞详解(含示例代码)》
《开源框架Pomelo实践:搭建Web端高性能分布式IM聊天服务器》
《使用WebSocket和SSE技术实现Web端消息推送》
《详解Web端通信方式的演进:从Ajax、JSONP 到 SSE、Websocket》
>> 更多同类文章 ……

[6] 有关IM架构设计:
《浅谈IM系统的架构设计》
《简述移动端IM开发的那些坑:架构设计、通信协议和客户端》
《一套海量在线用户的移动端IM架构设计实践分享(含详细图文)》
《一套原创分布式即时通讯(IM)系统理论架构方案》
《从零到卓越:京东客服即时通讯系统的技术架构演进历程》
《蘑菇街即时通讯/IM服务器开发之架构选择》
《腾讯QQ1.4亿在线用户的技术挑战和架构演进之路PPT》
《微信后台基于时间序的海量数据冷热分级架构设计实践》
《微信技术总监谈架构:微信之道——大道至简(演讲全文)》
《如何解读《微信技术总监谈架构:微信之道——大道至简》》
《快速裂变:见证微信强大后台架构从0到1的演进历程(一)》
《17年的实践:腾讯海量产品的技术方法论》
《移动端IM中大规模群消息的推送如何保证效率、实时性?》
《现代IM系统中聊天消息的同步和存储方案探讨》
>> 更多同类文章 ……

[7] 有关IM安全的文章:
《即时通讯安全篇(一):正确地理解和使用Android端加密算法》
《即时通讯安全篇(二):探讨组合加密算法在IM中的应用》
《即时通讯安全篇(三):常用加解密算法与通讯安全讲解》
《即时通讯安全篇(四):实例分析Android中密钥硬编码的风险》
《即时通讯安全篇(五):对称加密技术在Android平台上的应用实践》
《即时通讯安全篇(六):非对称加密技术的原理与应用实践》
《传输层安全协议SSL/TLS的Java平台实现简介和Demo演示》
《理论联系实际:一套典型的IM通信协议设计详解(含安全层设计)》
《微信新一代通信安全解决方案:基于TLS1.3的MMTLS详解》
《来自阿里OpenIM:打造安全可靠即时通讯服务的技术实践分享》
《简述实时音视频聊天中端到端加密(E2EE)的工作原理》
《移动端安全通信的利器——端到端加密(E2EE)技术详解》
《Web端即时通讯安全:跨站点WebSocket劫持漏洞详解(含示例代码)》
《通俗易懂:一篇掌握即时通讯的消息传输安全原理》
>> 更多同类文章 ……

[8] 有关实时音视频开发:
《专访微信视频技术负责人:微信实时视频聊天技术的演进》
《即时通讯音视频开发(一):视频编解码之理论概述》
《即时通讯音视频开发(二):视频编解码之数字视频介绍》
《即时通讯音视频开发(三):视频编解码之编码基础》
《即时通讯音视频开发(四):视频编解码之预测技术介绍》
《即时通讯音视频开发(五):认识主流视频编码技术H.264》
《即时通讯音视频开发(六):如何开始音频编解码技术的学习》
《即时通讯音视频开发(七):音频基础及编码原理入门》
《即时通讯音视频开发(八):常见的实时语音通讯编码标准》
《即时通讯音视频开发(九):实时语音通讯的回音及回音消除概述》
《即时通讯音视频开发(十):实时语音通讯的回音消除技术详解》
《即时通讯音视频开发(十一):实时语音通讯丢包补偿技术详解》
《即时通讯音视频开发(十二):多人实时音视频聊天架构探讨》
《即时通讯音视频开发(十三):实时视频编码H.264的特点与优势》
《即时通讯音视频开发(十四):实时音视频数据传输协议介绍》
《即时通讯音视频开发(十五):聊聊P2P与实时音视频的应用情况》
《即时通讯音视频开发(十六):移动端实时音视频开发的几个建议》
《即时通讯音视频开发(十七):视频编码H.264、VP8的前世今生》
《实时语音聊天中的音频处理与编码压缩技术简述》
《网易视频云技术分享:音频处理与压缩技术快速入门》
《学习RFC3550:RTP/RTCP实时传输协议基础知识》
《简述开源实时音视频技术WebRTC的优缺点》
《良心分享:WebRTC 零基础开发者教程(中文)》
《开源实时音视频技术WebRTC中RTP/RTCP数据传输协议的应用》
《基于RTMP数据传输协议的实时流媒体技术研究(论文全文)》
《声网架构师谈实时音视频云的实现难点(视频采访)》
《浅谈开发实时视频直播平台的技术要点》
《还在靠“喂喂喂”测试实时语音通话质量?本文教你科学的评测方法!》
《实现延迟低于500毫秒的1080P实时音视频直播的实践分享》
《移动端实时视频直播技术实践:如何做到实时秒开、流畅不卡》
《如何用最简单的方法测试你的实时音视频方案》
《技术揭秘:支持百万级粉丝互动的Facebook实时视频直播》
《简述实时音视频聊天中端到端加密(E2EE)的工作原理》
《移动端实时音视频直播技术详解(一):开篇》
《移动端实时音视频直播技术详解(二):采集》
《移动端实时音视频直播技术详解(三):处理》
《移动端实时音视频直播技术详解(四):编码和封装》
《移动端实时音视频直播技术详解(五):推流和传输》
《移动端实时音视频直播技术详解(六):延迟优化》
《理论联系实际:实现一个简单地基于HTML5的实时视频直播》
《IM实时音视频聊天时的回声消除技术详解》
《浅谈实时音视频直播中直接影响用户体验的几项关键技术指标》
《如何优化传输机制来实现实时音视频的超低延迟?》
《首次披露:快手是如何做到百万观众同场看直播仍能秒开且不卡顿的?》
《实时通信RTC技术栈之:视频编解码》
《开源实时音视频技术WebRTC在Windows下的简明编译教程》
《Android直播入门实践:动手搭建一套简单的直播系统》
>> 更多同类文章 ……

[9] IM开发综合文章:
《移动端IM中大规模群消息的推送如何保证效率、实时性?》
《移动端IM开发需要面对的技术问题》
《开发IM是自己设计协议用字节流好还是字符流好?》
《请问有人知道语音留言聊天的主流实现方式吗?》
《IM消息送达保证机制实现(一):保证在线实时消息的可靠投递》
《IM消息送达保证机制实现(二):保证离线消息的可靠投递》
《如何保证IM实时消息的“时序性”与“一致性”?》
《一个低成本确保IM消息时序的方法探讨》
《IM单聊和群聊中的在线状态同步应该用“推”还是“拉”?》
《IM群聊消息如此复杂,如何保证不丢不重?》
《谈谈移动端 IM 开发中登录请求的优化》
《移动端IM登录时拉取数据如何作到省流量?》
《浅谈移动端IM的多点登陆和消息漫游原理》
《完全自已开发的IM该如何设计“失败重试”机制?》
《通俗易懂:基于集群的移动端IM接入层负载均衡方案分享》
《微信对网络影响的技术试验及分析(论文全文)》
《即时通讯系统的原理、技术和应用(技术论文)》
《开源IM工程“蘑菇街TeamTalk”的现状:一场有始无终的开源秀》
《QQ音乐团队分享:Android中的图片压缩技术详解(上篇)》
《QQ音乐团队分享:Android中的图片压缩技术详解(下篇)》
《腾讯原创分享(一):如何大幅提升移动网络下手机QQ的图片传输速度和成功率》
《腾讯原创分享(二):如何大幅压缩移动网络下APP的流量消耗(上篇)》
《腾讯原创分享(二):如何大幅压缩移动网络下APP的流量消耗(下篇)》
《如约而至:微信自用的移动端IM网络层跨平台组件库Mars已正式开源》
《基于社交网络的Yelp是如何实现海量用户图片的无损压缩的?》
>> 更多同类文章 ……

[10] 开源移动端IM技术框架资料:
《开源移动端IM技术框架MobileIMSDK:快速入门》
《开源移动端IM技术框架MobileIMSDK:常见问题解答》
《开源移动端IM技术框架MobileIMSDK:压力测试报告》
>> 更多同类文章 ……

[11] 有关推送技术的文章:
《iOS的推送服务APNs详解:设计思路、技术原理及缺陷等》
《信鸽团队原创:一起走过 iOS10 上消息推送(APNS)的坑》
《Android端消息推送总结:实现原理、心跳保活、遇到的问题等》
《扫盲贴:认识MQTT通信协议》
《一个基于MQTT通信协议的完整Android推送Demo》
《IBM技术经理访谈:MQTT协议的制定历程、发展现状等》
《求教android消息推送:GCM、XMPP、MQTT三种方案的优劣》
《移动端实时消息推送技术浅析》
《扫盲贴:浅谈iOS和Android后台实时消息推送的原理和区别》
《绝对干货:基于Netty实现海量接入的推送服务技术要点》
《移动端IM实践:谷歌消息推送服务(GCM)研究(来自微信)》
《为何微信、QQ这样的IM工具不使用GCM服务推送消息?》
《极光推送系统大规模高并发架构的技术实践分享》
《从HTTP到MQTT:一个基于位置服务的APP数据通信实践概述》
《魅族2500万长连接的实时消息推送架构的技术实践分享》
《专访魅族架构师:海量长连接的实时消息推送系统的心得体会》
《深入的聊聊Android消息推送这件小事》
《基于WebSocket实现Hybrid移动应用的消息推送实践(含代码示例)》
《一个基于长连接的安全可扩展的订阅/推送服务实现思路》
《实践分享:如何构建一套高可用的移动端消息推送系统?》
《Go语言构建千万级在线的高并发消息推送系统实践(来自360公司)》
《腾讯信鸽技术分享:百亿级实时消息推送的实战经验》
《百万在线的美拍直播弹幕系统的实时推送技术实践之路》
>> 更多同类文章 ……

[12] 更多即时通讯技术好文分类:
http://www.52im.net/forum.php?mod=collection&op=all

(原文链接:http://hongweiyi.com/2014/01/netty-4-x-bytebuf/)

即时通讯网 - 即时通讯开发者社区! 来源: - 即时通讯开发者社区!

上一篇:Netty 4.x学习(三):线程模型详解▪下一篇:Netty 4.x学习(二):Channel和Pipeline详解

本帖已收录至以下技术专辑

推荐方案
评论 4
挺好的,好有深度啊
好文章 学习了

好文章 学习了
签名: 敲代码了
蛮好的文章,赞
签名: 春节快乐
打赏楼主 ×
使用微信打赏! 使用支付宝打赏!

返回顶部