目录
一、概念介绍
1、同步与异步
从字面的意思可以看出:同步IO即 如果一个线程请求进行IO操作,在IO操作完成之前,该线程会被阻塞;而异步IO为 如果一个线程请求进行IO操作,IO操作不会导致请求线程被阻塞。
事实上,同步IO和异步IO模型是针对用户线程和内核的交互来说的:
linux系统IO分为内核准备数据和将数据从内核拷贝到用户空间两个阶段。
对于同步IO:当用户发出IO请求操作之后,如果数据没有就绪,需要通过用户线程或者内核不断地去轮询数据是否就绪,当数据就绪时,再将数据从内核拷贝到用户线程;
而异步IO:只有IO请求操作的发出是由用户线程来进行的,IO操作的两个阶段都是由内核自动完成(等待数据就绪阶段和数据拷贝阶段),然后发送通知告知用户线程IO操作已经完成。也就是说在异步IO中,不会对用户线程产生任何阻塞。
这是同步IO和异步IO关键区别所在,同步IO和异步IO的关键区别反映在数据拷贝阶段是由用户线程完成还是内核完成。所以说异步IO必须要有操作系统的底层支持。
2、阻塞与非阻塞
阻塞IO和非阻塞IO是反映在当用户请求IO操作时,如果数据没有就绪,是用户线程一直等待数据就绪,还是会收到一个标志信息这一点上面的。也就是说,阻塞IO和非阻塞IO是反映在IO操作的第一个阶段,在查看数据是否就绪时是如何处理的。
3、同步阻塞io
4、同步非阻塞io
5、IO多路复用
IO多路复用模型是建立在内核提供的多路分离函数select基础之上的,使用select函数可以避免同步非阻塞IO模型中轮询等待的问题。
6、异步IO
二、BIO(同步阻塞IO)
通常由一个独立的线程Acceptor负责客户端的连接,接收到客户端的连接请求之后,为每个客户端创建一个新的线程进行链路处理,完成之后,通过输出流返回给客户端,线程销毁。
一个连接一个线程,客户端有连接请求时,服务端就启动一个线程来执行。
三、伪异步IO
对BIO进行了优化,后端通过一个线程池来处理多个客户端的请求,行程客户端个数M:线程池最大线程数N的比例关系,防止海量并发接入导致线程耗尽。
四、NIO(同步阻塞IO)
一个io请求一个线程,客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到有连接的io请求时才会启动一个线程来处理。
五、Netty线程模型
高性能 IO 模型: Reactor,
它是一种异步、非阻塞的事件驱动模型。
1、Reactor单线程模型
所有的IO操作都在同一个NIO线程上面完成,它是由一个线程来接收客户端的连接,并将该请求分发到对应的事件处理 handler 中,整个过程完全是异步非阻塞的;并且完全不存在共享资源的问题。所以理论上来说吞吐量也还不错。
2、Reactor多线程模型
一个线程负责接收TCP连接请求,有一组NIO线程负责IO操作
瓶颈点:一个NIO线程负责监听和处理所有的客户端连接,可能会存在性能问题。比如百万客户端连接,或者服务端需要对客户端进行安全认证等。
3、主从Reactor多线程模型
服务端用于接收客户端连接的不再是一个单独的NIO线程,而是一个独立的NIO线程池。
4、Netty线程模型实现
private EventLoopGroup boss = new NioEventLoopGroup();
private EventLoopGroup work = new NioEventLoopGroup();
/**
* 启动 Netty
*
* @return
* @throws InterruptedException
*/
@PostConstruct
public void start() throws InterruptedException {
ServerBootstrap bootstrap = new ServerBootstrap()
.group(boss, work)
.channel(NioServerSocketChannel.class)
.localAddress(new InetSocketAddress(nettyPort))
//保持长连接
.childOption(ChannelOption.SO_KEEPALIVE, true)
.childHandler(new HeartbeatInitializer());
ChannelFuture future = bootstrap.bind().sync();
if (future.isSuccess()) {
LOGGER.info("启动 Netty 成功");
}
}
单线程模型:
private EventLoopGroup group = new NioEventLoopGroup();
ServerBootstrap bootstrap = new ServerBootstrap()
.group(group)
.childHandler(new HeartbeatInitializer());
多线程模型:
private EventLoopGroup boss = new NioEventLoopGroup(1);
private EventLoopGroup work = new NioEventLoopGroup();
ServerBootstrap bootstrap = new ServerBootstrap()
.group(boss,work)
.childHandler(new HeartbeatInitializer());
主从多线程模型:
private EventLoopGroup boss = new NioEventLoopGroup();
private EventLoopGroup work = new NioEventLoopGroup();
ServerBootstrap bootstrap = new ServerBootstrap()
.group(boss,work)
.childHandler(new HeartbeatInitializer());