Netty1:初識Netty

来源:https://www.cnblogs.com/xrq730/archive/2018/04/05/8723728.html
-Advertisement-
Play Games

為什麼使用Netty Netty是業界最流行的NIO框架之一,它的健壯性、功能、性能、可定製性、可擴展性在同類框架中都是首屈一指的,它已經得到了成百上千的商用項目的證明。對於為什麼使用Netty這個話題,我們先看一下使用原生的NIO有什麼缺點: NIO的類庫和API繁雜,使用麻煩,需要熟練掌握Sel ...


為什麼使用Netty

Netty是業界最流行的NIO框架之一,它的健壯性、功能、性能、可定製性、可擴展性在同類框架中都是首屈一指的,它已經得到了成百上千的商用項目的證明。對於為什麼使用Netty這個話題,我們先看一下使用原生的NIO有什麼缺點:

  • NIO的類庫和API繁雜,使用麻煩,需要熟練掌握Selector、ServerSocketChannel、SocketChannel、ByteBuffer等,這就像我們會使用Hibernate、MyBatis這些ORM框架而不會直接使用Connection、Statement一樣
  • 需要其他額外技能作為鋪墊,必須對多線程和網路編程非常熟悉才能寫出高質量的NIO程式
  • 可靠性能力補齊,工作量和難度都非常大,例如客戶端面臨斷線重連、網路閃斷、半包讀寫、失敗緩存、網路擁塞、異常碼流等問題的處理
  • JDK NIO的BUG,例如著名的epoll bug,該問題會導致Selector空輪訓,最終導致CPU 100%

也正是因為有種種缺點,因此不建議使用原生的NIO而是建議使用一些比較成熟的NIO框架例如Netty、Mina,這一系列文章講的是Netty,Netty作為一款高性能NIO框架,其優點總結有:

  • API使用簡單、開發門檻低
  • 功能強大,預置了多種編碼解碼功能,支持多種主流協議
  • 定製能力強,可以通過ChannelHandler對通信框架進行靈活擴展
  • 性能高,與業界其他主流NIO框架對比,Netty性能最優
  • 成熟、穩定,Netty修複了已經發現的所有JDK NIO的BUG,業務開發人員不需要再為NIO的BUG而煩惱
  • 社區活躍、版本迭代周期短,發現的BUG可以被及時修複,同時,更多的新功能會被加入
  • 經歷了大規模的商業應用考驗,質量得到驗證

正因為這些優點,Netty逐漸成為了Java NIO變成的首選框架。

 

Netty入門Demo

下麵演示一下Netty的Demo(註:Demo來自Netty權威指南第三章),本文只寫代碼與演示結果,不做講解,對Netty的使用基本講解放在下一篇文章中,循序漸進,先感性地認識Netty,再理性地認識Netty中的東西。

從服務端代碼開始,定義一個TimeServer:

 1 public class TimeServer {
 2 
 3     public void bind(int port) throws Exception {
 4         // NIO線程組
 5         EventLoopGroup bossGroup = new NioEventLoopGroup();
 6         EventLoopGroup workerGroup = new NioEventLoopGroup();
 7         
 8         try {
 9             ServerBootstrap b = new ServerBootstrap();
10             b.group(bossGroup, workerGroup)
11                 .channel(NioServerSocketChannel.class)
12                 .option(ChannelOption.SO_BACKLOG, 1024)
13                 .childHandler(new ChildChannelHandler());
14             
15             // 綁定埠,同步等待成功
16             ChannelFuture f = b.bind(port).sync();
17             // 等待服務端監聽埠關閉
18             f.channel().closeFuture().sync();
19         } finally {
20             // 優雅退出,釋放線程池資源
21             bossGroup.shutdownGracefully();
22             workerGroup.shutdownGracefully();
23         }
24     }
25     
26     private class ChildChannelHandler extends ChannelInitializer<SocketChannel> {
27         @Override
28         protected void initChannel(SocketChannel arg0) throws Exception {
29             arg0.pipeline().addLast(new TimeServerHandler());
30         }
31     }
32     
33 }

TimeServerHandler這麼定義:

 1 public class TimeServerHandler extends ChannelHandlerAdapter {
 2 
 3     @Override
 4     public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
 5         ByteBuf buf = (ByteBuf)msg;
 6         byte[] req = new byte[buf.readableBytes()];
 7         buf.readBytes(req);
 8         
 9         String body = new String(req, "UTF-8");
10         System.out.println("The time server receive order:" + body);
11         String currentTime = "QUERY TIME ORDER".equalsIgnoreCase(body) ? new Date(System.currentTimeMillis()).toString() : "BAD ORDER";
12         
13         ByteBuf resp = Unpooled.copiedBuffer(currentTime.getBytes());
14         ctx.write(resp);
15     }
16     
17     @Override
18     public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
19         ctx.flush();
20     }
21     
22     @Override
23     public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
24         ctx.close();
25     }
26     
27 }

即讀取來自客戶端的數據,如果是"QUERY TIME ORDER",則把當前時間寫到Channel中去。至此,Netty服務端代碼已經開發完畢。接下來是Netty客戶端代碼,首先還是TimeClient:

 1 public class TimeClient {
 2 
 3     public void connect(int port, String host) throws Exception {
 4         EventLoopGroup group = new NioEventLoopGroup();
 5         try {
 6             Bootstrap b = new Bootstrap();
 7             
 8             b.group(group)
 9                 .channel(NioSocketChannel.class)
10                 .option(ChannelOption.TCP_NODELAY, true)
11                 .handler(new ChannelInitializer<SocketChannel>() {
12                     protected void initChannel(SocketChannel ch) throws Exception {
13                         ch.pipeline().addLast(new TimeClientHandler());
14                     };
15                 });
16             
17             // 發起非同步連接操作
18             ChannelFuture f = b.connect(host, port).sync();
19             // 等待客戶端連接關閉
20             f.channel().closeFuture().sync();
21         } finally {
22             // 優雅退出,釋放NIO線程組
23             group.shutdownGracefully();
24         }
25     }
26     
27 }

