NIO:高并发 长连接 短数据.例如即时通讯软件
低并发 大量的数据
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
1,监视器Selector主要是监视这些事件,一旦发生,生成SelectionKey对象,Selector是自我触发、自我激活的,因此是典型的Reactor模式实现
2,在非堵塞I/O API中,并不是由Selector来实现事件的处理,事件处理是由Selector激活出来后,通过其他处理器Handler来实现处理,开发者使用非堵塞I/O API需要做的工作就是:获取Selector激发的事件,然后根据相应事件类型,编制自己的处理器代码来进行具体处理。例如,如果是可读取事件,那么编制代码从SelectableChannel读取数据包,然后处理这个数据包
3,在非堵塞I/O API中,使用Reactor模式将事件发生和事件处理两个部分实现分离解耦,事件发生部分只负责事件的激活,而事件处理由专门的处理器实现具体处理
4,事件处理框架:1,源目标:事件发生,2, 监视者:将监察侦听事件的发生,事件发生后,它会被通知到3, 处理者:事件发生后,它将实现一定的行为动作,也就是处理事件
5,通常一个线程将花费 256kb到1mb的stack空间
多路复用器Selector,可以同时并发处理成百上千个客户端Channel,由于读写操作都是非阻塞的,这就可以充分提升IO线程的运行效率,避免由于频繁IO阻塞导致的线程挂起
高性能的三个主题
1) 传输:用什么样的通道将数据发送给对方,BIO、NIO或者AIO,IO模型在很大程度上决定了框架的性能
2) 协议:采用什么样的通信协议,HTTP或者内部私有协议。协议的选择不同,性能模型也不同。相比于公有协议,内部私有协议的性能通常可以被设计的更优
3) 线程:数据报如何读取?读取之后的编解码在哪个线程进行,编解码后的消息如何派发,Reactor线程模型的不同,对性能的影响也非常大。
netty零copy
1,Netty的接收和发送ByteBuffer采用DIRECT BUFFERS,使用堆外直接内存进行Socket读写,不需要进行字节缓冲区的二次拷贝。如果使用传统的堆内存(HEAP BUFFERS)进行Socket读写,JVM会将堆内存Buffer拷贝一份到直接内存中,然后才写入Socket中。相比于堆外直接内存,消息在发送过程中多了一次缓冲区的内存拷贝
Netty的高效并发编程主要体现在如下几点:
1) volatile的大量、正确使用;
2) CAS和原子类的广泛使用;
3) 线程安全容器的使用;
4) 通过读写锁提升并发性能。
高性能的序列化框架
影响序列化性能的关键因素总结如下:
1) 序列化后的码流大小(网络带宽的占用);
2) 序列化&反序列化的性能(CPU资源占用);
3) 是否支持跨语言(异构系统的对接和开发语言切换)。
Protobuf序列化后的码流只有Java序列化的1/4左右。正是由于Java原生序列化性能表现太差,才催生出了各种高性能的开源序列化技术和框架(性能差只是其中的一个原因,还有跨语言、IDL定义等其它因素)