那麼Netty到底是何方神聖?
用一句簡單的話來說就是:Netty封裝了JDK的NIO,讓你用得更爽,你不用再寫一大堆複雜的代碼了。
用官方正式的話來說就是:Netty是一個異步事件驅動的網絡應用框架,用於快速開發可維護的高性能服務器和客戶端。
下面是我總結的使用Netty不使用JDK原生NIO的原因
- 使用JDK自帶的NIO需要了解太多的概念,編程複雜,一不小心bug橫飛
- Netty底層IO模型隨意切換,而這一切只需要做微小的改動,改改參數,Netty可以直接從NIO模型變身爲IO模型
- Netty自帶的拆包解包,異常檢測等機制讓你從NIO的繁重細節中脫離出來,讓你只需要關心業務邏輯
- Netty解決了JDK的很多包括空輪詢在內的bug
- Netty底層對線程,selector做了很多細小的優化,精心設計的reactor線程模型做到非常高效的併發處理
- 自帶各種協議棧讓你處理任何一種通用協議都幾乎不用親自動手
- Netty社區活躍,遇到問題隨時郵件列表或者issue
- Netty已經歷各大rpc框架,消息中間件,分佈式通信中間件線上的廣泛驗證,健壯性無比強大
看不懂沒有關係,這些我們在後續的課程中我們都可以學到,接下來我們用Netty的版本來重新實現一下本文開篇的功能吧
首先,引入Maven依賴
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.6.Final</version>
</dependency>
然後,下面是服務端實現部分
NettyServer.java
/**
* @author 閃電俠
*/
public class NettyServer {
public static void main(String[] args) {
ServerBootstrap serverBootstrap = new ServerBootstrap();
NioEventLoopGroup boos = new NioEventLoopGroup();
NioEventLoopGroup worker = new NioEventLoopGroup();
serverBootstrap
.group(boos, worker)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<NioSocketChannel>() {
protected void initChannel(NioSocketChannel ch) {
ch.pipeline().addLast(new StringDecoder());
ch.pipeline().addLast(new SimpleChannelInboundHandler<String>() {
@Override
protected void channelRead0(ChannelHandlerContext ctx, String msg) {
System.out.println(msg);
}
});
}
})
.bind(8000);
}
}
這麼一小段代碼就實現了我們前面NIO編程中的所有的功能,包括服務端啓動,接受新連接,打印客戶端傳來的數據,怎麼樣,是不是比JDK原生的NIO編程優雅許多?
初學Netty的時候,由於大部分人對NIO編程缺乏經驗,因此,將Netty裏面的概念與IO模型結合起來可能更好理解
1.boos
對應,IOServer.java
中的接受新連接線程,主要負責創建新連接
2.worker
對應 IOClient.java
中的負責讀取數據的線程,主要用於讀取數據以及業務邏輯處理
然後剩下的邏輯我在後面的系列文章中會詳細分析,你可以先把這段代碼拷貝到你的IDE裏面,然後運行main函數
然後下面是客戶端NIO的實現部分
NettyClient.java
/**
* @author 閃電俠
*/
public class NettyClient {
public static void main(String[] args) throws InterruptedException {
Bootstrap bootstrap = new Bootstrap();
NioEventLoopGroup group = new NioEventLoopGroup();
bootstrap.group(group)
.channel(NioSocketChannel.class)
.handler(new ChannelInitializer<Channel>() {
@Override
protected void initChannel(Channel ch) {
ch.pipeline().addLast(new StringEncoder());
}
});
Channel channel = bootstrap.connect("127.0.0.1", 8000).channel();
while (true) {
channel.writeAndFlush(new Date() + ": hello world!");
Thread.sleep(2000);
}
}
}
在客戶端程序中,group
對應了我們IOClient.java
中main函數起的線程,剩下的邏輯我在後面的文章中會詳細分析,現在你要做的事情就是把這段代碼拷貝到你的IDE裏面,然後運行main函數,最後回到NettyServer.java
的控制檯,你會看到效果。
使用Netty之後是不是覺得整個世界都美好了,一方面Netty對NIO封裝得如此完美,寫出來的代碼非常優雅,另外一方面,使用Netty之後,網絡通信這塊的性能問題幾乎不用操心,盡情地讓Netty榨乾你的CPU吧。
目前我負責的兩大長連接項目均峯值QPS在50W左右,單機連接數10W左右,集羣規模在千萬級別,底層均使用了Netty作爲通信框架。Netty如此高性能及穩定的特性讓我幾乎不用爲性能而擔憂,所以,如果你工作中需要接觸到網絡編程,Netty必將是你的最佳選擇!