文章目录
- 一、TCP/IP
- 二、IO模型
- 三、Netty:网络IO的王者-堪比spring在java中的地位
- 1.使用场景:
- 2. IO原理:底层使用主从Reactor模型
- 3. 处理IO事件流程:
- 4. channel与channelPipeLine组成:
- 5.netty核心组件
- 6 netty面试题
提示:以下是本篇文章正文内容,下面案例可供参考
一、TCP/IP
1.理论上的网络传输模型-7层
从上层 -----> 往底层:
一个请求从一个应用到达另一个应用网络传输的流程图如下:
2.实际已实现的网络传输模型-4层
TCP/IP模型概念将以上7层概括为4层,由上层往底层依次是:
应用层、传输控制层、网络层、数据链路层
如下图:
程序:对应的是应用层
内核公共区域:对应传输控制层+网络层+链路层+物理层
3.两种传输模型的对比
二、IO模型
【重点理解】
网络通信中服务端与内核必有的3步交互:
1.socket => 3,调用内核的socket方法,返回文件描述符3
2.bind(3,8090) ,将server socket与8090端口进行绑定
3.listen(3,50),监听这个已绑定的socket,50代表最大监听数量
1.传统阻塞IO模型:accept阻塞与recv阻塞
阻塞原因:
在内核初始化socket,并绑定监听后,accept会一直等待客户端的链接,如此时A客户端与服务端建立了链接,迟迟不发送消息过来,此时recv也会一直处于阻塞状态。
此过程会有2次阻塞,即accept时阻塞与recv阻塞
2.每线程对应每链接:accept阻塞
在server端通过对每个已经建立连接的socket创建一个线程去处理recv操作,此时recv对于主线程来说没有阻塞了,但对于accept操作主线程还是处于阻塞状态。
2.1优势:
可以接受很多的连接
2.2存在问题:
1.线程内存浪费
2.CPU调度切换频率变高,浪费cpu资源
2.3问题根源:
此过程还是使用的是阻塞IO模型。accept、recv阻塞
3.NIO模型
面试问:你聊一下NIO
我:是聊java 的NIO(New IO) 还是OS的 NIO(nonBlocking)
NIO模型下对于accept方法的非阻塞处理:
ss.accept不会阻塞,执行完会立刻返回一个socket对象,如果有连接进来,那么sokcetChannel不为空,否则为空。
此时演进的NIO模型 一:accept和recv不会阻塞
3代表ServerSocket。3.nonBlocking = serverSocket.configureBlocking(false)
5代表连接的一个客户端。5.nonBlocking = clinetSocket.configureBlocking(false)
此时存在的问题:
多路复用器的出现:
什么是多路复用器:内核允许一个程序监听多个系统文件描述符
多路复用器种类:
1.select :同步io多路复用器
poll
select 与poll 区别:select最多只能接受1024个客户端连接,poll没有限制。
问:是否是使用了多路复用器,程序就将数据读取到了内存中?
答:否,多路复用器只是告诉程序哪些文件可读/可写的状态。真正程序要读取数据,还是要调用recv
问:什么是多路复用器,解决了什么问题
答:1.多路复用器解决的是IO状态的问题,并不解决读写数据的问题
2.多路复用器其实解决的是用更少的系统调用一次询问所有的IO状态,而不是每个IO独立询问状态,减少了用户态到内核态的切换过程
总结:如果程序自己读取IO,那么这个IO模型无论是BIO,NIO,多路复用器都是属于:同步IO模型
java代码中,使用的selector,可能用的多路复用器是select、poll、epoll,取决于系统
2.epoll:利用空间来换取时间,解决了select/poll多路复用器的阻塞。
4.NIO模型之reactor:
reactor:采用基于事件驱动的设计,当有事件触发时,才会调用处理器进行数据处理。
4.1:reactor单线程
缺点:读写会阻塞
4.2:reactor多线程
缺点:仍为单线程,处理acept事件接受client时,无法进行读写事件
4.2:主从reactor多线程
三、Netty:网络IO的王者-堪比spring在java中的地位
1.使用场景:
1.1 互联网RPC框架
1.2 大型游戏
1.3 大数据领域
2. IO原理:底层使用主从Reactor模型
3. 处理IO事件流程:
4. channel与channelPipeLine组成:
5.netty核心组件
5.1.Bootstrap与ServerBootstrap
Bootstrap:引导的意思,netty客户端启动类
ServerBootstrap:netty服务端启动类
主要方法如下:
主要作用:设置客户端与服务端io模型类型、配置channel、绑定端口号、连接服务端等。
5.2.Future与Promise、ChannelFuture
监听异步线程处理后的事件,成功或失败
5.3 Channel
主要执行网络IO操作
5.4 Selector
netty默认使用了多路复用的线程模型。一个selector可以同时监听多个channel事件
5.5 ChannelHandler 及其实现类
channel中真正处理IO事件的接口,处理IO事件/拦截IO操作,并转发给ChannelPipeline(业务处理器链)。
主要有几个实现类:
5.5.1 ChannelInboundHandler
处理IO入栈事件
5.5.2 ChannleOutboundHandler
处理IO出栈事件
5.5.2 ChannelDuplexHandler
用于处理入站和出站事件
5.6 Pipeline 与 ChannelPipeline
ChannelPipeline是一个双向链表,维护多个ChannelHandler 的集合。一个channel只对应一个channelPipeline
netty中的核心处理逻辑都是由ChannelPipeline来实现
IO进站操作由head依次向后执行到tail
IO出栈操作由tail依次向前执行到head
ChannelPipleline的这种设计模式使得netty在处理业务上可以为所欲为
5.7 ChannelHandlerContext
ChannelHandlerContext保存着Channel 所有的信息,同时关联一个channelHandler对象
5.8 ChannelOption
netty创建了channel后通过channelOption对channel进行配置:
5.8.1 ChannelOption.SO_BACKLOG
指定队列大小并存放客户端连接,同一时刻只能处理一个客户端连接
5.8.2 ChannelOption.SO_KEEPALIVE
一直保持连接活动状态
5.9 EventLoopGroup 与其实现类NioEventLoopGroup
一个EventLoop维护一个selector
通常netty会使用主从reactor多线程模型来配置netty的线程模型。一般为两个EventLoopGroup即bossEventLoopGroup与workEventLoopGroup
5.9.1 bossEventLoopGroup:
负责处理accept事件,并将坚挺到的SocketChannel交给workEventLoopGroup去管理处理响应的IO事件
5.9.2 workEventLoopGroup:
会选择一个EventLoop会将SocketChannel维护到自己的selector上,来处理IO操作,那么每次这个SocketChannel有事件时,都有这个EventLoop来处理