Netty學習

一、Netty有必要學嗎

Netty是一個基於NIO的客戶端/服務端框架,用於開發網絡應用程序。相對於傳統的Java I/O,Netty提供了更好的性能、更好的可維護性和更好的可擴展性。學習Netty可以讓我們更加深入地理解網絡編程,還能夠在工作中運用到這個高性能的框架。

與其他的網絡編程框架相比,Netty在處理高並發、高吞吐量以及低延遲等方面有很大的優勢。如果我們需要開發高性能的網絡應用,並且在實際應用中跑得更快、更穩定,那麼學習Netty就是非常有必要的。

最後,在如今互聯網高速發展的背景下,網絡安全一直是人們關注的焦點。Netty提供了基於SSL的安全傳輸,可以保證數據在傳輸過程中的安全性。所以,即使我們不經常開發網絡應用程序,學習Netty也有一定的必要性。

二、Netty客戶端維護多個連接

在實際應用中,我們可能需要維護多個網絡連接,例如連接多個服務器進行數據交互。當使用傳統Java I/O時,每個網絡連接都需要一個線程來處理,如果連接數非常多,那麼就會出現線程數過多的問題,導致系統崩潰。但是在Netty中,我們可以使用連接池技術來解決這個問題,從而提高應用程序的性能和可靠性。

(一)連接池實現方式舉例


public class NettyConnectionPool {
  private static final String HOST = "127.0.0.1";
  private static final int PORT = 8080;
  
  private static EventLoopGroup group = new NioEventLoopGroup();
  private static Bootstrap bootstrap = new Bootstrap();
  private static final int MAX_POOL_SIZE = 10;
  private static final Queue<Channel> pool = new ConcurrentLinkedQueue<Channel>();
  
  // 初始化連接池
  static {
       bootstrap.group(group);
    bootstrap.channel(NioSocketChannel.class);
    bootstrap.option(ChannelOption.TCP_NODELAY, true);
    bootstrap.handler(new ChannelInitializer<SocketChannel>() {
      @Override
      public void initChannel(SocketChannel ch) throws Exception {
        ChannelPipeline pipeline = ch.pipeline();
        pipeline.addLast(new NettyClientHandler());
      }
    });
    while (pool.size() < MAX_POOL_SIZE) {
       pool.add(bootstrap.connect(HOST, PORT).channel());
     }
  }
  
  // 獲取連接
  public static Channel getConnection() {
    if (pool.isEmpty()) {
       return null;
    } else {
       return pool.poll();
    }
  }
  
  // 釋放連接
  public static void releaseConnection(Channel channel) {
    if (channel != null && pool.size() < MAX_POOL_SIZE) {
       pool.add(channel);
    } else {
       channel.close();
    }
  }
}

(二)連接池使用方式

使用連接池技術,我們可以更好地管理網絡連接,提高應用程序的性能和可靠性。


public class NettyClient {
  private static final int MAX_RETRY = 3;
  
  // 啟動連接
  public static void start() {
     Bootstrap bootstrap = new Bootstrap();
     EventLoopGroup group = new NioEventLoopGroup();
     bootstrap.group(group);
     bootstrap.channel(NioSocketChannel.class);
     bootstrap.option(ChannelOption.SO_KEEPALIVE, true);
     bootstrap.option(ChannelOption.TCP_NODELAY, true);
     bootstrap.handler(new ChannelInitializer<SocketChannel>() {
         @Override
         protected void initChannel(SocketChannel ch) throws Exception {
             ChannelPipeline pipeline = ch.pipeline();
             pipeline.addLast(new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 4, 0, 4));
             pipeline.addLast(new LengthFieldPrepender(4));
             pipeline.addLast(new StringDecoder(CharsetUtil.UTF_8));
             pipeline.addLast(new StringEncoder(CharsetUtil.UTF_8));
             pipeline.addLast(new NettyClientHandler());
        }
     });
     ChannelFuture future = connect(bootstrap, "127.0.0.1", 8080, MAX_RETRY);
     future.addListener(new ChannelFutureListener() {
         @Override
      public void operationComplete(ChannelFuture future) throws Exception {
        if (future.isSuccess()) {
          Channel channel = future.channel();
          NettyConnectionPool.releaseConnection(channel);
        } else {
          System.out.println("連接失敗!");
        }
   }
 });
 }
  
  // 連接或重連服務器
  private static ChannelFuture connect(Bootstrap bootstrap, String host, int port, int retry) {
     return bootstrap.connect(host, port).addListener(new ChannelFutureListener() {
         @Override
         public void operationComplete(ChannelFuture future) throws Exception {
             if (future.isSuccess()) {
                 System.out.println("連接成功!");
             } else if (retry == 0) {
                 System.out.println("重試次數已用完,放棄連接!");
             } else {
                 int order = (MAX_RETRY - retry) + 1;
                 int delay = 1 <
                         connect(bootstrap, host, port, retry - 1), delay, TimeUnit.SECONDS);
             }
         }
     });
 }
}

