Netty

前言:

 

高效能的三大主題:

1) 傳輸:用什麽樣的通道將數據發送給對方,BIO、NIO或者AIO,IO模型在很大程度上決定了框架的效能。

2) 協定:采用什麽樣的通信協定,HTTP或者內部私有協定。協定的選擇不同,效能模型也不同。相比于公有協定,內部私有協定的效能通常可以被設計的更優。

3) 線程:數據報如何讀取?讀取之後的編解碼在哪個線程進行,編解碼後的消息如何派發,Reactor線程模型的不同,對效能的影響也非常大。

Netty 高效能的表現:

1.  異步非阻塞通信

2.  零拷貝

1)  Netty的接收和發送ByteBuffer采用DIRECT BUFFERS,使用堆外直接記憶體進行Socket讀寫,不需要進行字節緩沖區的二次拷貝

2) Netty提供了組合Buffer對象,可以聚合多個ByteBuffer對象,用戶可以像操作一個Buffer那樣方便的對組合Buffer進行操作,避免系統統通過記憶體拷貝的方式將幾個小Buffer合並成一個大的Buffer。

3) Netty的文件傳輸采用了transferTo方法,它可以直接將文件緩沖區的數據發送到目標Channel,避免了傳統通過循環write方式導致的記憶體拷貝問題。

 

3.  記憶體池

4.  高效的Reactor線程模型

5.  無鎖化的串行設計理念

6.  高效的並發編程

7.  高效能的序列化框架

8.  靈活的TCP參數配置能力

 

 

 

 

Netty 服務端創建(詳細解析):

  1. 創建TimeService

代碼如下:

package cn.zxm.netty.demo;

 

import io.netty.bootstrap.ServerBootstrap;

import io.netty.channel.ChannelFuture;

import io.netty.channel.ChannelInitializer;

import io.netty.channel.ChannelOption;

import io.netty.channel.ChannelPipeline;

import io.netty.channel.EventLoopGroup;

import io.netty.channel.nio.NioEventLoopGroup;

import io.netty.channel.socket.SocketChannel;

import io.netty.channel.socket.nio.NioServerSocketChannel;

import io.netty.handler.codec.DelimiterBasedFrameDecoder;

import io.netty.handler.codec.Delimiters;

import io.netty.handler.codec.string.StringDecoder;

import io.netty.handler.codec.string.StringEncoder;

 

/**

 * Time Netty服務端

 *

 * @author zhouxm@inspur.com

 *

 */

publicclassTimeService {

   publicvoid bind(intport) throws Exception {

      // 配置NIO服務端線程組

      EventLoopGroup bossGroup = new NioEventLoopGroup();// 用于服務端接收客戶端的鏈接

      EventLoopGroup workGroup = new NioEventLoopGroup();// 用于SocketChannel網路讀寫

      try {

         // 創建NIO服務端輔助啓動類

         ServerBootstrap b = new ServerBootstrap();

         b.group(bossGroup, workGroup).channel(NioServerSocketChannel.class)

                .option(ChannelOption.SO_BACKLOG, 1024)

                .childHandler(new ChildChannelHander());

         // 綁定監聽端口,同步等待成功

         ChannelFuture f = b.bind(port).sync();

         // 等待監聽端口關閉

         f.channel().closeFuture().sync();

         // b.bind(port).sync().channel().closeFuture().sync();//也可以這樣將上面兩步驟合並,使代碼更簡潔

      } finally {

         // 退出,釋放線程池資源

         bossGroup.shutdownGracefully();

         workGroup.shutdownGracefully();

      }

   }

 

   // 用戶處理網路IO事件,類似于Reactor模式中的handle例:消息編解碼日志列印

   privateclass ChildChannelHander extends ChannelInitializer<SocketChannel> {

      @Override

      protectedvoid initChannel(SocketChannel arg0) throws Exception {

         // TODO Auto-generated method stub

         ChannelPipeline pipeline = arg0.pipeline();

         // ("\n")爲結尾分割的解碼器

         pipeline.addLast("framer", new DelimiterBasedFrameDecoder(8192,

                Delimiters.lineDelimiter()));

         // 字符串解碼編碼

         pipeline.addLast("decoder", new StringDecoder());

         pipeline.addLast("encoder", new StringEncoder());

         // 自己的邏輯Handler

         pipeline.addLast("handler", new TimeServerHander());

      }

 

   }

publicstaticvoid main(String args[]){

      intport = 8080;

      try {

         new TimeService().bind(port);

      } catch (Exception e) {

         // TODO Auto-generated catch block

         e.printStackTrace();

      }

   }

}

  1. TimeServerHander

代碼如下:

package cn.zxm.netty.demo;

 

import io.netty.buffer.ByteBuf;

import io.netty.buffer.Unpooled;

import io.netty.channel.ChannelHandlerAdapter;

import io.netty.channel.ChannelHandlerContext;

 

/**

 * 邏輯handle

 *

 * @author zhouxm@inspur.com

 *

 */

publicclassTimeServerHander extends ChannelHandlerAdapter {

 

   /*

    * (non-Javadoc)

    *

    * @see

    * io.netty.channel.ChannelHandlerAdapter#channelActive(io.netty.channel

    * .ChannelHandlerContext)

    */

   @Override

   publicvoid channelActive(ChannelHandlerContext ctx) throws Exception {

      // TODO Auto-generated method stub

      super.channelActive(ctx);

   }

 

   /*

    * (non-Javadoc)

    *

    * @see io.netty.channel.ChannelHandlerAdapter#channelRead(io.netty.channel.

    * ChannelHandlerContext, java.lang.Object)

    */

   @Override

   publicvoid channelRead(ChannelHandlerContext ctx, Object msg)

         throws Exception {

      // TODO Auto-generated method stub

      ByteBuf buf = (ByteBuf) msg;// msg轉換成Netty ByteBuf 類似于jdk中的ByteBuffer

      byte[] req = newbyte[buf.readableBytes()];// 根據字節數創建byte數組

      buf.readBytes(req);// 將緩沖區中的字節數組複制到 byte數組中

      String body = new String(req, "utf-8");// 創建構造函數接收消息

      System.out.print("client send message :" + body);// 列印

      String resString = "response msg to client ";

      ByteBuf b = Unpooled.copiedBuffer(resString.getBytes());

      ctx.write(b);// 發送消息給客戶端

   }

 

   /*

    * (non-Javadoc)

    *

    * @see

    * io.netty.channel.ChannelHandlerAdapter#channelReadComplete(io.netty.channel

    * .ChannelHandlerContext)

    */

   @Override

   publicvoid channelReadComplete(ChannelHandlerContext ctx) throws Exception {

      // TODO Auto-generated method stub

      ctx.flush();// 將隊列中的消息寫入到SocketChannel發送給客戶端

   }

 

   /*

    * (non-Javadoc)

    *

    * @see

    * io.netty.channel.ChannelHandlerAdapter#exceptionCaught(io.netty.channel

    * .ChannelHandlerContext, java.lang.Throwable)

    */

   @Override

   publicvoid exceptionCaught(ChannelHandlerContext ctx, Throwable cause)

         throws Exception {

      // TODO Auto-generated method stub

      ctx.close();// 關閉,釋放資源

   }

 

}

 

 

 

 

 

 

 

 

 

 

 

 

創建Netty客戶端:

一.創建TimeClient:

package cn.zxm.netty.demo;

 

import io.netty.bootstrap.Bootstrap;

import io.netty.channel.ChannelFuture;

import io.netty.channel.ChannelInitializer;

import io.netty.channel.ChannelOption;

import io.netty.channel.ChannelPipeline;

import io.netty.channel.EventLoopGroup;

import io.netty.channel.nio.NioEventLoopGroup;

import io.netty.channel.socket.SocketChannel;

import io.netty.channel.socket.nio.NioSocketChannel;

import io.netty.handler.codec.DelimiterBasedFrameDecoder;

import io.netty.handler.codec.Delimiters;

import io.netty.handler.codec.string.StringDecoder;

import io.netty.handler.codec.string.StringEncoder;

 

