课程咨询: 400-996-5531 / 投诉建议: 400-111-8989
认真做教育 专心促就业
http编程是程序员在学习web前端编程开发技术的时候需要重点掌握的编程技术知识之一,而今天我们就通过案例分析来了解一下,http编程中序列化与零拷贝都有哪些特点。
一、序列化
JSON
Json进行序列化的额外空间开销比较大,对于大数据量的应用意味着更大的内存和磁盘开销
Json没有类型,像Java这种强类型语言,需要通过反射统一解决,所以性能不会太好
如果RPC框架选用Json序列化,服务之前传递的数据量要相对较小,否则会严重影响性能
Hessian
Hessian是动态类型、二进制、紧凑的,性能要比Json序列化高很多,并且生成的字节数也更小
相对于Json有非常好的兼容性和稳定性,所以Hessian更适合做RPC序列化协议
不支持Linked系列,LinkedHashMap,LinkedHashSet
Byte/Short反序列化时会变成Integer
Protobuf
序列化后的体积会比Json、Hessian小很多
IDL能清晰描述语义,保证应用程序之间的类型不会丢失
序列化/反序列化速度很快,无需通过反射获取类型
消息格式升级和兼容不错,可以做到向后兼容
Protostuff无需依赖IDL文件,可以直接对Java对象进行序列化操作,效率上和Protobuf差不多,生成的二进制格式和Protobuf完全相同,是一个Java版本的Protobuf序列化框架,但是也有不支持的情况
不支持null
不支持单纯的Map,List集合对象,需要包在对象里面
二、零拷贝
系统内核处理IO操作分为两个阶段——等待数据和拷贝数据
等待数据,系统内核等待网卡接收到数据后,将数据写入内核
拷贝数据,系统内核获取到数据后,将数据拷贝到用户进程空间中
读写操作
应用集成的每一次写操作,都会把数据写到用户空间的缓冲区中,再由CPU将数据拷贝到系统内核的缓冲区中,之后再由DMA将这份数据拷贝到网卡中,后由网卡发送出去
可以看到,一次写操作数据需要拷贝两次才能通过网卡发送出去,用户进程的读操作与写操作流程完全相反,数据同样会拷贝两次才能让应用程序读取到数据
应用进程的一次完整读写操作,都需要在用户空间与内核空间中来回拷贝,并且每次拷贝都需要CPU进行一次上下文切换(由用户进程切换到系统内核),这样很浪费CPU和性能
零拷贝
如何做到零拷贝
如果用户空间和内核空间都将数据写到一个地方,就不需要拷贝了,比如虚拟内存
Netty零拷贝
Netty的零拷贝主要针对于用户空间,偏向于数据操作的优化
传输过程中,RPC可能会把完整数据包拆分成好几个数据包,而对于数据包的分割和合并,是在用户空间完成的
在处理数据包的分割和合并时,也涉及到数据拷贝操作,Netty零拷贝就是为了解决这个问题,在用户空间对数据操作进行优化
Netty是如何对数据操作进行优化的
Netty提供了CompositeByteBuf类,它可以将多个ByteBuf合并为一个逻辑上的ByteBuf,避免各个ByteBuf之间的拷贝
ByteBuf支持slice操作,因此可以将ByteBuf分解为多个共享同一个存储区域的ByteBuf,避免内存拷贝
通过wrap操作,可以将byte[]数组、ByteBuf、ByteBuffer等包装成一个NettyByteBuf对象,进而避免拷贝操作
Netty框架中很多内部的ChannelHandler实现类,都是通过CompositeByteBuf、slice、wrap操作来处理TCP传输中的拆包和粘包问题
Netty如何解决用户空间和内核空间之间的数据拷贝问题
Netty的ByteBuffer可以采用DirectBuffers,使用对外直接内存进行Socket的读写操作,与虚拟内存实现效果是一样的
【免责声明】:本内容转载于网络,转载目的在于传递信息。文章内容为作者个人意见,本平台对文中陈述、观点保持中立,不对所包含内容的准确性、可靠性与完整性提供形式地保证。请读者仅作参考。更多内容请在707945861群中学习了解。