Netty

作者:加菲猫 2018-06-19 261 0

BIO、NIO、AIO

BIO:同步阻塞。一个连接一个线程,线程开销大。

NIO:同步非阻塞。一个请求一个线程,请求都被注册到多路复用器上,有 I/O 请求时才启动一个线程。

AIO:异步非阻塞。一个有效请求一个线程。

io 和 nio 的区别

io nio
面向流(只能顺序从流中读取数据) 面向块(数据先被读写进块中,然后根据需要读取指定位置的数据)
阻塞 IO 阻塞 / 非阻塞 IO

阻塞 IO:读取完全部数据,才能执行下边的操作。 非阻塞 IO:读取数据时,可以进行下边的操作,再回来查看数据是否完整。

Netty 的各大组件

Channel:基础的 IO 操作,如绑定、连接、读写等。

EventLoop:定义了处理在连接过程中发生的事件的核心抽象。

ChannelFuture:存储了之后执行的操作的结果并且无法预测操作何时被执行,提交至 Channel 的操作按照被唤醒的顺序被执行。

Netty 的线程模型

单线程模型:多个客户端,一个事件分解器,多个 Handler。

  • 用户发起IO操作到事件分离器。

  • 事件分离器调用相应的处理器处理事件。

  • 事件处理完成,事件分离器获得控制权,继续相应处理。

多线程模型:多个客户端,线程池,多个 Handler。

主从多线程模型:多个客户端,主线程池,子线程池,多个 Handler。

  • Acceptor(boss 线程池)不再是一个单独的NIO线程,而是一个独立的NIO线程池。

  • Acceptor(boss 线程池)处理完后,将事件注册到IO线程池(work 线程池)的某个线程上。

  • IO 线程继续完成后续的 IO 操作。

  • Acceptor(boss 线程池)仅仅完成登录、握手和安全认证等操作,IO(work 线程池)操作和业务处理依然在后面的从线程中完成。

TCP 粘包 / 拆包的原因及解决方法

粘包:发送端发送了 2 个包,接收端只收到一个,由于 TCP 是不会丢包的,所以这一个包中包含了 2 个包的内容,但是接收端无法判断 2 个包的界限。

拆包:发送端发送了 2 个包,接收端也收到了 2 个包,但是这 2 个包的内容,不是多就是少。

原因:

  • 要发送的数据大于 TCP 发送缓冲区剩余空间大小,将会发生拆包。

  • 待发送数据大于 MSS(最大报文长度),TCP在传输前将进行拆包。

  • 要发送的数据小于 TCP 发送缓冲区的大小,TCP 将多次写入缓冲区的数据一次发送出去,将会发生粘包。

  • 接收数据端的应用层没有及时读取接收缓冲区中的数据,将发生粘包。

解决办法:

  • 发送端给每个数据包添加包首部,首部中应该至少包含数据包的长度,这样接收端在接收到数据后,通过读取包首部的长度字段,便知道每一个数据包的实际长度了。

  • 发送端将每个数据包封装为固定长度(不够的可以通过补 0 填充),这样接收端每次从接收缓冲区中读取固定长度的数据就自然而然的把每个数据包拆分开来。

  • 可以在数据包之间设置边界,如添加特殊符号,这样,接收端通过这个边界就可以将不同的数据包拆分开。

有哪几种序列化协议?它们的使用场景分别是什么?

XML:常用的序列化和反序列化协议。

优点:

  • 人机可读性好。

  • 可指定元素或特性的名称。

缺点:

  • 序列化数据只包含数据本身以及类的结构,不包括类型标识和程序集信息。

  • 类必须有一个将由 XmlSerializer 序列化的默认构造函数。

  • 只能序列化公共属性和字段。

  • 不能序列化方法。

  • 文件庞大,文件格式复杂,传输占带宽。

使用场景:

  • 当做配置文件存储数据。

  • 实时数据转换。

JSON:轻量级的数据交换格式。

优点:

  • 前后兼容性高。

  • 数据格式比较简单,易于读写。

  • 序列化后数据较小,可扩展性好,兼容性好。

  • 与XML相比,其协议比较简单,解析速度比较快。

缺点:

  • 数据的描述性比XML差。

  • 不适合性能要求为ms级别的情况。

  • 额外空间开销比较大。

适用场景(可替代 XML):

  • 跨防火墙访问。

  • 可调式性要求高的情况。

  • 基于Web browser的Ajax请求。

  • 传输数据量相对小,实时性要求相对低(例如秒级别)的服务。

Fastjson:高性能功能完善的 JSON 库。

优点:

  • 接口简单易用。

  • 目前java语言中最快的json库。

缺点:

  • 过于注重快,而偏离了“标准”及功能性。

  • 代码质量不高,文档不全。

适用场景:

  • 协议交互。

  • Web输出。

  • Android 客户端。

Thrift:RPC 框架。

优点:

  • 序列化后的体积小, 速度快。

  • 支持多种语言和丰富的数据类型。

  • 对于数据字段的增删具有较强的兼容性。

  • 支持二进制压缩编码。

缺点:

  • 使用者较少。

  • 跨防火墙访问时,不安全。

  • 不具有可读性,调试代码时相对困难。

  • 不能与其他传输层协议共同使用(例如 HTTP)。

  • 无法支持向持久层直接读写数据,即不适合做数据持久化序列化协议。

适用场景:

  • 分布式系统的RPC解决方案。

Avro:Apache Hadoop 的一个子项目。

优点:

  • 支持丰富的数据类型。

  • 简单的动态语言结合功能。

  • 具有自我描述属性。

  • 提高了数据解析速度。

  • 快速可压缩的二进制数据形式。

  • 可以实现远程过程调用RPC。

  • 支持跨编程语言实现。

缺点:

  • 对于习惯于静态类型语言的用户不直观。

适用场景:

  • 在 Hadoop 中做 Hive、Pig 和 MapReduce 的持久化数据格式。

Netty 的零拷贝是怎样实现的?

操作数据时, 不需要将数据 buffer 从一个内存区域拷贝到另一个内存区域。因为少了一次内存的拷贝,CPU 的效率就得到的提升。

ByteBuffer 由 ChannelConfig 分配,而C hannelConfig 创建 ByteBufAllocator 默认使用 Direct Buffer,这就避免了读写数据的二次内存拷贝问题,从而实现了读写 Socket 的零拷贝功能,

Netty 的高性能表现在哪些方面?

https://blog.csdn.net/zero__007/article/details/51326591

发表评论

下一篇: 上一篇: