2015-10-15 37 views
1

我想創建多個客戶端連接到另一臺機器上的基於Java的套接字服務器。服務器和客戶端都使用Netty 4作爲NIO。在服務器端,我使用了boss和worker組,並且它能夠在單個linux機器上接收和服務100000個併發連接(在設置內核參數和ulimit之後)。Netty 4從客戶端創建多個連接

但是,我最終在客戶端的每個連接上創建了一個新線程,並導致JVM線程限制異常。

import io.netty.bootstrap.Bootstrap; 
import io.netty.channel.nio.NioEventLoopGroup; 
import io.netty.channel.socket.nio.NioSocketChannel; 
​ 
import java.util.ArrayList; 
import java.util.Collections; 
import java.util.List; 
import java.util.concurrent.CopyOnWriteArrayList; 
​ 
public class TelnetClient 
{ 
    private Bootstrap b; 
    private NioEventLoopGroup loopGroup; 
    private TelnetConnectionInitializer tci; 
​ 
​ 
    public static void main(String[] args) throws Exception 
    { 
     System.out.println("TelnetClient:main:enter " + args[0]); 
​ 
     TelnetClient tc = new TelnetClient(); 
​ 
     String countStr = args[0]; //number of connections to make 
     int count = Integer.valueOf(countStr); 
​ 
     for (int i=0; i < count; i++) 
     { 
      params.add(String.valueOf(i)); 
      Runnable r = new ClientThread(tc); 
      new Thread(r).start(); 
     } 
​ 
     System.out.println("TelnetClient:main:exit"); 
    } 
​ 
    public TelnetClient() 
    { 
     System.out.println("TelnetClient:TelnetClient"); 
     b = new Bootstrap(); 
     loopGroup = new NioEventLoopGroup(); 
     b = b.group(loopGroup); 
     b = b.channel(NioSocketChannel.class); 
     tci = new TelnetConnectionInitializer(); 
    } 
​ 
    public void connect(String host, int port) throws Exception { 
     System.out.println("TelnetClient:connect:enter"); 
​ 
     try { 
      b.handler(tci).connect(host, port).sync().channel().closeFuture().sync(); 
     } finally { 
      b.group().shutdownGracefully(); 
     } 
     System.out.println("TelnetClient:connect:exit"); 
    } 
} 
​ 
/// Creating a new thread per connection, 
/// Which seems the culprit of JVM exception, but couldn't found a way to implement boss/worker like solution on client side. 
class ClientThread implements Runnable 
{ 
    TelnetClient myTc; 
​ 
    public ClientThread(TelnetClient tc) 
    { 
     myTc = tc; 
    } 
​ 
    public void run() 
    { 
     System.out.println("ClientThread:run"); ​ 
     try 
     { 
      myTc.connect("192.168.1.65", 4598); //Server running on different machine in local network 
     } catch (Exception e) 
     { 
      e.printStackTrace(); 
     } 
    } 
} 

有人可以指出,我怎麼可以從客戶端使用Netty創建多個連接,而不會產生每個客戶端的新線程。我嘗試了一個且僅在another post on stack overflow中發現類似條件的代碼片段,但在此之後,對於我自己執行第一次成功連接後,暫停(進入無限等待狀態)。

感謝

+0

您可以啓動多少線程取決於您的PC容量。要麼你必須擴展你的內存,或者在某些時候你必須面對這個問題。 Netty的問題不在於它使用的線程模型。如果您想保留當前的RAM並接受許多連接,請使用Node.js,如併發模型。 – kazisami

+0

@kazisami,謝謝你的回答。我理解操作系統和硬件強加的最大線程限制。然而,我的問題是關於使用Netty框架打開NIO套接字連接時明智地使用線程。在我的理解中,Netty是事件驅動的,所以它應該提供像併發模型這樣的節點js。唯一的問題,我無法找到相同的示例/文檔,因此在這裏尋找幫助。 – devilzk83

+0

您是否嘗試過使用連接池? – Sudheera

回答

0

代碼看起來是正確的除了兩個重要的事情 - 你必須通過所有的客戶端共享網狀背景和異步工作。

I.e.在開始時初始化EvenetLoopGroup,並將此單個實例傳遞給每個客戶端對Bootstrap.group()的每次調用。

對於異步aproach避免connect()未來(不那麼重要)和主要關閉()將來的同步()。後者代碼被暫停,直到連接關閉。

+0

我會試一試並回復 – devilzk83

+0

試過,但無法讓它工作。 – devilzk83

+0

發佈更新的代碼。你是否避免了所有這些同步()?注意客戶端初始化的最後一次調用必須是connect()。其他的一切都將在處理程序中異步處理。 –