2016-12-31 1 views
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; 
    } 
} 

내가 처리 로직을 제거하고 때 더 많은 요청 전부는 아니지만을받을 수있다.

들어오는 요청을 모두받는 코드를 개선하려면 어떻게해야합니까?

+5

더 빠른 컴퓨터를 사십시오? 스케일 아웃? ---'processAndStore()'를 호출하기 위해 1000 개의 쓰레드를 생성하는 대신 쓰레드 풀/메시지 큐를 사용하십시오. 스레드를 시작하는 것은 ** 고비용 **입니다. 초당 10000 개의 스레드를 시작 하시겠습니까? * Yikes! * --- ** 프로파일 코드 **는 추측보다는 병목 현상을 파악하지만 어쨌든 여기서는 추측 할 수 있습니다. 1)'StringBuffer'를 사용하지 말고'StringBuilder'를 사용하십시오. 2)'lastIndexOf ("}}")'를 세 번 호출하지 마십시오. – Andreas

+0

NIO의 목적은 필요한 스레드의 수를 줄이는 것입니다. 당신은 그 메시지를 가지고 있지 않은 것 같습니다. 네가 묻고있는 것이 불분명하다. – EJP

+0

알맞은 답변을 주셔서 감사합니다. 그 동안 내가 한 일은 스레드 생성을 제거하고 성능을 약간 향상 시켰습니다. 또한, 'NIO'를 건너 뛰고 'netty'기반의 수신기와 'SimpleChannelInboundHandler'를 사용했으며 동일한 하드웨어 구성으로 거의 모든 요청을받을 수있었습니다. – desaiankitb

답변

1

processAndStore()을 호출하기 위해 1000 개의 스레드를 만드는 대신 스레드 풀/메시지 큐를 사용하십시오.

스레드 시작은 입니다.

초당 10000 개의 스레드를 시작 하시겠습니까? Yikes!

는 @EJP는 comment에서 말했듯이 :

NIO의 목적은 필요한 스레드의 수를 줄이는 것입니다. 당신은 그 메시지를 가지고 있지 않은 것 같습니다. 병목이 어디 그 외에도


, 프로필 코드 오히려 추측보다 볼 수 있습니다.

하지만, 여기에 몇 가지 추측은 어쨌든 있습니다

  1. StringBuilder를 사용 StringBuffer를 사용하지 마십시오.
    이유 :Difference between StringBuilder and StringBuffer을 참조하십시오.

  2. lastIndexOf("}") 번으로 전화하지 마십시오.
    이유 :lastIndexOf()은 순차 검색이므로 상대적으로 느립니다. JVM은 다중 호출을 최적화 할 수도 있고 그렇지 않을 수도 있지만 성능이 중요한 경우에는 의존하지 마십시오. 변수에 결과를 할당하여 직접 처리하십시오. 또한보십시오 Does Java optimize method calls via an interface which has a single implementor marked as final?

+0

예. 완전한! 고마워 친구. – Gray

관련 문제