Сокет Java: как обрабатывать много входящих соединений? - PullRequest
5 голосов
/ 18 марта 2010

Я пишу простой многопоточный сокет-сервер и мне интересно, как лучше всего обрабатывать входящие соединения:

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

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

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

Ответы [ 5 ]

6 голосов
/ 18 марта 2010

С неограниченным количеством соединений вы потенциально можете создавать огромное количество потоков. Это означает, что требуется много обработки, плюс каждый поток по умолчанию будет использовать фиксированный объем памяти только для кучи (я думаю, что значение составляет 512 КБ на поток , но это может зависеть от платформы).

Объединяя фиксированное количество потоков и принимая ограниченное количество клиентов, вы обеспечите обслуживание некоторых из ваших клиентов в течение разумного периода времени, и ваш сервер не потерпит крах от перегрузки.

Возможно, вы захотите прочитать эту статью о построении серверов с использованием NIO или, возможно, ознакомьтесь с такими платформами, как Apache Mina .

4 голосов
/ 18 марта 2010

Я действительно не хочу отказываться ни от чего соединения

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

Теория массового обслуживания говорит, что сладкое место составляет около 70% использования. Если ваш сервер будет иметь постоянную нагрузку выше, чем это, получите более быстрое аппаратное обеспечение, пока это не так.

Сказав это, если вы ожидаете сотни тысяч соединений, я бы использовал пул потоков или NIO. Если вы ожидаете только тысячи, поток на соединение - это самый простой способ.

2 голосов
/ 18 марта 2010

1 Поток на соединение не масштабируется. Читайте об этом в проблеме C10K . Это долго читается, но очень известный.

Я бы посоветовал узнать о NIO или, скорее, использовать впечатляющий netty каркас, который обрабатывает все тяжелые (NIO) для вас.

2 голосов
/ 18 марта 2010

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

0 голосов
/ 03 февраля 2015

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

Ваш вариант 2 - единственный путь, по моему мнению. Вы должны иметь одну закрепленную резьбу селектора NIO на каждые 5-10 тыс. Соединений. Но ничто не может задержать этот критический поток, поэтому вы используете DEMUX для распределения работы между фиксированным числом закрепленных потоков , а не в пул потоков . И MUX для сбора работы и ответа клиентам. Как сказал EJP, если ваши рабочие потоки отстают, в конечном итоге вам придется отбросить соединения , если вы не начнете записывать сообщения на диск, чтобы сделать вашу очередь максимально большой . Таким образом, у вас не будет разрыва соединения, даже при высоких нагрузках. Вы можете проверить эту статью , которая объясняет это подробно и диаграмму ниже:

enter image description here

Отказ от ответственности: Я один из разработчиков CoralQueue

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...