同樣的,定義一個TimeClientHandler:

 1 public class TimeClientHandler extends ChannelHandlerAdapter {
 2 
 3     private static final Logger LOGGER = LoggerFactory.getLogger(TimeClientHandler.class);
 4     
 5     private final ByteBuf firstMessage;
 6     
 7     public TimeClientHandler() {
 8         byte[] req = "QUERY TIME ORDER".getBytes();
 9         firstMessage = Unpooled.buffer(req.length);
10         firstMessage.writeBytes(req);
11     }
12     
13     @Override
14     public void channelActive(ChannelHandlerContext ctx) throws Exception {
15         ctx.writeAndFlush(firstMessage);
16     }
17     
18     @Override
19     public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
20         ByteBuf buf = (ByteBuf)msg;
21         byte[] req = new byte[buf.readableBytes()];
22         buf.readBytes(req);
23         
24         String body = new String(req, "UTF-8");
25         System.out.println("Now is:" + body);
26     }
27     
28     @Override
29     public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
30         LOGGER.warn("Unexcepted exception from downstream:" + cause.getMessage());
31         ctx.close();
32     }
33     
34 }

客戶端的操作為列印來自服務端的數據,這樣,整個Netty Demo代碼就寫完了,結構比較清楚,都是一個Server+一個Handler的模式,Handler用於處理讀取到的信息。

 

運行Demo

上面寫完了Demo,接著寫一下測試代碼,很簡單,分別運行bind方法和connect方法即可:

 1 public class CoreTest {
 2 
 3     @Test
 4     public void timeServerTest() throws Exception {
 5         new TimeServer().bind(8080);
 6     }
 7     
 8     @Test
 9     public void timeClientTest() throws Exception {
10         new TimeClient().connect(8080, "127.0.0.1");
11     }
12     
13 }

先運行timeServerTest讓服務端先啟動,再運行timeClientServer讓客戶端後啟動,運行結果服務端的列印為:

The time server receive order:QUERY TIME ORDER

結合代碼可以看到,服務端讀取到了來自客戶端的數據,數據內容為"QUERY TIME ORDER",接著服務端取自己的時間,傳輸給客戶端,看一下客戶端的列印:

Now is:Thu Apr 05 21:07:39 CST 2018

列印了來自服務端的時間,這樣,利用Netty進行服務端+客戶端的相互通信的Demo完成,有了這個Demo,對Netty有了感性上的認識,接著我們一點一點深入去學習Netty。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 前言: 必需學會SpringBoot基礎知識 簡介: spring cloud 為開發人員提供了快速構建分散式系統的一些工具,包括配置管理、服務發現、斷路器、路由、微代理、事件匯流排、全局鎖、決策競選、分散式會話等等。它運行環境簡單,可以在開發人員的電腦上跑。 工具: JDK8 apache-mave ...
  • 【步驟】 【說明】 1、什麼是環境變數? 其實就是操作系統的全局變數。 1、為什麼配置PATH? 通過配置path環境變數,我們可以使某個程式,比如javac.exe,在任意目錄下都可以運行,而不用跑到javac存在的目錄下進行dos命令。 比如:可以將QQ.exe所在目錄配置到path中,這樣在任 ...
  • 作為你程式代碼的構建基礎,類和結構體是一種多功能且靈活的構造體。通過使用與現存常量、變數、函數完全相同的語法來在類和結構體當中定義屬性和方法以添加功能。 ...
  • 解析器 (1)api/urls.py (2)views.py (3)通過postman發送Json數據 在後臺可以獲取發過來的Json數據 源碼流程 (1)dispatch (2)initialize_request 獲取所有解析器 (3)get_parsers (4)parser_classes ...
  • SSH框架整合 前言:有人說,現在還是流行主流框架,SSM都出來很久了,更不要說SSH。我不以為然。現在許多公司所用的老項目還是ssh,如果改成主流框架,需要成本。再說比如金融IT這一塊,資料庫dao層還是推薦使用的是hibernate,因為能夠快速開發上手,除非是互聯網,因涉及到高併發,dao層用 ...
  • 曾經,博主的房東養了只金毛叫奶茶,今天就拿它當議題好了。 博主寫本文時正在被廣州的蚊子圍攻。 ...
  • Java既是編譯型語言,又是解釋型語言 java源文件首先需要通過javac編譯生成尾碼名為.class的位元組碼文件(與平臺無關,只面向JVM),然後使用Java虛擬機將位元組碼解釋成特定平臺上的機器碼運行。 Java虛擬機JVM 不同平臺上的JVM不同,但是都提供了相同的介面。 開發Java準備 下 ...
  • 聲明 可能本文章會有錯誤,希望各位讀者看到後,記得回覆留言,提醒我,以免誤人子弟。本人菜雞,還望各位大佬手下留情。文章是以我個人思路來寫的,只能在學習的時候看,在比賽中,當然還是怎麼 快速準確的解答題目為標準 。 題目 : 我們來玩一個游戲。 同時擲出3個普通骰子(6個面上的數字分別是1~6)。 如 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...