乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      Netty原理和使用

       知識存儲館 2014-07-24

      性能主題

      Netty原理和使用

        Netty是一個(gè)高性能 事件驅(qū)動(dòng)的異步的非堵塞的IO(NIO)框架,用于建立TCP等底層的連接,基于Netty可以建立高性能的Http服務(wù)器。支持HTTP、 WebSocket 、Protobuf、 Binary TCP |和UDP,Netty已經(jīng)被很多高性能項(xiàng)目作為其Socket底層基礎(chǔ),如HornetQ Infinispan Vert.x
      Play Framework Finangle和 Cassandra。其競爭對手是:Apache MINA和 Grizzly。

         傳統(tǒng)堵塞的IO讀取如下:

      InputStream is = new FileInputStream("input.bin");
      int byte = is.read(); // 當(dāng)前線程等待結(jié)果到達(dá)直至錯(cuò)誤

         而使用NIO如下:

      while (true) {
       selector.select(); // 從多個(gè)通道請求事件
       Iterator it = selector.selectedKeys().iterator();
       while (it.hasNext()) {
        SelectorKey key = (SelectionKey) it.next();
        handleKey(key);
        it.remove();
       }

      堵塞與非堵塞原理

        傳統(tǒng)硬件的堵塞如下,從內(nèi)存中讀取數(shù)據(jù),然后寫到磁盤,而CPU一直等到磁盤寫完成,磁盤的寫操作是慢的,這段時(shí)間CPU被堵塞不能發(fā)揮效率。

        使用非堵塞的DMA如下圖:CPU只是發(fā)出寫操作這樣的指令,做一些初始化工作,DMA具體執(zhí)行,從內(nèi)存中讀取數(shù)據(jù),然后寫到磁盤,當(dāng)完成寫后發(fā)出一個(gè)中斷事件給CPU。這段時(shí)間CPU是空閑的,可以做別的事情。這個(gè)原理稱為Zero.copy零拷貝。

        Netty底層基于上述Java NIO的零拷貝原理實(shí)現(xiàn):

      比較

      • Tomcat是一個(gè)Web服務(wù)器,它是采取一個(gè)請求一個(gè)線程,當(dāng)有1000客戶端時(shí),會耗費(fèi)很多內(nèi)存。通常一個(gè)線程將花費(fèi) 256kb到1mb的stack空間。
      • Node.js是一個(gè)線程服務(wù)于所有請求,在錯(cuò)誤處理上有限制
      • Netty是一個(gè)線程服務(wù)于很多請求,如下圖,當(dāng)從Java NIO獲得一個(gè)Selector事件,將激活通道Channel。

      演示

      Netty的使用代碼如下:

      Channel channel = ...
      ChannelFuture cf = channel.write(data);
      cf.addListener(
        new ChannelFutureListener() {
         @Override
         public void operationComplete(ChannelFuture future) throws Exception {
           if(!future.isSuccess() {
              future.cause().printStacktrace();
              ...
           }
           ...
         }
      });
      ...
      cf.sync();

      通過引入觀察者監(jiān)聽,當(dāng)有數(shù)據(jù)時(shí),將自動(dòng)激活監(jiān)聽者中的代碼運(yùn)行。

      我們使用Netty建立一個(gè)服務(wù)器代碼:

      public class EchoServer {

          private final int port;

          public EchoServer(int port) {
              this.port = port;
          }

          public void run() throws Exception {
              // Configure the server.
              EventLoopGroup bossGroup = new NioEventLoopGroup();
              EventLoopGroup workerGroup = new NioEventLoopGroup();
              try {
                  ServerBootstrap b = new ServerBootstrap();
                  b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class).option(ChannelOption.SO_BACKLOG, 100)
                         .handler(new LoggingHandler(LogLevel.INFO)).childHandler(new ChannelInitializer<SocketChannel>() {
                             @Override
                             public void initChannel(SocketChannel ch) throws Exception {
                                 ch.pipeline().addLast(
                                 // new LoggingHandler(LogLevel.INFO),
                                         new EchoServerHandler());
                             }
                         });

                  // Start the server.
                  ChannelFuture f = b.bind(port).sync();

                  // Wait until the server socket is closed.
                  f.channel().closeFuture().sync();
              } finally {
                  // Shut down all event loops to terminate all threads.
                  bossGroup.shutdownGracefully();
                  workerGroup.shutdownGracefully();
              }
          }

         
      }

      這段代碼調(diào)用:在9999端口啟動(dòng)

      new EchoServer(9999).run();

      我們需要完成的代碼是EchoServerHandler

      public class EchoServerHandler extends ChannelInboundHandlerAdapter {

          private static final Logger logger = Logger.getLogger(EchoServerHandler.class.getName());

          @Override
          public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
              ctx.write(msg);
          }

          @Override
          public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
              ctx.flush();
          }

          @Override
          public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
              // Close the connection when an exception is raised.
              logger.log(Level.WARNING, "Unexpected exception from downstream.", cause);
              ctx.close();
          }
      }

      原理

         一個(gè)Netty服務(wù)器的原理如下:

        圖中每次請求的讀取是通過UpStream來實(shí)現(xiàn),然后激活我們的服務(wù)邏輯如EchoServerHandler,而服務(wù)器向外寫數(shù)據(jù),也就是響應(yīng)是通過DownStream實(shí)現(xiàn)的。每個(gè)通道Channel包含一對UpStream和DownStream,以及我們的handlers(EchoServerHandler),如下圖,這些都是通過channel pipeline封裝起來的,數(shù)據(jù)流在管道里流動(dòng),每個(gè)Socket對應(yīng)一個(gè)ChannelPipeline。

       

         CHANNELPIPELINE是關(guān)鍵,它類似Unix的管道,有以下作用:

      • 為每個(gè)Channel 保留 ChannelHandlers ,如EchoServerHandler
      • 所有的事件都要通過它
      • 不斷地修改:類似unix的SH管道: echo "Netty is shit...." | sed -e 's/is /is the /'
      • 一個(gè)Channel對應(yīng)一個(gè) ChannelPipeline
      • 包含協(xié)議編碼解碼 安全驗(yàn)證SSL/TLS和應(yīng)用邏輯

       

      客戶端代碼

        前面我們演示了服務(wù)器端代碼,下面是客戶端代碼:

      public class EchoClient {
          private final String host;
          private final int port;
          private final int firstMessageSize;

          public EchoClient(String host, int port, int firstMessageSize) {
              this.host = host;
              this.port = port;
              this.firstMessageSize = firstMessageSize;
          }

          public void run() throws Exception {
              // Configure the client.
              EventLoopGroup group = new NioEventLoopGroup();
              try {
                  Bootstrap b = new Bootstrap();
                 b.group(group).channel(NioSocketChannel.class).option(ChannelOption.TCP_NODELAY, true).handler(new ChannelInitializer<SocketChannel>() {
                      @Override
                      public void initChannel(SocketChannel ch) throws Exception {
                         ch.pipeline().addLast(
                         // new LoggingHandler(LogLevel.INFO),
                                 new EchoClientHandler(firstMessageSize));
                      }
                  });

                  // Start the client.
                  ChannelFuture f = b.connect(host, port).sync();

                  // Wait until the connection is closed.
                  f.channel().closeFuture().sync();
              } finally {
                  // Shut down the event loop to terminate all threads.
                  group.shutdownGracefully();
              }
          }
      }

      客戶端的應(yīng)用邏輯EchoClientHandler

      public class EchoClientHandler extends ChannelInboundHandlerAdapter {

          private static final Logger logger = Logger.getLogger(EchoClientHandler.class.getName());

          private final ByteBuf firstMessage;

          /**
           * Creates a client-side handler.
           */
          public EchoClientHandler(int firstMessageSize) {
              if (firstMessageSize <= 0) {
                  throw new IllegalArgumentException("firstMessageSize: " + firstMessageSize);
              }
              firstMessage = Unpooled.buffer(firstMessageSize);
              for (int i = 0; i < firstMessage.capacity(); i++) {
                  firstMessage.writeByte((byte) i);
              }
          }

          @Override
          public void channelActive(ChannelHandlerContext ctx) {
              ctx.writeAndFlush(firstMessage);
              System.out.print("active");
          }

          @Override
          public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
              ctx.write(msg);
              System.out.print("read");
          }

          @Override
          public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
              ctx.flush();
              System.out.print("readok");
          }

          @Override
          public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
              // Close the connection when an exception is raised.
              logger.log(Level.WARNING, "Unexpected exception from downstream.", cause);
              ctx.close();
          }

      }

       

      Java NIO原理和使用

      NodeJS入門

      vertx入門教程

      Netty作者談Java性能優(yōu)化要點(diǎn)

      2

      banq   2014-07-22    1討論    180瀏覽

      Orleans 是微軟推出的類似Scala Akka的Actor模型,可用于實(shí)現(xiàn) DDD +EventSourcing/CQRS系統(tǒng)。 Orlea....

      banq   2014-07-20    0討論    699瀏覽

      國內(nèi)大部分號稱 云計(jì)算 的產(chǎn)品基本是主機(jī)托管+數(shù)據(jù)中心,很多人認(rèn)為 ....

      banq   2014-07-16    1討論    722瀏覽

      這是一篇討論客戶端MVC和服務(wù)器端MVC的比較文章。 首先分離關(guān)注是架構(gòu)設(shè)計(jì)的一個(gè)基本原則,多層架構(gòu)中:數(shù)據(jù)存儲 服務(wù)層 API層和表現(xiàn)層各層之間應(yīng)該最小依賴,服務(wù)層只需要知道在哪里存儲數(shù)據(jù),A....

      banq   2014-07-08    0討論    1127瀏覽

      一位Node.js guru大牛 TJ Holowaychuk最近發(fā)表了 再會Node.js ,他曾經(jīng)是Empress, Mocha, Jade, Stylus Koa等參與者,TJ在這篇宣言中首先強(qiáng)....

      banq   2014-07-05    8討論    1300瀏覽

      這是來自ScalaDays 2014大會上有關(guān)如何使用 DDD EventSourcing/CQRS和Akka構(gòu)建一個(gè)reactive的微服務(wù)應(yīng)用系統(tǒng)的演講,大意如下, ..




        本站是提供個(gè)人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多