publicclass TimeClient {

   publicvoid connect(String host, intport) throws Exception {

      // 配置客戶端NIO線程組

      EventLoopGroup group = new NioEventLoopGroup();

      try {

         // 創建NIO客戶端輔助啓動類

         Bootstrap b = new Bootstrap();

         b.group(group).channel(NioSocketChannel.class)

                .option(ChannelOption.TCP_NODELAY, true)

                .handler(new ClientTimeHander());

         //發起異步鏈接操作

         ChannelFuture f = b.connect(host, port).sync();

         //等待客戶端鏈路關閉

         f.channel().closeFuture().sync();

      } finally {

         group.shutdownGracefully();// 關閉  釋放資源

      }

   }

 

   privateclass ClientTimeHander extends ChannelInitializer<SocketChannel> {

      @Override

      protectedvoid initChannel(SocketChannel arg0) throws Exception {

         // TODO Auto-generated method stub

         ChannelPipeline pipeline = arg0.pipeline();

         // ("\n")爲結尾分割的解碼器

         pipeline.addLast("framer", new DelimiterBasedFrameDecoder(8192,

                Delimiters.lineDelimiter()));

         // 字符串解碼編碼

         pipeline.addLast("decoder", new StringDecoder());

         pipeline.addLast("encoder", new StringEncoder());

         // 自己的邏輯Handler

         pipeline.addLast("handler", new TimeClientHander());

      }

 

   }

 

   publicstaticvoid main(String[] args) {

      // TODO Auto-generated method stub

      String  host = "localhost";

      int     port = 8080;

      try {

         new TimeClient().connect(host, port);

      } catch (Exception e) {

         // TODO Auto-generated catch block

         e.printStackTrace();

      }

   }

 

}

 

二.創建TimeClientHander:

 

package cn.zxm.netty.demo;

 

import io.netty.buffer.ByteBuf;

import io.netty.buffer.Unpooled;

import io.netty.channel.ChannelHandlerAdapter;

import io.netty.channel.ChannelHandlerContext;

 

publicclass TimeClientHander extends ChannelHandlerAdapter{

   

   privatefinal ByteBuf firstMsg;

   public TimeClientHander(){

      byte[] req = "send msg to server date".getBytes();

      firstMsg = Unpooled.buffer(req.length);

      firstMsg.writeBytes(req);

   }

   /* (non-Javadoc)

    * @see io.netty.channel.ChannelHandlerAdapter#channelActive(io.netty.channel.ChannelHandlerContext)

    */

   @Override

   publicvoid channelActive(ChannelHandlerContext ctx) throws Exception {

      // TODO Auto-generated method stub

      ctx.writeAndFlush(firstMsg);

   }

 

   /* (non-Javadoc)

    * @see io.netty.channel.ChannelHandlerAdapter#channelRead(io.netty.channel.ChannelHandlerContext, java.lang.Object)

    */

   @Override

   publicvoid channelRead(ChannelHandlerContext ctx, Object msg)

         throws Exception {

      // TODO Auto-generated method stub

      ByteBuf buf = (ByteBuf) msg;// msg轉換成Netty ByteBuf 類似于jdk中的ByteBuffer

      byte[] req = newbyte[buf.readableBytes()];// 根據字節數創建byte數組

      buf.readBytes(req);// 將緩沖區中的字節數組複制到 byte數組中

      String body = new String(req, "utf-8");// 創建構造函數接收消息

      System.out.print("server send message :" + body);// 列印

   }

 

   /* (non-Javadoc)

    * @see io.netty.channel.ChannelHandlerAdapter#exceptionCaught(io.netty.channel.ChannelHandlerContext, java.lang.Throwable)

    */

   @Override

   publicvoid exceptionCaught(ChannelHandlerContext ctx, Throwable cause)

         throws Exception {

      // TODO Auto-generated method stub

      ctx.close();

   }

 

}

 

