Как лучше реализовать клиент-серверное приложение?

 
0
 
Python
ava
Mihail2205 | 06.03.2012, 17:44
Здравствуйте, подскажите пожалуйста как лучше реализовать клиент-серверное приложение по удаленному мониторингу и контролю некоторых устройств:

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

Устройства подключаются через интернет к серверу, на котором запущен веб-интерфейс. Время от времени на сайт заходит оператор, смотрит состояние устройств и если нужно - отправляет команду. Нужно чтобы с момента отправки команды оператором она выполнялась на выбранном устройстве с минимальной задержкой (максимум пара секунд), но при этом чтобы целевое устройство не расходовало слишком много трафика, постоянно отправляя что-то на сервер. Оперативность нужна только в момент захода оператора на сайт, в остальное время достаточно просто отсылать свой статус раз в 10-15 минут.

Как бы вы подошли к реализации такой задачи? Возможно ли использовать веб-сервер в качестве серверного приложения?

Заранее спасибо за ваши ответы!
Kommentare (5)
ava
rsm | 06.03.2012, 17:52 #
Цитата (Mihail2205 @ 6.3.2012, 18:44 findReferencedText)
вопрос в том чтобы делать это с минимальным расходом трафика и небольшими задержками

Уменьшить траффик - оптимизировать и упаковывать данные, снижать количество запросов. Что по задержкам - тут всё зависит от организации сети. В порядке возрастания задержек:
а) если все устройства физически в одной сети, то широковещательная передача решает;
б) если устройства разбиты по группам и/или подсетям - мультикаст;
в) если совсем разрознены - адресная передача;
Далее, протоколы по мере возрастания задержки:
а) самопальный протокол уровня MAC - при этом важно, чтобы размер передаваемых данных не превышал размер одного Ethernet-фрейма, т.к. в противном случае потребуется обработка фрагментированных пакетов, что в итоге может дать такие же задержки, что и UDP, или даже хуже;
б) IP;
в) UDP;
г) TCP;
Однако в случае использования вариантов а, б или в потребуется требуется контроль целостности данных с обоих сторон соединения, который также будет отнимать некоторое количество времени.
В общем, продолжать в том же духе можно долго - вопрос сформулирован слишком широко и размыто. Для проектирования оптимального сетевого обмена нужно задаться намного большим количеством критериев, нежели указано.
ava
Mihail2205 | 06.03.2012, 20:07 #
протокол уровня MAC это конечно круто, но не - давайте уточним:

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

я пока вижу только 2 решения:

1. все устройства все время флудят на сервер что-то вроде "нет ли для меня новых команд?" (можно даже UDP пакетами)
2. все устройства постоянно держат открытую TCP-сессию до сервера и по ней получают команды и передают свое состояние

Возможны ли еще варианты?

-
В случае с TCP соединением, можно ли использовать в качестве серверного приложения какой-нибудь apache+php\python, чтобы не писать свое приложение с сокетами блекджеком и шлюхами? Переварит ли апач одновременные несколько сотен подключений и какую технологию надо будет использовать (там же везде таймауты, не получится часами какой-нибудь http запрос держать)? Или все-таки придется что-то свое городить?
ava
rsm | 07.03.2012, 16:08 #
Цитата (Mihail2205 @ 6.3.2012, 22:07 findReferencedText)
я пока вижу только 2 решения

Второй вариант будет потреблять больше трафика, т.к. всё равно нужно будет отправлять keep-alive пакеты чтобы соединение держалось стабильно.

Цитата (Mihail2205 @ 6.3.2012, 22:07 findReferencedText)
Возможны ли еще варианты?

а) одноранговая сеть (p2p): тратится довольно много трафика, работает неторопливо, но зато высокая надёжность и отказоустойчивость;
б) подобие ботнета, когда некоторые устройства (master) наделяются возможностью управления другими устройствами (slave): с центральным сервером общаются только master-устройства, транслируя данные в заданные slave-устройства. При такой схеме количество трафика снижается, нагрузка на центральный сервер снижается, но надёжность и отказоустойчивость так же снижаются - если master-устройство откажет, то исчезнет связь со всеми его slave-устройствами;
в) комбинация а и б - распределённый ботнет, когда в случае выхода из строя одного master-устройства его подменяет другое master-устройство;
Вообще, что ставится во главу угла - надежность и отказоустойчивость или время реакции и объем трафика? Это почти взаимоисключающие свойства.

Цитата (Mihail2205 @ 6.3.2012, 22:07 findReferencedText)
В случае с TCP соединением, можно ли использовать в качестве серверного приложения какой-нибудь apache

Если использовать HTTP (много трафика!), то подойдет любой сервер, расчитанный на большие нагрузки - nginx, lighttpd и т.п.

Цитата (Mihail2205 @ 6.3.2012, 22:07 findReferencedText)
и какую технологию надо будет использовать

У этой задачи даже есть специальное название: The C10K Problem (проблема 10000 соединений). Готовые решения уже есть (например, тот же nginx), исходники открыты - можно достаточно легко (особенно если выпилить HTTP) адаптировать под собственные нужды.

Цитата (Mihail2205 @ 6.3.2012, 22:07 findReferencedText)
не получится часами какой-нибудь http запрос держать

У HTTP нет понятия "держать состояние". Это протокол без состояния, работающий по принципу "запрос-ответ".

В целом, если не требуется высокая надёжность, то вполне хватит центрального сервера, которому через некоторый интервал времени по протоколу UDP будут приходить сигнальные пакеты от устройств. А если ещё и разнести отправку этих пакетов по времени, то и устройства, и сервер получатся лёгкими и простыми. Во-первых, UDP значительно проще в реализации, хотя и имеет недостаток: не гарантирует доставку и целостность данных. Что, к слову, ничуть не мешает его использованию в NFS, которая работает очень быстро и надёжно. Во-вторых, сервер не "утонет" в потоке данных от устройств, если их передача будет распределена по времени (а она будет распределена в любом случае, даже если не реализовывать это намерено).
ava
Mihail2205 | 07.03.2012, 19:03 #
Я не силен в TCP/IP стеке, все-таки считаете что протокол на основе UDP будет меньше нагружать сервер и потреблять меньше трафика, чем постоянно открытое TCP соединение от каждого клиента? Напомню что устройства UDP пакетами должны будут каждые несколько секунд передавать свое состояние и в случае необходимости получать от сервера команды. При этом клиентские устройства имеют серый ИП и находятся за NATом, следовательно входящие соединения принимать не имеют возможности - могут только сами что-то отправлять на сервер.
ava
rsm | 08.03.2012, 08:44 #
Цитата (Mihail2205 @ 7.3.2012, 21:03 findReferencedText)
следовательно входящие соединения принимать не имеют возможности - могут только сами что-то отправлять на сервер

В принципе для UDP через NAT можно сделать общий тоннель. Однако это уже нетривиально. Поэтому лучше делать проще - брать за основу TCP, поддерживать и тщательно контролировать соединение. И, разумеется, изначально предусмотреть возможность параллельной обработки данных в случае, если клиентов станет больше, чем в самых смелых предположениях.
Registrieren Sie sich oder melden Sie sich an, um schreiben zu können.
Unternehmen des Tages
Вы также можете добавить свою фирму в каталог IT-фирм, и публиковать статьи, новости, вакансии и другую информацию от имени фирмы.
Подробнее
Mitwirkende
  rsm   Mihail2205
advanced
Absenden