#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.c3. @markspace Спасибо, это именно то, что я сделал в своей реализации «прослушивание сервера на нескольких портах» с помощью селектора NIO (я не добавил весь код, чтобы привести минимально воспроизводимый пример, но, как вы можете видеть из кода, есть один поток, прослушивающий все порты и отправляющий пакеты в отдельный пул потоков). К сожалению, поскольку это делает обслуживание событий выбора последовательным, мне нужно иметь несколько пулов потоков — по одному на порт, — чтобы при наличии нескольких запросов, поступающих от нескольких портов, я не застрял только на обслуживании одного порта за раз.
4. @markspace Источник веб — сервера Apache действительно интересен, и он определенно подтверждает, что такое стандарт-очевидно, то, что мне нужно, не может быть сделано с помощью селекторов (библиотека NIO). Тем не менее, я действительно нуждаюсь в совете относительно того, как изменить первую многопоточную реализацию сервера в вопросе, чтобы он мог принимать запросы, поступающие от заданного набора портов (поскольку часть «создать пул потоков на порт» будет довольно легко реализовать после этого).
5. @markspace Создание другого многопоточного объединенного сервера — ove для каждого порта — возможно, решило бы мою проблему? Хотя как бы я реализовал этот маршрут (я новичок)?
Ответ №1:
Вы уже можете создать сервер с одним потоком, ожидающим соединений на одном порту и обслуживающим входящие соединения потоками из одного определенного пула.
Что мешает вам создать этот шаблон трижды? Затем вы прослушиваете три порта и обслуживаете входящие соединения потоками из трех определенных пулов потоков. Единственное, чего вам нужно остерегаться: ожидание подключения к одному сокету может заблокировать поток.
В качестве решения просто создайте три потока, которые прослушивают по одному порту каждый.
Комментарии:
1. Такое простое решение, спасибо! Для каждого порта будет реализован новый сокет, NIO не требуется!