2016-12-31 10 views
1

送信者が1秒あたり10000リクエストを送信していますが、ServerSocketChannelは8000リクエスト(〜appx)しか読み取りおよび処理できません。Java NIOを使用して1000sの並行接続を処理する方法

public class NioReceiver { 
    private int port = -1; 
    private static String message = null; 
    public void receive() throws IOException { 
     // Get the selector 
     Selector selector = Selector.open(); 
     // Selector is open for making connection 
     // Get the server socket channel and register using selector 
     ServerSocketChannel SS = ServerSocketChannel.open(); 
     InetSocketAddress hostAddress = new InetSocketAddress(this.port); 
     SS.bind(hostAddress); 
     SS.configureBlocking(false); 
     int ops = SS.validOps(); 
     SelectionKey selectKy = SS.register(selector, ops, null); 
     for (;;) { 
      //Waiting for the select operation... 
      int noOfKeys = selector.select(); 
      // The Number of selected keys are: noOfKeys 
      Set selectedKeys = selector.selectedKeys(); 
      Iterator itr = selectedKeys.iterator(); 
      while (itr.hasNext()) { 
       ByteBuffer buffer = ByteBuffer.allocate(1024 * 60); 
       SelectionKey ky = (SelectionKey) itr.next(); 
       if (ky.isAcceptable()) { 
        // The new client connection is accepted 
        SocketChannel client = SS.accept(); 
        client.configureBlocking(false); 
        // The new connection is added to a selector 
        client.register(selector, SelectionKey.OP_READ); 
        // The new connection is accepted from the client: client 
       } else if (ky.isReadable()) { 
        // Data is read from the client 
        SocketChannel client = (SocketChannel) ky.channel(); 
        String output = null; 
        buffer.clear(); 
        int charRead = -1; 
        try { 
         charRead = client.read(buffer); 
        } catch (IOException e) { 
         continue; 
        } 
        if (charRead <= 0) { 
         // client closed 
         client.close(); 
        } else { 
         output = new String(buffer.array()); 
         message = output; 
         try { 
          new Thread(() -> { 
           processAndStore(message); 
          }).start(); 
         } catch (Exception e) { 
          System.err.println("Thread exception:::" + e.getMessage()); 
         } 
        } // else if of client.isConnected() 
       } // else if of ky.isReadable() 
       itr.remove(); 
      } // end of while loop 
     } // end of for loop 
    } 

    public void processAndStore(String output) { 
     String exchangeName = null; 
     String dataLine = null; 
     String Lines[] = output.split("\r\n"); 
     for (int i = 0; i < Lines.length; i++) { 
      if (Lines[i].contains("Host: ")) { 
       exchangeName = Lines[i].substring(6); 
      } 
      if (Lines[i].isEmpty()) { 
       dataLine = Lines[i + 1]; 
      } 
     } 
     StringBuffer updatedLastLine = null; 
     if (dataLine != null) { 
      if (dataLine.contains("POST")) { 
       updatedLastLine = new StringBuffer(dataLine.substring(0, dataLine.indexOf("POST"))); 
      } else { 
       updatedLastLine = new StringBuffer(dataLine); 
      } 
      if (!dataLine.equals("")) { 
       try { 
        if (updatedLastLine.lastIndexOf("}") != -1) { 
         updatedLastLine.replace(updatedLastLine.lastIndexOf("}"), updatedLastLine.lastIndexOf("}") + 1, ",\"name\":\"" + exchangeName 
           + "\"}"); 
        } else { 

         return; 
        } 
       } catch (StringIndexOutOfBoundsException e) { 
        System.out.println(updatedLastLine + "::" + dataLine); 
        System.out.println(e); 
       } 
       store(updatedLastLine.toString()); 
      } 
     } 
    } 

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

私は処理ロジックを削除していた場合、より多くの要求ではなく、すべてを受信することが可能である:

ダミーコードは次のようです。

すべての10000s着信要求を受信するようにコードを改善する方法を教えてください。

+5

高速コンピュータを購入しますか?規格外? --- 'processAndStore()'を呼び出すスレッドを1000個作成するのではなく、スレッドプール/メッセージキューを使用します。スレッドを開始するのは**高価です**。毎秒10000スレッドを開始しますか? * Yikes!* --- **プロファイルコード**は、推測ではなくボトルネックがどこにあるかを見ていますが、ここではいくつかの推測があります:1) 'StringBuffer'を使わず、' StringBuilder'を使います。 2) 'lastIndexOf("}} ")'を3回呼び出さないでください。 – Andreas

+0

NIOの目的は、必要なスレッドの数を減らすことです。あなたはメッセージを持っていないようです。あなたが何を求めているのか不明です。 – EJP

+0

okありがとうございました。私がやったことは、スレッドの作成を取り除いてパフォーマンスが少し向上したことです。また、「NIO」をスキップし、「netty」ベースの受信機と「SimpleChannelInboundHandler」を使用し、同じハードウェア構成でほぼすべての要求を受け取ることができました。 – desaiankitb

答えて

1

processAndStore()を呼び出すスレッドを1000個作成する代わりに、スレッドプール/メッセージキューを使用します。

スレッドの開始は、高価なです。

1秒間に10000スレッドを開始しますか? Yikes! @EJPとして

commentで述べている:

をNIOの目的は、必要なスレッドの数を減らすことです。あなたはメッセージを持っていないようです。ボトルネックがどこにあることに加えて


プロファイルあなたのコードではなく推測よりも、確認してください。

しかし、ここではいくつかの推測はとにかく、次のとおりです。

  1. StringBuilderを使用し、StringBufferを使用しないでください。
    理由:Difference between StringBuilder and StringBufferを参照してください。

  2. lastIndexOf("}")に3回電話をかけないでください。
    理由:lastIndexOf()は、比較的遅いので、順次検索です。 JVMは、複数の呼び出しを最適化するかどうかを決めることはできませんが、パフォーマンスが重要な場合は、依存しないでください。結果を変数に代入することで自分自身で行います。も参照してくださいDoes Java optimize method calls via an interface which has a single implementor marked as final?

+0

完璧!ありがとう、相棒。 – Gray

関連する問題