2016-12-31 2 views
1

Мой отправитель отправляет 10000 запросов в секунду (или даже больше), но мой ServerSocketChannel способен читать и обрабатывать (в потоке) 8000 запросов (~ appx).Как обслуживать 1000 одновременных соединений с использованием Java NIO

пустышка код выглядит так:

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

Купить более быстрый компьютер? Масштабирование? --- Используйте пул потоков/очередь сообщений вместо создания 1000 потоков для вызова 'processAndStore()'. Запуск потока ** дорого **. Начиная 10000 потоков в секунду? * Yikes! * --- ** Код профиля **, чтобы увидеть, где узкое место, а не гадать, но вот некоторые догадки: 1) Не используйте 'StringBuffer', используйте' StringBuilder'. 2) Не вызывайте 'lastIndexOf ("} ")' три раза. – Andreas

+0

Целью NIO является сокращение количества требуемых потоков. У вас, похоже, нет сообщения. Неясно, что вы спрашиваете. – EJP

+0

Хорошо благодарю вас за своевременные ответы. Между тем, что я сделал, я удалил создание потоков, и производительность немного улучшилась. Более того, я пропустил «NIO» и использовал приемник «netty» и «SimpleChannelInboundHandler» и с той же аппаратной конфигурацией, я получаю почти все запросы. – desaiankitb

ответ

1

Используйте пул потоков/очередь сообщений вместо создания 1000 потоков для вызова processAndStore().

Начальная нить дорогая.

Начато 10000 сообщений в секунду? Yikes!

Как сказал @EJP в comment:

Цель NIO заключается в уменьшении количества требуемых потоков. У вас, похоже, нет сообщения.


В дополнение к этому, профиль ваш код, чтобы увидеть, где узкое место, а не гадать.

Но вот некоторые догадки так или иначе:

  1. Не используйте StringBuffer, используйте StringBuilder.
    Причина: См. 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

Смежные вопросы