一、Netty4教程
Netty4是一款使用Java語言基於NIO框架構建的高性能非同步網路通信框架,它提供了一種新的方式在Java平台上開發可擴展的、模塊化的、高性能的、可維護的TCP/IP伺服器和客戶端。Netty4的特點是高性能、高清晰度,易於使用和靈活性。
在Netty4的教程中,我們可以學習如何使用Netty4來編寫TCP/IP伺服器、客戶端和代碼示例,如下所示:
public class NettyServer { public static void main(String[] args) throws Exception { //1.創建EventLoopGroup對象,是一個線程池,實際數量可以根據業務需求調整 EventLoopGroup bossGroup = new NioEventLoopGroup(1); EventLoopGroup workGroup = new NioEventLoopGroup(); try { //2.創建ServerBootstrap對象,是啟動服務的工具類 ServerBootstrap b = new ServerBootstrap(); b.group(bossGroup, workGroup) //3.設置TCP協議的Channel,NioServerSocketChannel是對java.nio.*包的封裝 .channel(NioServerSocketChannel.class) //4.設置對client連接的數據處理邏輯PipeLine .childHandler(new ChannelInitializer<SocketChannel>() { @Override public void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast(new NettyServerHandler()); } }) //5.設置TCP連接參數,SO_BACKLOG是指處於同一時刻待處理的連接隊列的最大長度,超出的新連接會被拒絕,jvm會拋出ConnectionRefusedException .option(ChannelOption.SO_BACKLOG, 100) //6.設置緩衝區大小,通常可以不設置,會根據操作系統自適應,如果出現流量控制異常,可以考慮增加緩衝區大小 .option(ChannelOption.SO_SNDBUF, 65535) .option(ChannelOption.SO_RCVBUF, 65535) //7.設置心跳檢測機制以及關閉保護機制,保證TCP的正常關閉,防止TCP連接個數增長到JVM的最大值時出現宕機和內存耗盡等問題 .childOption(ChannelOption.SO_KEEPALIVE, true) .childOption(ChannelOption.TCP_NODELAY, true); // Bind and start to accept incoming connections. //8.綁定埠 ChannelFuture f = b.bind(PORT).sync(); //9.監聽channel關閉事件並執行shutdownGracefully關閉伺服器和事件處理組 f.channel().closeFuture().sync(); } finally { bossGroup.shutdownGracefully(); workGroup.shutdownGracefully(); } } }
二、Netty4 Client Pool
在我們使用Netty4來編寫客戶端時,為了保證程序的高效性,需要使用連接池來減少重新建立連接帶來的開銷,使用連接池來管理大量的連接可以提高程序的並發量和性能。
下面是使用Apache Commons Pool結合Netty4實現連接池的代碼示例:
public class NettyClientFactory extends BasePooledObjectFactory<NettyClient> { private String ip; private int port; public NettyClientFactory(String ip, int port) { this.ip = ip; this.port = port; } @Override public NettyClient create() throws Exception { Bootstrap bootstrap = new Bootstrap(); bootstrap.group(new NioEventLoopGroup()); bootstrap.channel(NioSocketChannel.class); bootstrap.option(ChannelOption.SO_KEEPALIVE, true); //設置重連機制 bootstrap.handler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel channel) throws Exception { channel.pipeline().addLast(new NettyClientHandler()); channel.pipeline().addLast(new IdleStateHandler(0, 5, 0, TimeUnit.SECONDS)); } }); ChannelFuture channelFuture = bootstrap.connect(ip, port); channelFuture.awaitUninterruptibly(); if (channelFuture != null && channelFuture.isSuccess()) { return new NettyClient(channelFuture.channel()); } return null; } @Override public PooledObject<NettyClient> wrap(NettyClient nettyClient) { return new DefaultPooledObject<>(nettyClient); } }
三、Netty4源碼
深入探究Netty4源碼可以大幅度提高我們對Netty4的理解和認識,方便我們更好的使用和維護Netty4。
Netty4的主要源碼結構如下:
+- common -- 通用的代碼 +- buffer -- 位元組緩存相關的代碼,包括ByteBuf的實現、池化等 +- codec -- 編碼和解碼相關的代碼 +- channel -- 整體框架代碼,包括Channel和EventLoop的實現 +- handler -- 處理器相關的代碼 +- transport -- 傳輸相關的代碼,包括網路傳輸和本地傳輸 +- resolver -- 解析器相關的代碼 +- resolver-dns -- DNS解析器相關的代碼
其中,參考使用ChannelInboundHandlerAdapter實現簡單的數據讀取處理,如下代碼所示:
public class NettyServerHandler extends ChannelInboundHandlerAdapter { private static final Logger log = LoggerFactory.getLogger(NettyServerHandler.class); @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { ByteBuf buf = (ByteBuf) msg; byte[] data = new byte[buf.readableBytes()]; buf.readBytes(data); String request = new String(data, "UTF-8"); log.info("Server received message: {}", request); ByteBuf resp = Unpooled.copiedBuffer("Hello, I'm server!", CharsetUtil.UTF_8); ctx.write(resp); ctx.flush(); } @Override public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { ctx.flush(); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { log.error("Exception caught: {}", cause.getMessage()); ctx.close(); } }
四、Netty4 TCP開發
使用Netty的TCP開發,可以讓我們非常輕鬆、高效、安全地實現TCP協議方面的開發工作。
下面是一個基於Netty4實現的TCP客戶端代碼示例:
public class NettyTcpClient { static final String HOST = System.getProperty("host", "127.0.0.1"); static final int PORT = Integer.parseInt(System.getProperty("port", "8080")); public static void main(String[] args) throws Exception { EventLoopGroup group = new NioEventLoopGroup(1); try { Bootstrap b = new Bootstrap(); b.group(group) .channel(NioSocketChannel.class) .handler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast(new NettyClientHandler()); } }); ChannelFuture f = b.connect(HOST, PORT).sync(); f.channel().closeFuture().sync(); } finally { group.shutdownGracefully(); } } }
五、Netty4核心原理
從底層分析Netty4的核心原理可以更好地幫助我們理解和使用Netty4。
Netty4的核心原理是基於NIO的非同步網路通信,NIO通過Selector機制在一組Channel中逐個輪詢事件,只有一個線程能夠輪詢並處理多個Channel,因此Netty4是通過NioEventLoop來負責I/O處理事件。
下面是NioEventLoop的源碼片段:
public void run() { while (!Thread.interrupted()) { try { // 通過selector來取到Channel int numReady = selectStrategy.calculateStrategy(selectNowSupplier, hasTasks()); // ... // 通過selector方式來獲取I/O事件 processSelectedKeys(); // 處理Channel上的所有I/O任務和定時任務 runAllTasks(); // ... } catch (Throwable t) { // ... } } // ... }
六、Netty4和5有什麼區別
Netty5相比於Netty4在某些方面進行了較大的改變,比如在編解碼器方面進行不同程度的優化、非同步API使用更加靈活等。
下面是Netty4和Netty5對比的一些區別:
1、Netty4採用EventLoop和EventExecutor分離的設計思路,而Netty5採用非同步的ActiveObject計算模型; 2、Netty5新增了一些基於HTTP/2協議的組件; 3、Netty5提供了更加靈活的非同步API機制,可以更精細地控制非同步事件的執行邏輯; 4、Netty5的通信協議棧進行了重新設計,比如在編解碼器方面進行了不同程度的優化; 5、Netty5底層的非同步事件處理引擎也進行了改進,更加適配不同場景的使用;
結語
Netty4是一個功能強大、易於使用、高性能的非同步網路編程框架,它提供了豐富的網路協議支持和超高的吞吐量,是目前業界最為流行的非同步網路編程框架之一。通過對Netty4的全方位解析,更加深入地理解Netty4的使用、原理和優勢。
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/241632.html