一、概述
异步io框架,做网络通信的基础底层框架。被很多其他框架所使用,比如dubbo。
io分类
java共支持三种io模式,bio,nio,aio
bio就是最普通的io,阻塞同步io。客户端每发一个连接请求,服务端都要专门起一个线程去处理。
nio是同步非阻塞io,服务端起一个线程维护一个selector,这个selector去处理多个客户端的连接请求。
aio是异步非阻塞
二、nio
三大核心
selector,channel,buffer
一个线程对应一个selector,一个selector对应多个channel,一个channel对应一个buffer。
selector去处理哪个channel,是由事件决定的。
channel,buffer都是双向的。
缓冲区buffer
nio在selector和socket(程序)之间有channel和buffer,通过channel就可以进行数据传输。但正是有了缓冲区,才可以做到非阻塞。由buffer去和channel交互。
所谓缓冲区底层是数组,有各种buffer,shortbuffer,intbuffer,bytebuffer,longbuffer,不同的buffer存不同的数据类型。最常用的是bytebuffer。
通道channel
channel特性:
- 同时读写
- 异步读写
选择器selector
基本概念
Java的Nio,用非阻塞的io方式,用一个线程去处理多个客户端的连接,就会使用到Selector(选择器)
处理多个客户端连接的方式
多个channel以事件的方式注册到同一个selector,如果有事件发生,便获取事件,针对每个事件做对应的处理。以此来做到一个线程管理多个连接(实质是一个selector管理多个channel通道)。
三、AIO
I/O编程两种模式
在进行 I/O 编程中,常用到两种模式:Reactor和 Proactor,两个词顾名思义,reactor,是反应,而proactor,就是在反应前就反应。说白了,aio希望当有有效请求时才启动线程。(和nio对比,nio是一直有一个线程在轮询)
但目前aio并没有得到广泛使用,而netty也是基于nio的。
四、netty
原生nio存在的问题
- nio的类库以及api繁杂,使用麻烦
- 需要对多线程和网络编程很熟
- 开发难度以及工作量都很大
- 存在bug,如epoll bug
netty的优点
对原生nio进行了封装,便捷好用
目前稳定的是4.x版本
netty高性能架构设计
Reactor模式
单reactor单线程
负责监听事件和分发任务的线程是一个,处理任务的线程还是一个
单reactor多线程
负责监听事件和分发任务的线程是一个,处理任务的线程是多个
主从reactor多线程
负责监听事件和分发任务的线程是多个,处理任务的线程也是多个
netty工作原理示意图
Netty主要基于主从 Reactors多线程模型(如图)做了一定的改进
- BossGroup 线程维护 Selector,只关注 Accecpt
- 当接收到 Accept 事件,获取到对应的 SocketChannel,封装成 NIOScoketChannel 并注册到 Worker 线程(事件循环),并进行维护
- 当 Worker 线程监听到 Selector 中通道发生自己感兴趣的事件后,就进行处理(就由handler),注意 handler 已经加入到通道
异步执行的三种途径
1.用户程序自定义的普通任务
taskQueue自定义任务,向队列中添加异步任务
2.用户自定义定时任务
与上面taskQueue的区别就是加了个延时时长
3.非当前Reactor线程调用channel的各种方法
服务器端可以拿到所有客户端的channel,再从channel里取eventLoop就可以操作了。
异步模型
Future
1.Future代表异步执行的结果,可以通过它提供的方法来检测执行是否完成
2.ChannelFuture是一个接口,我们可以添加监听器,当监听的事件发生时,就会通知到监听器
当Future对象刚刚创建时,处于非完成状态,调用者可以通过返回的ChannelFuture来获取操作执行的状态,注册监听函数来执行完成后的操作。
常见的有:
isDone方法来判断当前操作是否完成;
isSuccess方法来判断已完成的当前操作是否成功;
addListener方法来注册监听器,当操作已完成(isDone方法返回完成),将会通知给指定的监听器;如果Future对象已完成,则通知指定的监听器。这样做的好处就是异步,不会阻塞,增加并发量。
五、开发总结
私聊实现思路:
客户端给服务端先发消息,服务端再转发
获取channel
获取channel后直接对channel操作就可以了
说白了管理客户端就是管理channel