LINUX.ORG.RU

Unix-way разработки серверного приложения


0

0

Мы разрабатываем сложное серверное приложение и по максимуму решили дробить задачи на небольшие демоны, которые общаются по сокетам между собой.
При чем большенство демонов не знает ничего кроме своей задачи, несколько знают про другого демона и пару штук знают про 2 и больше демонов (это чтото вроде "мостов" которые соеденяют независимые приложения). Есть также сущтьность которая знает про всё и вся, и управляет ими.

Вроди такой подход "правильный". Такие демоны легко разнести на разные машины, а при гигабитной сети на площадке проблем вызвать не должно.

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

Где можно почитать про эти самые критерии? Какие проблемы могут возникнуть? (кроме того что заткнется гигабитная сеть или взаимодействие между компонентами станен слищком сложным).
Спасибо за ответы.

anonymous

Ответ на: комментарий от Bohtvaroh

erlang да, неплохая щтука =) Но опыта работы с ним у нашей команды нет (один человек который его крутил для самообразования не в счет). В основном работа на C++ с примемением скриптового языка для логики где не нужна высокая производительность. Плюс ещё 2 языка, но они не входят в схему про которую я написал.

anonymous
()
Ответ на: комментарий от Bohtvaroh

> Для такого приложение актуален erlang. ;-)

ИМХО нет.

Die-Hard ★★★★★
()

IMHO, "дробить задачи на небольшие демоны, которые общаются по сокетам между собой" в вашем случае - ПРОТИВОПОКАЗАНО. Иначе получите хорошую практику по отладке сетевых комплексов, но так и не сделаете "сложное серверное приложение" :)

MKuznetsov ★★★★★
()

а какого рода данные ходят между демонами? не слишком ли сложно получится?

Pi ★★★★★
()
Ответ на: комментарий от Bohtvaroh

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

если нужна труба, разбросанная по хостам, то совсем не годится, а у топикстартера, кажется, именно такая ситуация

Pi ★★★★★
()
Ответ на: комментарий от MKuznetsov

> IMHO, "дробить задачи на небольшие демоны, которые общаются по сокетам между собой" в вашем случае - ПРОТИВОПОКАЗАНО. Иначе получите хорошую практику по отладке сетевых комплексов, но так и не сделаете "сложное серверное приложение" :)

Ну отдельно компоненты более-менее покрыты тестами. Есть более комплексные тесты включающие в себя несколько компонентов.
Для отладки используются детальные логи;) Есть также сервис в котором собираются данные со всех демонов, что облегчает задачу выявления компонента, который даёт сбой. В будущем планируем сделать систему мониторинга состояния сервисов.

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

А что предлагаете Вы?

anonymous
()

> Но интересует вопрос - когда стоит делать монолитным приложение,

Всегда. И не надо путать монолитность с модульностью - монолитное приложение вполне может быть (и должно быть :)) модульным.

> а не разбивать его на несколько задач

Разбивать приложение на отдельные демоны нужно только тогда, когда это дейстительно необходимо. Вам _уже_ нужно масштабирование на десятки узлов (== автономных демонов)? Или решили программировать "про запас"?

Сделайте работающий прототип, отладьте логику. Потом (может быть) разнесете его по узлам.

tailgunner ★★★★★
()
Ответ на: комментарий от Pi

> а какого рода данные ходят между демонами? не слишком ли сложно получится?

В большенстве случаев данные простые. Поднимаются с базы данных - кормятся серверу, он их обрабатывает и в итоге передаёт результат другому компоненту (либо он их сам запрашивает). В некоторых случаях общение компонет более динамическое - на протяжении определенного отрезка времени компоненты активно обмениваются простыми пакетами.

Большая часть общения происходит по сокетам, часть по HTTP.

Собственно говоря сомнения возникли после создания дополнительного компонента:
* У нас есть компонент А. Он достаточно критичен.
* Есть задача Б, которую можно включить в компонент А, но эта задача менее критична для системы и более нагрузочна.
Ввиду больщой связаности компонента А и задачи Б - было бы логично реализовать её внутри А. НО - это усложнит А, Сделает его менне производительным. И если возникнут проблемы с производительностю - то надо будет разносить критичный компонент А, а если Б сделать отдельно - то можно поставить несколько машин выполняющих задачу Б и оставить одну машину А.
Вот тут и возникла делема.

anonymous
()
Ответ на: комментарий от Pi

> если нужна труба, разбросанная по хостам, то совсем не годится, а у топикстартера, кажется, именно такая ситуация

