Netty如何支持三種Reactor


參考文獻:極客時間傅健老師的《Netty源碼剖析與實戰》Talk is cheap.show me the code!

什么是Reactor及三種版本

   反應堆設計模式(Reactor pattern):是一種為處理並發服務請求,並將請求提交到一個或者多個服務處理程序的事件設計模式。當客戶端請求抵達后,服務處理程序使用多路分配策略,由一個非阻塞的線程來接收所有的請求,然后派發這些請求至相關的工作線程進行處理。

  三種版本:Reactor單線程(一個人包攬),Reactor多線程模式(多人分擔),主從Reactor多線程模式(多人細工分擔)。

Reactor是一種開發模式,模式的核心流程為:注冊感興趣的事件---->掃描是都有感興趣的事件發生---->事件發生后做出相應的處理。

  對於每一種的SocketChannel它監聽的事件也不同,如下圖!

如何在Netty中使用Reactor模式

  

  上圖中非主從Reactor多線程模式中"EventLoopGroup eventGroup = new NioEventLoopGroup()"中沒有給參數,參考Reactor單線程模式給的參數是1,這里沒有參數為什么是多線程模式?那是因為如果我們不去設置的話,它會根據CPU核數去計算出一個最優的線程數,現在單核CPU幾乎沒有了,所以現在幾乎可以百分百的肯定這樣就是多線程模式。

源碼解釋

public class MyServer {
    public static void main(String[] args) throws Exception {
        EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workerGroup = new NioEventLoopGroup(); try {
            ServerBootstrap sb = new ServerBootstrap();
            sb.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class)
                    .handler(new LoggingHandler(LogLevel.INFO)).childHandler(new ChannelInitializer<SocketChannel>() {
                @Override
                public void initChannel(SocketChannel ch) throws Exception {
                    ChannelPipeline p = ch.pipeline();
                    p.addLast(new LoggingHandler(LogLevel.INFO));
                    p.addLast(new MyServerHandler());
                }
            });
            ChannelFuture f = sb.bind(8090).sync();
            f.channel().closeFuture().sync();
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
}

  代碼中標粗標大的就是主從Reactor模式的核心點,其中bossGroup(可以理解為主)和workerGroup(可以理解為從)都是需要被設置到ServerBootstrap中去,“sb.group(bossGroup,workerGroup)”則是綁定,進入group()方法:

public ServerBootstrap group(EventLoopGroup parentGroup, EventLoopGroup childGroup) {
        super.group(parentGroup);
        ObjectUtil.checkNotNull(childGroup, "childGroup");
        if (this.childGroup != null) {
            throw new IllegalStateException("childGroup set already");
        }
        this.childGroup = childGroup;
        return this;
    }

進入super.group(parentGroup);

可以看到"this.group = group”;group則是傳入的“bossGroup”;this.group則是該類定義的成員。

volatile EventLoopGroup group;

而該成員在group()被return.

接下來需要查看哪里調用了該方法(windows下的idea按ctrl+alt+h可以查詢),如圖:

 

  圖上標記的“ChannelFuture regFuture = config().group().register(channel);”不難看出我們取到了group,再將channel綁定進去,這里的channel指的是:在服務器的開發那就是ServerSocketChannel。所以可以簡單的理解:我們將ServerSocketChannel綁定到bossGroup上,有了ServerSocketChannel就能創建子的SocketChannel,再將子的SocketChannel綁定到之前的workerGroup上。

源碼驗證

  還是之前的那張圖,進入sb.group()中:

這里的“this.childGroup = childGroup;”的this.childGroup 也是定義的成員

private volatile EventLoopGroup childGroup;

查看this.childGroup誰在用,搜索發現:

final EventLoopGroup currentChildGroup = childGroup;

msg即SocketChannel,下面標紅框的就是將msg進行綁定到workerGroup中,簡單說就是兩種SocketChannel綁定到兩個Group里面去。這樣就完成了主從Reactor模式的支持。

我只想做的更好,僅此而已


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM