netty入門小程序

Netty的特性

  1. 設計統一的API,適用於不同的協議(阻塞和非阻塞)基於靈活、可擴展的事件驅動模型高度可定製的線程模型可靠的無連接數據Socket支持(UDP)
  2. 性能更好的吞吐量,低延遲更省資源儘量減少不必要的內存拷貝
  3. 安全完整的SSL/TLS和STARTTLS的支持能在Applet與Android的限制環境運行良好
  4. 健壯性不再因過快、過慢或超負載連接導致OutOfMemoryError不再有在高速網絡環境下NIO讀寫頻率不一致的問題
  5. 易用完善的JavaDoc,用戶指南和樣例簡潔簡單僅信賴於JDK1.5

Netty 在哪些行業得到了應用?

互聯網行業

隨着網站規模的不斷擴大,系統併發訪問量也越來越高,傳統基於 Tomcat 等 Web 容器的垂直架構已經無法滿足需求,需要拆分應用進行服務化,以提高開發和維護效率。從組網情況看,垂直的架構拆分之後,系統採用分佈式部署,各個節點之間需要遠程服務調用,高性能的 RPC 框架必不可少,Netty 作爲異步高性能的通信框架,往往作爲基礎通信組件被這些 RPC 框架使用。  

典型的應用有

阿里分佈式服務框架 Dubbo 的 RPC 框架使用 Dubbo 協議進行節點間通信,Dubbo 協議默認使用 Netty 作爲基礎通信組件,用於實現各進程節點之間的內部通信。它的架構圖如下:

這裏寫圖片描述

其中,服務提供者和服務消費者之間,服務提供者、服務消費者和性能統計節點之間使用 Netty 進行異步/同步通信。 

除了 Dubbo 之外,淘寶的消息中間件 RocketMQ 的消息生產者和消息消費者之間,也採用 Netty 進行高性能、異步通信。  

除了阿里系和淘寶系之外,很多其它的大型互聯網公司或者電商內部也已經大量使用 Netty 構建高性能、分佈式的網絡服務器。

遊戲行業

無論是手遊服務端、還是大型的網絡遊戲,Java 語言得到了越來越廣泛的應用。Netty 作爲高性能的基礎通信組件,它本身提供了 TCP/UDP 和 HTTP 協議棧,非常方便定製和開發私有協議棧。賬號登陸服務器、地圖服務器之間可以方便的通過 Netty 進行高性能的通信,架構示意圖如下:

這裏寫圖片描述

大數據領域

經典的 Hadoop 的高性能通信和序列化組件 Avro 的 RPC 框架,默認採用 Netty 進行跨節點通信,它的 Netty Service 基於 Netty 框架二次封裝實現。  
大數據計算往往採用多個計算節點和一個/N個彙總節點進行分佈式部署,各節點之間存在海量的數據交換。由於 Netty 的綜合性能是目前各個成熟 NIO 框架中最高的,因此,往往會被選中用作大數據各節點間的通信。

企業軟件

企業和 IT 集成需要 ESB,Netty 對多協議支持、私有協議定製的簡潔性和高性能是 ESB RPC 框架的首選通信組件。事實上,很多企業總線廠商會選擇 Netty 作爲基礎通信組件,用於企業的 IT 集成。

通信行業

Netty 的異步高性能、高可靠性和高成熟度的優點,使它在通信行業得到了大量的應用。

簡單實現服務器端和客戶端

NettyServer.java

package netty;

import org.jboss.netty.bootstrap.ServerBootstrap;    
import org.jboss.netty.channel.*;    
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;    
import org.jboss.netty.handler.codec.string.StringDecoder;    
import org.jboss.netty.handler.codec.string.StringEncoder;    

import java.net.InetSocketAddress;    
import java.util.concurrent.Executors;    

/**  
 * Author: yexx
 * 
 */    
public class NettyServer {    
    public static void main(String[] args) {    
        ServerBootstrap bootstrap = new ServerBootstrap(new NioServerSocketChannelFactory(Executors.newCachedThreadPool(), Executors.newCachedThreadPool()));    

        // Set up the default event pipeline.    
        bootstrap.setPipelineFactory(new ChannelPipelineFactory() {    
            @Override    
            public ChannelPipeline getPipeline() throws Exception {    
                return Channels.pipeline(new StringDecoder(), new StringEncoder(), new ServerHandler());    
            }    
        });    

        // Bind and start to accept incoming connections.    
        Channel bind = bootstrap.bind(new InetSocketAddress(8000));    
        System.out.println("Server已經啓動,監聽端口: " + bind.getLocalAddress() + ", 等待客戶端註冊。。。");    
    }    

    private static class ServerHandler extends SimpleChannelHandler {    
        @Override    
        public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {    
            if (e.getMessage() instanceof String) {    
                String message = (String) e.getMessage();    
                System.out.println("Client發來:" + message);    

                e.getChannel().write("Server已收到剛發送的:" + message);    

                System.out.println("\n等待客戶端輸入。。。");    
            }    

            super.messageReceived(ctx, e);    
        }    

        @Override    
        public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {    
            super.exceptionCaught(ctx, e);    
        }    

        @Override    
        public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {    
            System.out.println("有一個客戶端註冊上來了。。。");    
            System.out.println("Client:" + e.getChannel().getRemoteAddress());    
            System.out.println("Server:" + e.getChannel().getLocalAddress());    
            System.out.println("\n等待客戶端輸入。。。");    
            super.channelConnected(ctx, e);    
        }    
    }    
}   

NettyClient.java

package netty;

import org.jboss.netty.bootstrap.ClientBootstrap;    
import org.jboss.netty.channel.*;    
import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;    
import org.jboss.netty.handler.codec.string.StringDecoder;    
import org.jboss.netty.handler.codec.string.StringEncoder;    

import java.io.BufferedReader;    
import java.io.InputStreamReader;    
import java.net.InetSocketAddress;    
import java.util.concurrent.Executors;    

/**  
 * Author: yexx
 * 
 */    
public class NettyClient {    

    public static void main(String[] args) {    
        // Configure the client.    
        ClientBootstrap bootstrap = new ClientBootstrap(new NioClientSocketChannelFactory(Executors.newCachedThreadPool(), Executors.newCachedThreadPool()));    

        // Set up the default event pipeline.    
        bootstrap.setPipelineFactory(new ChannelPipelineFactory() {    
            @Override    
            public ChannelPipeline getPipeline() throws Exception {    
                return Channels.pipeline(new StringDecoder(), new StringEncoder(), new ClientHandler());    
            }    
        });    

        // Start the connection attempt.    
        ChannelFuture future = bootstrap.connect(new InetSocketAddress("localhost", 8000));    

        // Wait until the connection is closed or the connection attempt fails.    
        future.getChannel().getCloseFuture().awaitUninterruptibly();    

        // Shut down thread pools to exit.    
        bootstrap.releaseExternalResources();    
    }    

    private static class ClientHandler extends SimpleChannelHandler {    
        private BufferedReader sin = new BufferedReader(new InputStreamReader(System.in));    

        @Override    
        public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {    
            if (e.getMessage() instanceof String) {    
                String message = (String) e.getMessage();    
                System.out.println(message);    

                e.getChannel().write(sin.readLine());    

                System.out.println("\n等待客戶端輸入。。。");    
            }    

            super.messageReceived(ctx, e);    
        }    

        @Override    
        public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {    
            System.out.println("已經與Server建立連接。。。。");    
            System.out.println("\n請輸入要發送的信息:");    
            super.channelConnected(ctx, e);    

            e.getChannel().write(sin.readLine());    
        }    
    }    
}   

運行可以自己試一試

需要jar包

netty jar包

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章