chapter22 高性能之道
1、RPC调用性能模型分析
传统RPC调用性能差三宗罪
- 网络传输方式问题,基于RMI等方式,同步阻塞IO
- 序列化性能差
- 线程模型问题,BIO,导致TCP连接占用一个线程。
IO通信性能三原则
- 传输:用什么样的通道将数据发送给对方
- 协议
- 线程:数据报如何读取,读取之后的编码在哪个线程进行,消息如何派发等
2、Netty高性能之道
- 异步非阻塞通信
- 高效的Reactor线程模型
- 单线程模型
EventLoopGroup reactor = new NioEventLoopGroup(1);
ServerBootStrap b = new ServerBootStrap();
b.group(reactor,reactor);
- 多线程模型
EventLoopGroup reactor = new NioEventLoopGroup(1);
EventLoopGroup IOreactor = new NioEventLoopGroup();
ServerBootStrap b = new ServerBootStrap();
b.group(reactor,IOreactor);
- 主从Reactor多线程模型
EventLoopGroup reactor = new NioEventLoopGroup(); // 默认cpu*2
EventLoopGroup IOreactor = new NioEventLoopGroup();
ServerBootStrap b = new ServerBootStrap();
b.group(reactor,IOreactor);
3、无锁化的串行设计
- 通过调整NIO线程池参数,可以同时启动多个串行化的线程并运行
4、高效的并发编程
- volatile的大量、正确使用
- CAS和原子类的广泛使用
- 线程安全容器的使用
- 通过读写锁提升并发性能
5、高性能的序列化框架
- Netty默认提供了google的protobuf二进制序列化框架
- 影响序列化性能的关键因素:
- 序列化后的码流大小
- 序列化、反序列化的性能(cpu资源占用)
- 是否支持跨语言
6、零拷贝
- Netty的零拷贝主要体现在三个方面:
- Netty的接收和发送ByteBuffer采用DIRECT BUFFERS
- CompositeByteBuf,将多个ByteBuf封装成一个ByteBuf,对外提供了统一接口,添加ByteBuf不需要做内存拷贝
- 文件传输,直接将文件缓冲区的内容发送到目标channel中。
7、内存池
- 对缓冲区Buffer的内存分配和回收特别在于堆外是一件非常耗时的操作。因此,Netty提供了内存池的缓冲区重用机制。
- Netty提供了多种内存管理策略,通过在启动辅助类中配置相关参数,可以实现差异化的定制。
8、灵活的TCP参数配置能力(启动辅助类中配置)
- SO_RCVBUF和SO_SNDBUF:通常建议值为128KB,或者256KB
- SO_TCPNODELAY:NAGLE算法通过将缓冲区内的小封包自动相连,组成较大的封包,阻止大量小封包的发送阻塞网络,从而提高网络应用效率。但对于延时敏感的应该关掉该配置。
- 软中断:如果Linux内核版本为RPS2.6.35版本以上,开启RPS后可以实现软中断,提升网络吞吐量。每个连接和CPU绑定,并通过hash值,来均衡软中断在多个cpu上。提升网络并行。