Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Python: Общие вопросы > Как лучше реализовать клиент-серверное приложение?


Автор: Mihail2205 6.3.2012, 16:44
Здравствуйте, подскажите пожалуйста как лучше реализовать клиент-серверное приложение по удаленному мониторингу и контролю некоторых устройств:

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

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

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

Заранее спасибо за ваши ответы!

Автор: rsm 6.3.2012, 17:52
Цитата(Mihail2205 @  6.3.2012,  18:44 Найти цитируемый пост)
вопрос в том чтобы делать это с минимальным расходом трафика и небольшими задержками

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

Автор: Mihail2205 6.3.2012, 20:07
протокол уровня MAC это конечно круто, но не - давайте уточним:

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

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

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

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

-
В случае с TCP соединением, можно ли использовать в качестве серверного приложения какой-нибудь apache+php\python, чтобы не писать свое приложение с сокетами блекджеком и шлюхами? Переварит ли апач одновременные несколько сотен подключений и какую технологию надо будет использовать (там же везде таймауты, не получится часами какой-нибудь http запрос держать)? Или все-таки придется что-то свое городить?

Автор: rsm 7.3.2012, 16:08
Цитата(Mihail2205 @  6.3.2012,  22:07 Найти цитируемый пост)
я пока вижу только 2 решения

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

Цитата(Mihail2205 @  6.3.2012,  22:07 Найти цитируемый пост)
Возможны ли еще варианты?

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

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

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

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

У этой задачи даже есть специальное название: http://www.kegel.com/c10k.html (проблема 10000 соединений). Готовые решения уже есть (например, тот же nginx), исходники открыты - можно достаточно легко (особенно если выпилить HTTP) адаптировать под собственные нужды.

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

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

В целом, если не требуется высокая надёжность, то вполне хватит центрального сервера, которому через некоторый интервал времени по протоколу UDP будут приходить сигнальные пакеты от устройств. А если ещё и разнести отправку этих пакетов по времени, то и устройства, и сервер получатся лёгкими и простыми. Во-первых, UDP значительно проще в реализации, хотя и имеет недостаток: не гарантирует доставку и целостность данных. Что, к слову, ничуть не мешает его использованию в http://en.wikipedia.org/wiki/Network_File_System_%28protocol%29, которая работает очень быстро и надёжно. Во-вторых, сервер не "утонет" в потоке данных от устройств, если их передача будет распределена по времени (а она будет распределена в любом случае, даже если не реализовывать это намерено).

Автор: Mihail2205 7.3.2012, 19:03
Я не силен в TCP/IP стеке, все-таки считаете что протокол на основе UDP будет меньше нагружать сервер и потреблять меньше трафика, чем постоянно открытое TCP соединение от каждого клиента? Напомню что устройства UDP пакетами должны будут каждые несколько секунд передавать свое состояние и в случае необходимости получать от сервера команды. При этом клиентские устройства имеют серый ИП и находятся за NATом, следовательно входящие соединения принимать не имеют возможности - могут только сами что-то отправлять на сервер.

Автор: rsm 8.3.2012, 08:44
Цитата(Mihail2205 @  7.3.2012,  21:03 Найти цитируемый пост)
следовательно входящие соединения принимать не имеют возможности - могут только сами что-то отправлять на сервер

В принципе для UDP через NAT можно сделать общий тоннель. Однако это уже нетривиально. Поэтому лучше делать проще - брать за основу TCP, поддерживать и тщательно контролировать соединение. И, разумеется, изначально предусмотреть возможность параллельной обработки данных в случае, если клиентов станет больше, чем в самых смелых предположениях.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)