2017-02-01 4 views
1

В настоящее время я работаю над проектом, в котором я должен разместить сервер, который выбирает входной поток, анализирует данные и отправляет их в базу данных. Каждый клиент, который подключается к моему серверу, отправляет входной поток, который никогда не останавливается после его подключения. Каждому клиенту назначается сокет и его собственный объект потока парсера, поэтому сервер может иметь дело с потоком данных, поступающим от клиента. Объект parser обрабатывает только входящие данные и отправляет их в базу данных.Оптимизация многопоточного сервера java, использующего входной указатель

Server/анализатор генератор:

public void generateParsers() { 
    while (keepRunning) { 
     try { 
      Socket socket = s.accept(); 
      // new connection 
      t = new Thread(new Parser(socket)); 
      t.start(); 
     } catch (IOException e) { 
      appLog.severe(e.getMessage()); 
     } 
    } 
} 

Parser нить:

@Override 
    public void run() { 
     while (!socket.isClosed() && socket.isConnected()) { 
      try { 
       BufferedReader bufReader = new BufferedReader(new InputStreamReader(socket.getInputStream())); 
       String line = bufReader.readLine(); 
       String data = ""; 
       if (line == null) { 
        socket.close(); 
       } else if (Objects.equals(line, "<DATA")) { 
        while (!Objects.equals(line, "</DATA>")) { 
         data += line; 
         line = bufReader.readLine(); 
        } 
        /* 
        Send the string that was build    
        from the client's datastream to the database 
        using the parse() function.   
        */ 
        parse(data); 
        } 
       } 
      } catch (IOException e) { 
       System.out.println("ERROR : " + e); 
      } 
     } 
    } 

Моя установка функциональна, но проблема в том, что она доставляет слишком много стресса на моем сервере при подключении слишком много клиентов и таким образом, слишком много потоков одновременно анализируют данные. Разбор входящих данных и отправка данных в базу данных практически не влияют на производительность. Узким местом является, в основном, одновременное считывание потоков данных клиента от подключенных клиентов.

Есть ли способ, которым я могу оптимизировать текущую настройку? Я подумывал ограничить количество подключений и после получения полного файла данных, проанализировать его и перейти к следующему клиенту в очереди подключений или что-то подобное.

+1

'data + = line;' вы можете реорганизовать эту конкатенацию строк, используя 'StringBuilder'. Также вы можете просмотреть свой код, чтобы узнать, есть ли какие-либо узкие места –

ответ

3

Узким в основном одновременное чтение

No. Узким является конкатенация.Используйте StringBuffer или StringBuilder.

И, возможно, неправильное поведение, когда клиент отключается. Трудно поверить, что это вообще работает. Он не должен:

  • Вы должны использовать тот же самый BufferedReader для срока службы разъема, в противном случае вы можете потерять данные.
  • Socket.isClosed() и Socket.isConnected() не делать то, что вы думаете, что они делают: правильное условие завершения цикла является readLine() возвращение нулевой, или бросать IOException:

    while ((line = bufReader.readLine()) != null) 
    

укупорки количество одновременных соединений может» возможно, что-либо достигнуть, если клиенты никогда не отключится. Все, что вы достигнете, никогда не слушает клиентов за пределами первого N, чтобы подключиться, что не может быть то, что вы хотите. «Переход к следующему клиенту» никогда не произойдет.

2

Если ваша проблема в том, что все, что вы делаете, когда клиент подключен, дорого, вам придется использовать клиентскую очередь. Самый простой способ сделать это - использовать ExecutorService с N количеством максимальных потоков.

Например

private ExecutorService pool=Executors.newFixedThreapPool(N); 

... , а затем

Socket socket = s.accept(); 
pool.submit(new Parser(socket))); 

Это будет ограничивать обработку до одновременно максимально N в то время клиента, и очереди дополнительных клиентов, что превышает N.

Также зависит от того, что вы делаете с данными, вы всегда можете разделить процесс на фазы, например

  1. Читайте необработанные данные от клиента и Епдиеего для обработки - закрыть сокет и т.д., так что вы можете сэкономить ресурсы
  2. обрабатывать данные в отдельном потоке (возможно, пул потоков) и епдиеий результат
  3. ли что-то в результате (проверка достоверности, сохранение в БД и т. д.) в другом пуле.

Это особенно полезно, если у вас есть какие-то блокирующие операции, такие как сети I/O, или дорогой и т.д.

выглядит как в вашем случае, клиент не должен ждать весь бэкенд proess, чтобы закончить. Ему нужно только доставлять данные, поэтому разделение данных на чтение и разбор/сохранение на отдельные фазы (подзадачи) звучит как разумный подход.

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