网络编程与高效IO
2021-02-25 18:18:15 15 举报
AI智能生成
网络IO编程,高效IO, Netty原理, 网络协议
作者其他创作
大纲/内容
网络协议
网络模型
TCP和UDP的区别
UDP
1. 无连接协议, 无需握手
2. 除了1对1单播通信, 还可以1对多广播通信
3. 面向报文
TCP
1. 面向连接, 见面3次握手, 断开4次挥手
3次握手
1. C端发起syn请求
2. S端回复ack+syn请求
3. C端回复ack请求, 这时C端的TCP通道estalished
4. S端收到B端回复, 这时S端的TCP通道estalished
为什么S-C需要握手3次, 而不是2次?
4次挥手
1. C端发起fin请求
2. S端回复ack请求
3. S端信息业务继续发送中
为什么S-C需要挥手4次, 而不是3次?
4. S端发送fin请求
5. C端回复ack请求, S端通道CLOSED, C端等待2MSL后CLOSED
2. 仅支持1对1单播
3. 面向字节流
4. 可靠传输
序列号
检验和
确认应答信号
重发控制
窗口控制
拥塞控制
对比
TCP中拆包黏包现象
1、将消息分为头部和消息体,在头部中保存有当前整个消息的长度
2、可以在数据包之间设置边界,如添加特殊符号
3. 消息定长
网络IO
IO
两个阶段
1. 等待数据准备阶段 - 等待数据从socket中到达(recvfrom函数),到达后需要复制到内核的缓冲区中
2. 从内核的缓冲区复制到进程的缓冲区,复制到进程的缓冲区才算读取完毕
IO演进
阻塞IO
一个线程只能同时处理一个socket通道
等待数据准备阶段] 和 [线程read] 都会会阻塞线程
缺点
每个请求都需要开启线程,并且阻塞不能干其他事情,比较耗费资源
非阻塞IO
一个线程能同时处理多个socket通道
socket请求的[等待数据准备阶段],进程不会阻塞,会快速返回结果(返回error的话,会过一段时间再发送recvfrom请求, 期间可以做其他事情).
缺点
当有大量客户端连接时,每次判断fd状态都需要从用户态切换到内核态,
即10k个连接需要循环10k次系统调用,费时费力
即10k个连接需要循环10k次系统调用,费时费力
多路复用
select O(n)
在非阻塞IO基础上,改进10k次系统调用为1次系统调用
缺点
每次系统调用都需要传10k个fd
实际上是由用户循环10k次改为了内核循环10k次,同样是O(n)复杂度
32位机器上,源码中写死了最多接受的fd为1024个,容易成为瓶颈
poll O(n)
在select基础上,改进了1024个的限制
缺点
除1024缺陷外,其余都在
epoll O(1)
在poll基础上实现:
1. 在内核开辟一个缓存区,将监听的fd注册到缓存区中, 并且记录下fd监听的事件类型
2. 当fd的监听事件发生了, 便把fd加入对应的事件就绪列表
3. 轮询就绪队列, 触发回调通知用户进程
1. 在内核开辟一个缓存区,将监听的fd注册到缓存区中, 并且记录下fd监听的事件类型
2. 当fd的监听事件发生了, 便把fd加入对应的事件就绪列表
3. 轮询就绪队列, 触发回调通知用户进程
10k个fd不再循环10k次,而实现了事件机制
缺点
每次读和写的时候,都是由用户线程自己从内核buffer读
异步IO
在epoll基础上,改进读写的时候由内核完成,用户线程只需要提供读写完成后的回调方法即可
目前linux系统还没有成熟的商用异步IO
C10K问题
http://www.kegel.com/c10k.html
netty
netty是一款基于NIO开发的网络通信框架.
优势
使用简单
功能强大
定制能力强
性能高
IO 线程模型
主从Reactor多线程模型
内存零拷贝
1. netty接收和发送ByteBuffe采用堆外直接内存, 避免从堆内存中复制到直接内存的步骤
2. 提供了组合ByteBuffer对象, 避免传统对象拼接时的内存拷贝
3. Netty的文件传输采用了transferTo方法,它可以直接将文件缓冲区的数据发送到目标Channel,避免了传统通过循环write方式导致的内存拷贝问题
内存池设计
串形化处理读写
高性能序列化协议
主要组件
Channel
EventLoop
ChannelFuture
ChannelHandler
ChannelPipeline
Reactor线程模型
Reactor模型基于异步通知模式, 即有事情发生了, 我就通知你去处理
Reactor
负责消息监听及事件响应,将事件分发给绑定了该事件的Handler处理
假如是连接事件, 则交给acceptor处理
假如是读写事件, 则交给handler处理
Acceptor
Handler的一种,绑定了connect事件.
注册channel到Reactor的selector中, 并创建对应的handlerPipe
注册channel到Reactor的selector中, 并创建对应的handlerPipe
Handler
事件处理器,绑定了某类事件.
完成channel的消息读取, 完成业务逻辑, 完成消息的发送
完成channel的消息读取, 完成业务逻辑, 完成消息的发送
单Reactor单线程模型
1个主线程
Reactor和Handlers在同一个线程内
1个Reactor
负责消息的监听, 及消息处理的分发
dispatch
dispatch
N个Handler
负责事件的响应处理
accept、read、decode、process、encode、send
accept、read、decode、process、encode、send
缺点
不能利用多核CPU
高并发时性能上无法支撑
一旦reactor线程意外跑飞或者进入死循环,会导致整个系统通信模块不可用
应用: redis
单Reactor多线程模型
1个主线程+1个worker线程池
1个Reactor(主线程内)
负责消息的监听, 及消息处理的分发
dispatch
dispatch
N个Handler(主线程内)
负责响应事件,不做具体的业务处理
read+send
read+send
worker线程池
具体的业务处理
decode+compute+encode
decode+compute+encode
特点
1. 相对于单reactor单线程, 将具体的业务处理交给worker线程池处理, 提高了cpu的利用率
2. 目前的问题是, 在handler读取时仍会阻塞线程
主从Reactor多线程模型
Nginx, Netty, Memcached 都是应用该模式
MainReactor线程池+SubReactor线程池+worker线程池
MainReactor
监听连接事件,收到事件后,通过Acceptor处理连接事件
accept
accept
SubReactor
连接事件处理完后, MainReactor将连接移交给SubReactor监听
接下来的各种事件处理由SubReactor去完成
read+send
接下来的各种事件处理由SubReactor去完成
read+send
worker
具体的业务处理
decode+compute+encode
decode+compute+encode
特点
1. MainReactor只负责连接事件的处理+移交
2. SubReactor负责事件的读写响应及消息处理的分发
3. worker线程负责具体的业务处理
优点
响应快,不必为单个同步事件所阻塞,虽然Reactor本身依然是同步的
可以最大程度的避免复杂的多线程的同步问题,并且避免了多线程/进程的切换开销
扩展性好,可以方便的通过增加Reactor实例个数来充分利用CPU资源
复用性好,Reactor模型本身与处理逻辑无关,具有很高的复用性
小结
1. 单Reactor单线程,前台接待员和服务员是同一个人,全程为顾客服务
2. 单Reactor多线程,1个前台接待员,多个服务员,接待员只负责接待
3. 主从Reactor多线程,多个前台接待员,多个服务生
netty模型
NIOLoopGroup
NIOEventLoop表示一个不断循环的执行处理任务的线程,
每个NIOEventLoop都有一个Selector,用于监听绑定在其上的socket网络通讯
每个NIOEventLoop都有一个Selector,用于监听绑定在其上的socket网络通讯
NIOEventLoopGroup相当于一个事件循环组,
这个组中含有多个事件循环,每一个事件循环是NIOEventLoop
这个组中含有多个事件循环,每一个事件循环是NIOEventLoop
NIOEventLoopGroup可以有多个线程,即可以含有多个NIOEventLoop
Netty抽象出两组线程池
BossGroup和WorkerGroup类型都是NIOEventLoopGroup
BossGroup:专门负责接收客户端的连接
1:轮询Accept事件
2:处理Accept事件,与Client建立连接,生成NIOSocketChannel,并将其注册到某个
Worker NIOEventLoop上的selector
Worker NIOEventLoop上的selector
3:再去处理任务队列的任务,即runAllTasks
WorkerGroup:专门负责网络的读写
1:轮询read,write事件
2:处理IO事件,即read write,在NIOSocketChannel处理
3:处理任务队列的任务,即runAllTasks
每个Worker NIOEventLoop 要处理数据的话,是通过PipeLine(管道)执行的
0 条评论
下一页