滴滴面試:談談你對Netty線程模型的理解?

磊哥課程 2024-06-01 06:55:43

Netty 線程模型是指 Netty 框架爲了提供高性能、高並發的網絡通信,而設計的管理和利用線程的策略和機制。

Netty 線程模型被稱爲 Reactor(響應式)模型/模式,它是基于 NIO 多路複用模型的一種升級,它的核心思想是將 IO 事件和業務處理進行分離,使用一個或多個線程來執行任務的一種機制。

1.Reactor三大組件

Reactor 包含以下三大組件:

其中:

Reactor(反應器):Reactor 負責監聽和分發事件,它是整個 Reactor 模型的調度中心。Reactor 監視一個或多個輸入通道,如監聽套接字上的連接請求或讀寫事件。當檢測到事件發生時,Reactor 會將其分發給預先注冊的處理器(Handler)進行處理。在 Netty 中,這個角色經常是由 EventLoop 或其相關的 EventLoopGroup 來扮演,它們負責事件的循環處理、任務調度和 I/O 操作。Acceptor(接收器):用于處理 IO 連接請求。當 Reactor 檢測到有新的客戶端連接請求時,會通知 Acceptor,後者通過 accept() 方法接受連接請求,並創建一個新的 SocketChannel(在 Netty 中是 Channel)來表示這個連接。隨後,Acceptor 通常會將這個新連接的 Channel 注冊到 Worker Reactor 或 EventLoop 中,以便進一步處理該連接上的讀寫事件。Handlers(處理器):Handlers 負責具體的事件處理邏輯,即執行與事件相關的業務操作。在 Netty 中,Handler 是一個或多個 ChannelHandler 的實例,它們形成一個責任鏈(ChannelPipeline),每個 Handler 負責處理一種或一類特定的事件(如解碼、編碼、業務邏輯處理等)。數據或事件在 ChannelPipeline 中從一個 Handler 傳遞到下一個,直至處理完畢或被消費。Handler 可以分爲入站(inbound)和出站(outbound)兩種,分別處理流入的數據或流出的數據。2.Reactor三大模型

Reactor 模式支持以下三大模型:

單線程模型多線程模型主從多線程模型

具體內容如下。

2.1 單線程模型

在單線程模型中,所有的事件處理操作都由單個 Reactor 實例在單個線程下完成。Reactor 負責監控事件、分發事件和執行事件處理程序(Handlers),如下圖所示:

單線程模型的實現 Demo 如下:

// 假設有一個單線程的Reactor,負責監聽、接收連接、讀寫操作class SingleThreadReactor { EventLoop eventLoop; // 單個事件循環線程 SingleThreadReactor() { eventLoop = new EventLoop(); // 初始化單個事件循環 } void start(int port) { ServerSocketChannel serverSocket = ServerSocketChannel.open(); serverSocket.socket().bind(new InetSocketAddress(port)); // 綁定端口 eventLoop.execute(() -> { // 在事件循環中執行 while (true) { SocketChannel clientSocket = serverSocket.accept(); // 接受連接 if (clientSocket != null) { handleConnection(clientSocket); // 處理連接 } } }); eventLoop.run(); // 啓動事件循環 } void handleConnection(SocketChannel clientSocket) { // 讀寫操作,這裏簡化處理 ByteBuffer buffer = ByteBuffer.allocate(1024); while (clientSocket.read(buffer) > 0) { // 處理讀取的數據 buffer.flip(); // 假設處理數據邏輯... buffer.clear(); } // 寫操作邏輯類似 }}優缺點分析優點:簡單、線程安全性好、適合編寫簡單的網絡應用。缺點:處理能力受限于單個線程的處理能力,無法充分利用多核 CPU,可能會影響性能。2.2 多線程模型

在多線程模型中,連接 Acceptor 和業務處理(Handlers)是由不同線程分開執行的,其中 Handlers 是由線程池(多個線程)來執行的,如下圖所示:

多線程模型的實現 Demo 如下:

// 假設有兩個線程,一個用于監聽連接,一個用于處理連接後的操作class MultiThreadReactor { EventLoop acceptLoop; EventLoop workerLoop; MultiThreadReactor() { acceptLoop = new EventLoop(); // 接收連接的線程 workerLoop = new EventLoop(); // 處理連接的線程 } void start(int port) { ServerSocketChannel serverSocket = ServerSocketChannel.open(); serverSocket.socket().bind(new InetSocketAddress(port)); acceptLoop.execute(() -> { // 在接受線程中監聽 while (true) { SocketChannel clientSocket = serverSocket.accept(); if (clientSocket != null) { workerLoop.execute(() -> handleConnection(clientSocket)); // 將新連接交給工作線程處理 } } }); acceptLoop.run(); // 啓動接受線程 workerLoop.run(); // 啓動工作線程 } // handleConnection 方法與單線程模型中的相同}優缺點分析優點:此模式可以提高並發性能,充分利用多核 CPU,並且保持簡單的編程模型。缺點:多線程數據共享和數據同步比較複雜,並且 Reactor 需要處理所有事件監聽和響應,在高並發場景依然會出現性能瓶頸。2.3 主從多線程模型

主從多線程模型是一個主 Reactor 線程加多個子 Reactor 子線程,以及多個工作線程池來處理業務的,如下圖所示:

主從多線程模型的實現 Demo 如下:

import io.netty.bootstrap.ServerBootstrap;import io.netty.channel.ChannelFuture;import io.netty.channel.ChannelInitializer;import io.netty.channel.EventLoopGroup;import io.netty.channel.nio.NioEventLoopGroup;import io.netty.channel.socket.SocketChannel;import io.netty.channel.socket.nio.NioServerSocketChannel;public MainReactorModel { public static void main(String[] args) { // 主Reactor,用于接受連接 EventLoopGroup bossGroup = new NioEventLoopGroup(); // 從Reactor,用于處理連接後的讀寫操作 EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap bootstrap = new ServerBootstrap(); bootstrap.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .childHandler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) { // 在這裏添加業務處理器,如解碼器、編碼器、業務邏輯處理器 ch.pipeline().addLast(new MyBusinessHandler()); } }); ChannelFuture future = bootstrap.bind(8080).sync(); System.out.println("Server started at port 8080"); future.channel().closeFuture().sync(); // 等待服務器關閉 } catch (InterruptedException e) { e.printStackTrace(); } finally { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } }}優缺點分析優點:可以充分利用多核 CPU 的資源,提高系統的整體性能和並發處理能力。缺點:模型相對複雜,實現和維護成本較高。課後思考

NioEventLoop 是如何實現的?它能夠保證 Channel 操作的線程安全嗎?爲什麽?

本文已收錄到我的面試小站 [www.javacn.site](https://www.javacn.site),其中包含的內容有:Redis、JVM、並發、並發、MySQL、Spring、Spring MVC、Spring Boot、Spring Cloud、MyBatis、設計模式、消息隊列等模塊。

0 阅读:0

磊哥課程

簡介:感謝大家的關注