天天看點

Java IO模型與Netty線程模型一、概念介紹二、BIO(同步阻塞IO)三、僞異步IO四、NIO(同步阻塞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分為核心準備資料和将資料從核心拷貝到使用者空間兩個階段。

Java IO模型與Netty線程模型一、概念介紹二、BIO(同步阻塞IO)三、僞異步IO四、NIO(同步阻塞IO)五、Netty線程模型

  對于同步IO:當使用者發出IO請求操作之後,如果資料沒有就緒,需要通過使用者線程或者核心不斷地去輪詢資料是否就緒,當資料就緒時,再将資料從核心拷貝到使用者線程;

  而異步IO:隻有IO請求操作的發出是由使用者線程來進行的,IO操作的兩個階段都是由核心自動完成(等待資料就緒階段和資料拷貝階段),然後發送通知告知使用者線程IO操作已經完成。也就是說在異步IO中,不會對使用者線程産生任何阻塞。

  這是同步IO和異步IO關鍵差別所在,同步IO和異步IO的關鍵差別反映在資料拷貝階段是由使用者線程完成還是核心完成。是以說異步IO必須要有作業系統的底層支援。

2、阻塞與非阻塞

  阻塞IO和非阻塞IO是反映在當使用者請求IO操作時,如果資料沒有就緒,是使用者線程一直等待資料就緒,還是會收到一個标志資訊這一點上面的。也就是說,阻塞IO和非阻塞IO是反映在IO操作的第一個階段,在檢視資料是否就緒時是如何處理的。

3、同步阻塞io

Java IO模型與Netty線程模型一、概念介紹二、BIO(同步阻塞IO)三、僞異步IO四、NIO(同步阻塞IO)五、Netty線程模型

4、同步非阻塞io

Java IO模型與Netty線程模型一、概念介紹二、BIO(同步阻塞IO)三、僞異步IO四、NIO(同步阻塞IO)五、Netty線程模型

5、IO多路複用

IO多路複用模型是建立在核心提供的多路分離函數select基礎之上的,使用select函數可以避免同步非阻塞IO模型中輪詢等待的問題。

Java IO模型與Netty線程模型一、概念介紹二、BIO(同步阻塞IO)三、僞異步IO四、NIO(同步阻塞IO)五、Netty線程模型

6、異步IO

Java IO模型與Netty線程模型一、概念介紹二、BIO(同步阻塞IO)三、僞異步IO四、NIO(同步阻塞IO)五、Netty線程模型

二、BIO(同步阻塞IO)

通常由一個獨立的線程Acceptor負責用戶端的連接配接,接收到用戶端的連接配接請求之後,為每個用戶端建立一個新的線程進行鍊路處理,完成之後,通過輸出流傳回給用戶端,線程銷毀。

一個連接配接一個線程,用戶端有連接配接請求時,服務端就啟動一個線程來執行。

Java IO模型與Netty線程模型一、概念介紹二、BIO(同步阻塞IO)三、僞異步IO四、NIO(同步阻塞IO)五、Netty線程模型

三、僞異步IO

對BIO進行了優化,後端通過一個線程池來處理多個用戶端的請求,行程用戶端個數M:線程池最大線程數N的比例關系,防止海量并發接入導緻線程耗盡。

Java IO模型與Netty線程模型一、概念介紹二、BIO(同步阻塞IO)三、僞異步IO四、NIO(同步阻塞IO)五、Netty線程模型

四、NIO(同步阻塞IO)

一個io請求一個線程,用戶端發送的連接配接請求都會注冊到多路複用器上,多路複用器輪詢到有連接配接的io請求時才會啟動一個線程來處理。

五、Netty線程模型

高性能 IO 模型: 

Reactor,

它是一種異步、非阻塞的事件驅動模型。

1、Reactor單線程模型

所有的IO操作都在同一個NIO線程上面完成,它是由一個線程來接收用戶端的連接配接,并将該請求分發到對應的事件處理 handler 中,整個過程完全是異步非阻塞的;并且完全不存在共享資源的問題。是以理論上來說吞吐量也還不錯。

Java IO模型與Netty線程模型一、概念介紹二、BIO(同步阻塞IO)三、僞異步IO四、NIO(同步阻塞IO)五、Netty線程模型

2、Reactor多線程模型

一個線程負責接收TCP連接配接請求,有一組NIO線程負責IO操作

Java IO模型與Netty線程模型一、概念介紹二、BIO(同步阻塞IO)三、僞異步IO四、NIO(同步阻塞IO)五、Netty線程模型

瓶頸點:一個NIO線程負責監聽和處理所有的用戶端連接配接,可能會存在性能問題。比如百萬用戶端連接配接,或者服務端需要對用戶端進行安全認證等。

3、主從Reactor多線程模型

服務端用于接收用戶端連接配接的不再是一個單獨的NIO線程,而是一個獨立的NIO線程池。

Java IO模型與Netty線程模型一、概念介紹二、BIO(同步阻塞IO)三、僞異步IO四、NIO(同步阻塞IO)五、Netty線程模型

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