三、Netty的對象池技術

Netty的對象池技術是指在應用程序中,為了防止頻繁地創建對象而引入的一種技術方案。由於頻繁創建對象會導致申請和銷毀內存空間的開銷,從而影響應用程序的性能。因此,使用對象池技術可以大大地提高應用程序的性能。

(一)對象池實現方式舉例


public class NettyObjectPool {
  private static final int DEFAULT_POOL_SIZE = 10;
  private final int maxPoolSize;
  private final PoolObjectFactory factory;
  private final Deque pool;
  
  // 實現 PoolObjectFactory 接口
  public interface PoolObjectFactory<T> {
    T createObject();
     void destroyObject(T obj);
  }
  
  // 初始化對象池
  public NettyObjectPool(PoolObjectFactory factory) {
     this(DEFAULT_POOL_SIZE, factory);
  }
  
  public NettyObjectPool(int maxPoolSize, PoolObjectFactory factory) {
     this.maxPoolSize = maxPoolSize;
     this.factory = factory;
     this.pool = new ConcurrentLinkedDeque();
    for (int i = 0; i < maxPoolSize; i++) {
      pool.add(factory.createObject());
    }
  }
  
  // 獲取對象
  public Object borrowObject() {
    if (pool.isEmpty()) {
       return null;
    } else {
       return pool.pop();
    }
  }
  
  // 歸還對象
  public void returnObject(Object obj) {
    if (pool.size() >= maxPoolSize) {
       factory.destroyObject(obj);
    } else {
       pool.add(obj);
    }
  }
}

(二)對象池使用方式

使用對象池技術,我們可以更好地管理內存,減少內存分配和銷毀的開銷,提高應用程序的性能。


public class NettyClient {
  private static final NettyObjectPool<NettyClientHandler> handlerPool =
    new NettyObjectPool(MAX_POOL_SIZE, new NettyObjectPool.PoolObjectFactory<NettyClientHandler>() {
      @Override
      public NettyClientHandler createObject() {
        return new NettyClientHandler();
      }
      @Override
      public void destroyObject(NettyClientHandler handler) {
        handler = null;
      }
    });
  
