Java IO模型與Netty線程模型

目錄

 

一、概念介紹

1、同步與異步

2、阻塞與非阻塞

3、同步阻塞io

4、同步非阻塞io

5、IO多路複用

6、異步IO

二、BIO(同步阻塞IO)

三、僞異步IO

四、NIO(同步阻塞IO)

五、Netty線程模型

1、Reactor單線程模型

2、Reactor多線程模型

3、主從Reactor多線程模型

4、Netty線程模型實現


一、概念介紹

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());

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章