да. В большей части данные загружаются в компонент, работают с клиентами, передаются другому компоненту. Либо другой тип компонентов, который хранит данные и отвечает на простые запросы по ним (чтото сродни memcached).

anonymous
()
Ответ на: комментарий от tailgunner

> Всегда. И не надо путать монолитность с модульностью - монолитное приложение вполне может быть (и должно быть :)) модульным.
Может я чтото путаю. Под монодитностю я имел ввиду 1 приложение включающее в себя все компоненты (пусть даже загружаемые с *.so =) vs несколько приложений.
Но это не важно;)

> Разбивать приложение на отдельные демоны нужно только тогда, когда это дейстительно необходимо. Вам _уже_ нужно масштабирование на десятки узлов (== автономных демонов)? Или решили программировать "про запас"?
Нагрузка ожидается сразу, даже до готовности всего приложения. Очень важно - что если будут пробдемы и их нельзя будет быстро рещить - иметь fallback в качестве покупки N серверов.

> Сделайте работающий прототип, отладьте логику. Потом (может быть) разнесете его по узлам.
Прототип уже готов. Но как я говорил - часть функционала будет уже дописыватся на запущеной системе.

anonymous
()
Ответ на: комментарий от anonymous

Кофигурация сетки в процессе работы не меняется, так что все довольно просто и всякие теории ИМХО лишние, достаточно просто положиться на здравый смысл. Но в остальном -- извини, как-то трудно что-то посоветовать, не зная проблемы.

> В большенстве случаев данные простые.

Вопрос не в простоте данных, а в их объеме и частоте "переговоров".

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

Ethernet -- штука дешевая, но тупая. Latency весьма велика, поэтому интенсивное общение мелкими пакетами ничем хорошим не кончится; маршрутизацию она сама не умеет, так что игры в "толстую" топологию не проканают (дробить на подсетки и играть ИП маршрутизацией -- сразу на порядок все тормознется).

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

Die-Hard ★★★★★
()
Ответ на: комментарий от Die-Hard

> Вопрос не в простоте данных, а в их объеме и частоте "переговоров".

В большенстве предполагается передача 2 максимум 10 килобайт и их обработка в течении длительного времени (от 5 минут до нескольких часов) + переодические обращения типа "запрос 20 байт - ответ 20-1000 байт".

В компоненте который у меня вызвал сомнения - передача данных более интенсивная: компонент включающий в пике до 500 заданий (ну можно округлить до 2000) общаются с другим компонентом пересылая гдето раз в 5 секунд по 6-40 байт и получая по 6-400 байт (в больщенстве запросов < 40). Ну если учесть что используется TCP - то можно округлить до 1024 в одну сторону. Получается, что в пике 2000 / 5 * 1024 = 500 килобайт/секунду.
Но это при максимальной загружености. В щтатном режиме будет не больне 100 килобайт в секунду.
Много это или мало?

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

Это мы учитываем. Есть простые компоненты которые часто общаются с другим сложным компонентом (чтото типа сателитов). Мы так и закладывались - что они всегда будут на одном сервере.

anonymous
()
Ответ на: комментарий от anonymous

> Много это или мало?

:-)

Мало!

Такими темпами коммуникации -- вообще не боттлнек, ИМХО смело можно разносить А и Б, и вообще, не обращать на коммуникации особого внимания.

Проблемы могут быть две, но чисто теоретические (т.е., если случайно "наступить"):

1. Сложная логика коммуникаций -- с ростом числа компонент число возможных связей растет экспоненциально;) -- можно будет потом легко запутаться, если злоупотребить каким-либо вычурным дизайном.

2. Топология хитрее "звезды", да и масштабируемость Ethernet - базированного кластера невелика. Если вдруг потребуются под 1000 нод, могут неожиданно начаться проблемы.

Die-Hard ★★★★★
()

> Где можно почитать про эти самые критерии? Какие проблемы могут возникнуть? (кроме того что заткнется гигабитная сеть или взаимодействие между компонентами станен слищком сложным).

Э. Таненбаум, М. ван Стеен "Распределенные системы: принципы и парадигмы", раздел 1.

Решением большей части проблем может стать хорошо спроектированный и реализованный RPC. Для C++ рекомендую посмотреть на ICE (http://zeroc.com/). Городить огород без знания предметной темы не рекомендую: вероятность получить что-то хорошее не слишком большая.

mv ★★★★★
()
Ответ на: комментарий от dave

Corba слишком сложная и плохо спроектированна.

mv ★★★★★
()

всем спасибо за помощь

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.