Многопоточный объединенный сервер, прослушивающий несколько портов на Java —

#java #multithreading #server #threadpool

Вопрос:

Я пытаюсь понять, как создать многопоточный сервер Java, который может прослушивать несколько портов и иметь пулы потоков для каждого из портов, от которых он принимает запросы.

Я уже реализовал чертов многопоточный сервер с пулом, прослушивающий один порт, как показано здесь:

 public void run() {
        synchronized (this) {
            this.runningThread = Thread.currentThread();
        }
        openSocketServer();
        while (!isStopped()) {
            Socket clientSocket = null;
            try {
                clientSocket = this.serverSocket.accept();
            } catch (IOException e) {
                if (isStopped()) {
                    System.out.println("Server Stopped.");
                    break;
                }
                throw new RuntimeException("Error with accepting client connection", e);
            }
            this.threadPool.submit(new HandlerRichieste(clientSocket, this));
        }
        this.threadPool.shutdown();
        System.out.println("Server stopped");
    }

 

И мне удалось реализовать сервер, прослушивающий несколько портов с помощью библиотеки NIO; проблема с этой реализацией заключается в том, что она использует только один поток для обработки запросов, поступающих с разных портов, поэтому обрабатывает их последовательно и снижает производительность:

 Selector selector = Selector.open();

int[] ports = {4000,4001,6000};

for (int port : ports) {
   ServerSocketChannel server = ServerSocketChannel.open();
   server.configureBlocking(false);

   server.socket().bind(new InetSocketAddress(port));
   // from here we are only interested when accept evens occur on this socket
   server.register(selector, SelectionKey.OP_ACCEPT); 
}

while (selector.isOpen()) {
   selector.select();
   Set readyKeys = selector.selectedKeys();
   Iterator iterator = readyKeys.iterator();
   while (iterator.hasNext()) {
      SelectionKey key = (SelectionKey) iterator.next();
      if (key.isAcceptable()) {
         SocketChannel client = server.accept(); //SERVER CANNOT BE RESOLVED!!!!
         Socket socket = client.socket();
         // create new thread to deal with the connection coming from that port (closing both socket and client when done)
      }
   }
}
 

Как я могу объединить их, в результате чего сервер прослушивает несколько портов, у которых есть пул потоков для каждого порта?
Возможно ли вообще создать многопоточный сервер с пулом, который прослушивает несколько портов, без использования библиотеки NIO?
Если да, то может ли кто-нибудь показать мне механизм создания пула потоков для каждого порта без Java NIO?

Комментарии:

1. Если вы используете a Selector , обычный способ-использовать один поток, который не выполняет ничего, кроме событий выбора службы. Затем, когда вы получаете пакет / какую-то работу, которую нужно выполнить, вы отправляете пакет в отдельный пул потоков для выполнения работы. Затем поток селектора сразу же возвращается к обслуживанию селектора.

2. Если вы хотите увидеть реальный рабочий код, ознакомьтесь с исходным кодом веб-сервера Apache, который также использует select() poll() вызов или. Я полагаю, что соответствующий код находится в listen.c : github.com/apache/httpd/blob/trunk/server/listen.c

3. @markspace Спасибо, это именно то, что я сделал в своей реализации «прослушивание сервера на нескольких портах» с помощью селектора NIO (я не добавил весь код, чтобы привести минимально воспроизводимый пример, но, как вы можете видеть из кода, есть один поток, прослушивающий все порты и отправляющий пакеты в отдельный пул потоков). К сожалению, поскольку это делает обслуживание событий выбора последовательным, мне нужно иметь несколько пулов потоков — по одному на порт, — чтобы при наличии нескольких запросов, поступающих от нескольких портов, я не застрял только на обслуживании одного порта за раз.

4. @markspace Источник веб — сервера Apache действительно интересен, и он определенно подтверждает, что такое стандарт-очевидно, то, что мне нужно, не может быть сделано с помощью селекторов (библиотека NIO). Тем не менее, я действительно нуждаюсь в совете относительно того, как изменить первую многопоточную реализацию сервера в вопросе, чтобы он мог принимать запросы, поступающие от заданного набора портов (поскольку часть «создать пул потоков на порт» будет довольно легко реализовать после этого).

5. @markspace Создание другого многопоточного объединенного сервера — ove для каждого порта — возможно, решило бы мою проблему? Хотя как бы я реализовал этот маршрут (я новичок)?

Ответ №1:

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

Что мешает вам создать этот шаблон трижды? Затем вы прослушиваете три порта и обслуживаете входящие соединения потоками из трех определенных пулов потоков. Единственное, чего вам нужно остерегаться: ожидание подключения к одному сокету может заблокировать поток.

В качестве решения просто создайте три потока, которые прослушивают по одному порту каждый.

Комментарии:

1. Такое простое решение, спасибо! Для каждого порта будет реализован новый сокет, NIO не требуется!