Как общаться с тысячами сокетов одновременно в Java? - PullRequest
5 голосов
/ 07 октября 2010

Это описание проблемы У нас есть тысячи устройств (примерно 4–5 тыс.), Через которые мы должны считывать данные непрерывно, каждые 2 минуты или 30 секунд. Каждое устройство имеет свой уникальный IP. Эти данные будут собраны и затем сохранены в базе данных. Эти устройства находятся в сотнях мест по всей стране. Данные будут считываться не круглосуточно, а как минимум в течение 12 часов.

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

Вот как мы думаем, что можем реализовать в Java

Раствор А : В каждом месте назначьте одну машину, которая будет выполнять роль сервера и будет считывать данные с x-го количества устройств. Эти данные будут отправляться на центральный сервер каждые 1 час. На этой назначенной машине данные извлекаются и хранятся локально (плоский файл или в базе данных памяти)

В этом случае у нас будет столько серверов, сколько мест. например, у нас может оказаться 1500 серверов / управление машиной, что станет кошмаром.

Раствор B :

У нас есть 8-10 центральных серверов, и каждый сервер считывает данные с нескольких машин. Данные помещаются в очередь и собираются в порядке поступления.

Серверы отправляют данные в базу данных.

Как клиент получает данные ?

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

Как вы думаете, что должно работать лучше?

Есть ли альтернативный дизайн / решение?

Должны ли мы думать о программировании на сервере с Unix / Perl. Мы не хотим использовать C ++ по некоторым другим причинам.

Ответы [ 5 ]

4 голосов
/ 07 октября 2010

Требование, указанное в вашем вопросе, не подразумевает 1000-х одновременных соединений, поскольку вы можете легко создавать соединение заново каждые 30 секунд.Предполагая, что соединение может быть удалено в течение 500 мс, это оставляет 5000/30 * 0,5 ~ = 100 одновременных соединений.Любая приличная ОС должна быть в состоянии справиться с таким количеством.При таком низком параллелизме вы даже можете обойтись без использования одного сервера, в котором каждое соединение выполняется отдельным потоком.

Поэтому ваш дизайн должен быть ориентирован на другие ваши требования.Несколько идей:

  • Защищены ли устройства?С решением A у вас будут исходящие соединения из каждого местоположения, а с решением B у вас будут входящие.
  • Какая надежность вам нужна?Например, вам нужно записывать измерения, если подключение к Интернету не работает?Это будет означать, что локальный сервер буферизует измерения.
3 голосов
/ 07 октября 2010

Если вы поддерживаете соединения, вы сможете опрашивать каждое соединение менее чем за 20 микросекунд на соединение.Это означает, что вы можете опрашивать каждое соединение менее чем за 100 мс, используя только один неблокирующий поток.(возможно, наименее эффективный способ сделать это)

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

Если вы создаете новое соединение каждый раз, этогораздо дороже, но может занять 20 миллисекунд (дольше в зависимости от задержки вашей сети).Чтобы объединить 5000 соединений за 30 секунд, вам нужно поддерживать 3-4 активности в любое время.(Большая часть времени будет потрачена на установление и уничтожение соединения). Вы можете сделать все это с помощью одного потока, но использование небольшого пула потоков может быть проще.

2 голосов
/ 07 октября 2010

Если это возможно, я думаю, что ваши клиенты должны отправлять сообщения JMS или какую-то очередь, тогда вы обрабатываете очередь для хранения в базе данных. Есть ActiveMQ, который отлично подойдет для этого. Есть также SQS (от Amazon), если вам нравятся облачные развертывания, тогда ваши java-серверы, которые общаются с главной БД, могут просто извлечь из этого.

2 голосов
/ 07 октября 2010

Попробуйте Нетти .

1 голос
/ 07 октября 2010

Вы не упоминали о том, чтобы клиенты общались с серверами, а не наоборот. Это вариант? Вы также не упоминаете объемы передаваемых данных.

Упомянутые вами цифры не кажутся необоснованными для сервера Java (с соответствующим пулом соединений и т. Д.). Попробуйте создать прототипы некоторых решений просто для тестирования пулов связи и потоков / соединений. И проверьте такие фреймворки, как Apache Mina .

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