目錄
一、概念介紹
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());