更多相關文章
  • 前言今年7月份左右報名參加了阿裏巴巴組織的高效能中間件挑戰賽,這次比賽不像以往的比賽,是從一個工程的視角來比賽的. 這個比賽有兩個賽題,第一題是實現一個RPC框架,第二道題是實現一個Mom消息中間件. RPC題目如下一個簡單的RPC框架 RPC(Remote Procedure Call )--遠程 ...
  • 代碼地址 http://git.oschina.net/yunnysunny/summercool-hsf引用: 筆者工作的這幾年之中,總結並開發了如下幾個框架: summercool( Web框架,已經應用于某國內大型網路公司的等重要應用).summercool-hsf(基于Netty實現的RPC ...
  • 利用netty寫了一個簡單的RPC框架,純粹是爲了理解RPC框架.使用protostuff 1.07 序列化,以netty 3.2.1 網路框架.下載地址:https://github.com/stefzhlg/snrpc##How to use e.g.1,server class;   inte ...
  • Netty系列之Netty高效能之道
    1. 背景1.1. 驚人的效能數據最近一個圈內朋友通過私信告訴我,通過使用Netty4 + Thrift壓縮二進制編解碼技術,他們實現了10W TPS(1K的複雜POJO對象)的跨節點遠程服務調用.相比于傳統基于Java序列化+BIO(同步阻塞IO)的通信框架,效能提升了8倍多.事實上,我對這個數據 ...
  • netty是繼mina之後一個非常受歡迎的nio網路框架(其實netty的主程就是mina的主程).其實netty的介紹就不說了,去看專案介紹吧,直接上代碼httpserver啓動和配置類 import static org.jboss.netty.channel.Channels.pipeline ...
  • Netty教程
    摘自Netty官網: "Netty是一個NIO C/S框架,能夠快速.簡單的開發協定伺服器和客戶端等網路應用.它能夠很大程度上簡單化.流水線化開發網路應用,例如TCP/UDP socket伺服器." Netty是一個主要用于編寫高並發網路系統.網路應用和服務的Java庫.Nett ...
  • 我的netty筆記
    1.簡介 Java1.4提供了NIO使開發者可以使用Java編寫高效能的服務端程序,但使用原生的NIO API就像Linux C中網路編程一樣,還是需要做IO處理.協定處理等低層次工作.所以,就像C服務端程序大量使用libevent作爲網路應用框架一樣,Java社區也不斷湧現出基于NIO的網路應用框 ...
  • tomcat、netty以及nodejs的helloworld效能對比
    最近閑來無事,對tomcat.netty以及nodejs的效能對比比較有興趣,于是自行測試了一下. 測試環境: 測試工具:Apache JMeter2.9 測試代碼: tomcat下的jsp: <%@page language="java" contentType=&quo ...
  • netty 學習 2Handler的執行順序
    Handler在netty中,無疑占據著非常重要的地位.Handler與Servlet中的filter很像,通過Handler可以完成通訊報文的解碼編碼.攔截指定的報文.統一對日志錯誤進行處理.統一對請求進行計數.控制Handler執行與否.一句話,沒有它做不到的只有你想不到的. Netty中的所有 ...
一周排行
  • 零.  前言簡單的查詢一般都使用 HQL , 開發效率會比較高, 但是複雜的查詢如果前期用 HQL , 那麽後期出現慢查詢, 就不得不用 原生 SQL 重寫一遍, 要是濫用 HQL 返回各種對象, 用對象到處操作, ...
  • Linux時區相關1. 查看當前時區# vi /etc/sysconfig/clock# date -u# date -R2. 修改設置時區 方法(1)   tzselect  方法(2) 僅限于RedHat Lin ...
  • deb http://mirrors.163.com/ubuntu/ raring main universe restricted multiversedeb-src http://mirrors.163.com/ ...
  • SSH進階之路Hibernate映射一對多關聯映射七
    上上篇博文[SSH進階之路]Hibernate映射--一對一單向關聯映射(五),我們介紹了 ...
  • Hadoop一理論體系
        隨著人民生活水平的提高,隨著各種各類數據指數級的增長,"大數據" ...
  • 話說我們專案決定把遊戲數據靜態文件都從csv讀取,所以就寫了這個類了,非常簡單的,可以把csv的一行映射到一個pojo上上代碼!!import java.io.BufferedReader;import java.i ...
  • 當你學不進去的時候,不妨看看大腦是怎麽想的?  http://anforen.5d6d.com/ 1.大腦喜歡色彩.平時使用高質量的有色筆或使用有色紙,顔色能幫助記憶.  2.大腦集中精力最多只有25分鍾.這是對成人 ...
  • 小專案中發現的問題,糾結了半天: 問題原因: 同步請求,返回的是NSData類型 查了好久,有的寫NSDictionary寫擴展還有其他的什麽歸檔啥的,沒一個好使.最後發現利用JSon中轉做的這個方法成功了.記錄一下 ...
  • 部署及配置第二台CAS/HUB伺服器
               部署完第一台Exchange2010的CAS/HUB伺服器之後,接下 ...
  • ResultServlet.java:package com.you.servlet; import java.io.IOException; import java.io.PrintWriter; import j ...