  // 啟動連接
  public static void start() {
     Bootstrap bootstrap = new Bootstrap();
     EventLoopGroup group = new NioEventLoopGroup();
     bootstrap.group(group);
     bootstrap.channel(NioSocketChannel.class);
     bootstrap.option(ChannelOption.SO_KEEPALIVE, true);
     bootstrap.option(ChannelOption.TCP_NODELAY, true);
     bootstrap.handler(new ChannelInitializer<SocketChannel>() {
          @Override
          protected void initChannel(SocketChannel ch) throws Exception {
             ChannelPipeline pipeline = ch.pipeline();
             pipeline.addLast(new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 4, 0, 4));
             pipeline.addLast(new LengthFieldPrepender(4));
             pipeline.addLast(new StringDecoder(CharsetUtil.UTF_8));
             pipeline.addLast(new StringEncoder(CharsetUtil.UTF_8));
      NettyClientHandler handler = handlerPool.borrowObject();
      pipeline.addLast(handler);
      channel.attr(AttributeKey.valueOf("handler")).set(handler); // 將handler保存到channel的屬性中
         }
     });
     ChannelFuture future = connect(bootstrap, "127.0.0.1", 8080, MAX_RETRY);
     future.addListener(new ChannelFutureListener() {
         @Override
         public void operationComplete(ChannelFuture future) throws Exception {
             if (future.isSuccess()) {
                 System.out.println("連接成功!");
                 Channel channel = future.channel();
                 NettyClientHandler handler = (NettyClientHandler) channel.pipeline().last();
                 handlerPool.returnObject(handler); // 將handler對象歸還給對象池
             } else {
                 System.out.println("連接失敗!");
             }
         }
     });
 }
}

原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hk/n/233623.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
小藍的頭像小藍
上一篇 2024-12-11 17:10
下一篇 2024-12-11 17:11

相關推薦

  • gateway io.netty.buffer.poolchunk

    在本文中,我們將深入探討Netty中的一個基礎組件——PoolChunk,它是Netty中ByteBuf的一個關鍵實現,負責對ByteBuf進行緩存和管理。我們將從多個方面對該組件…

    編程 2025-04-28
  • 同時啟動兩個netty服務的實現方法

    本文將介紹如何同時啟動兩個netty服務的具體實現方法。 一、實現思路 為了同時啟動兩個netty服務,我們需要創建兩個不同的Channel,每個Channel都綁定到不同的服務端…

    編程 2025-04-27
  • netty和tomcat的比較

    一、簡介 Netty和Tomcat都是Java Web服務器,但它們的設計思想和應用場景不同。 Netty是一個高性能、異步事件驅動的網絡通信框架,可以用於實現WebSocket服…

    編程 2025-04-20
  • 深入理解Netty粘包

    一、什麼是粘包 網絡通信中消息的傳輸有兩個重要的問題,一個是粘包,一個是拆包。 粘包的概念就是發送方發送的多個小數據包被接收方一次性收到,這就像是把多個包「粘」在了一起。 造成粘包…

    編程 2025-04-12
  • Netty in Action:Java網絡編程的終極選擇

    一、基礎概念 Netty是由JBOSS的工程師Norman Maurer和Trustin Lee共同開發的,是一個高性能、異步、事件驅動的網絡編程框架。 相比於傳統的BIO(Blo…

    編程 2025-01-24
  • 深入探討Netty ByteBuf

    一、ByteBuf概述 在Netty中,ByteBuf是最基本、最核心的數據結構之一。實際上,Netty在設計時,就將ByteBuf作為數據處理的核心,因為I/O操作的數據流必定是…

    編程 2025-01-11
  • Netty面試題及答案詳解

    一、Netty面試題及答案 在Netty的面試過程中,會涉及到不少面試題,下面列舉並解答幾個比較常見的問題。 1、Netty是什麼? Netty是一個基於Java的NIO網絡編程框…

    編程 2024-12-23
  • 使用Android Netty輕鬆實現網絡通信

    一、什麼是Android Netty Android Netty是一個開源的,基於Java NIO的客戶端/服務器框架。Netty框架的出現使得開發者可以輕鬆地構建可維護和高性能協…

    編程 2024-12-22
  • Netty面試

    一、Netty面試題 Netty是一個高性能的網絡通信框架,它的出現使得網絡編程變得更加簡單和高效。以下是一些常見的Netty面試題: 1. 請簡要介紹Netty框架及其優點。 N…

    編程 2024-12-13
  • 如何使用Netty實現客戶端斷線重連

    一、Netty客戶端離線監聽 在Netty客戶端中,由於網絡原因,客戶端會與服務端斷開連接,但是我們希望客戶端能夠重新連接服務端,這就需要在客戶端中監聽客戶端是否處於離線狀態。 我…

    編程 2024-12-12

發表回復

登錄後才能評論