2016-12-31 4 views
1

zu bedienen Mein Absender sendet 10000 Anfragen pro Sekunde (oder sogar mehr), aber meine ServerSocketChannel ist nur in der Lage zu lesen und zu verarbeiten (in Thread) 8000 Anfragen (~ appx).wie 1000s gleichzeitige Verbindung mit Java NIO

Dummy-Code ist wie folgt aus:

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; 
    } 
} 

Wenn ich Verarbeitungslogik bin Entfernen es in der Lage ist, mehr Anforderungen zu empfangen, aber nicht alle.

Wie kann ich meinen Code verbessern, um alle 10000 eingehenden Anfragen zu empfangen.

+5

Kaufen Sie einen schnelleren Computer? Scale out? --- Verwenden Sie eine Thread-Pool-/Nachrichtenwarteschlange, anstatt 1000 Threads zum Aufrufen von 'processAndStore()' zu erstellen. Das Starten eines Threads ist ** teuer **. 10000 Threads pro Sekunde starten? * Huch! * --- ** Profilcode **, um zu sehen, wo Engpaß ist, anstatt zu raten, aber hier sind einige Vermutungen trotzdem: 1) Verwenden Sie nicht 'StringBuffer', verwenden Sie' StringBuilder'. 2) Rufen Sie 'lastIndexOf ("} ")' nicht dreimal auf. – Andreas

+0

Der Zweck von NIO ist es, die Anzahl der erforderlichen Threads zu reduzieren. Du scheinst die Nachricht nicht zu haben. Unklar, was du verlangst. – EJP

+0

ok danke für rechtzeitige antworten. In der Zwischenzeit habe ich die Erstellung von Threads entfernt und die Performance ein wenig verbessert. Außerdem habe ich "NIO" übersprungen und benutze 'netty' basierte Empfänger und' SimpleChannelInboundHandler' und mit der gleichen Hardwarekonfiguration bin ich in der Lage fast alle Anfragen zu empfangen. – desaiankitb

Antwort

1

Verwenden Sie eine Thread-Pool-/Nachrichtenwarteschlange, anstatt 1000 Threads zum Aufrufen von processAndStore() zu erstellen.

Starten eines Threads ist teuer.

Starten von 10.000 Fäden pro Sekunde? Huch!

Wie gesagt @EJP in einem comment:

Der Zweck von NiO ist die Anzahl der erforderlichen Fäden zu verringern. Du scheinst die Nachricht nicht zu haben.


Zusätzlich zu, dass Profil Code, um zu sehen, wo der Engpass ist, anstatt zu raten.

Aber hier sind einige Vermutungen trotzdem:

  1. nicht StringBuffer, StringBuilder verwenden Verwenden Sie.
    Grund: Siehe Difference between StringBuilder and StringBuffer.

  2. Rufen Sie nicht lastIndexOf("}") dreimal.
    Grund:lastIndexOf() ist eine sequenzielle Suche, also relativ langsam. Die JVM kann die Mehrfachanrufe optimieren oder auch nicht, aber wenn die Leistung kritisch ist, verlassen Sie sich nicht darauf. Tun Sie es selbst, indem Sie der Variablen das Ergebnis zuweisen. Siehe auch Does Java optimize method calls via an interface which has a single implementor marked as final?

+0

Ja. Perfekt! Danke, Alter. – Gray

Verwandte Themen