Общие принципы построения распределенных систем

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

Построение распределенных систем высокого качества является одной из наиболее сложных задач разработки ПО. Технологии типа J2EE и .NET создаются как раз для того, чтобы сделать разработку широко встречающихся видов распределенных систем — так называемых бизнес-приложений, поддерживающих решение бизнес-задач некоторой организации, — достаточно простой и доступной практически любому программисту. Основная задача, которую пытаются решить с помощью распределенных систем — обеспечение максимально простого доступа к возможно большему количеству ресурсов как можно большему числу пользователей. Наиболее важными свойствами такой системы являются прозрачность, открытость, масштабируемость и безопасность.

  • Прозрачность (transparency).

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

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

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

  • Открытость (openness).

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

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

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

  • Масштабируемость (scalability).

Масштабируемость системы — это зависимость изменения ее характеристик от количества ее пользователей и подключенных ресурсов, а также от степени географической распределенности системы. В число значимых характеристик при этом попадают функциональность, производительность, стоимость, трудозатраты на разработку, на внесение изменений, на сопровождение, на администрирование, удобство работы с системой. Для некоторых из них наилучшая возможная масштабируемость обеспечивается линейной зависимостью, для других хорошая масштабируемость означает, что показатель не меняется вообще при изменении масштабов системы или изменяется незначительно.

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

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

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

    • Децентрализация обработки запросов за счет использования для этого нескольких машин.
    • Децентрализация данных за счет использования нескольких хранилищ данных или нескольких копий одного хранилища.
    • Децентрализация алгоритмов работы за счет использования для алгоритмов:
      • не требующих полной информации о состоянии системы;
      • способных продолжать работу при сбое одного или нескольких ресурсов системы;
      • не предполагающих единого хода времени на всех машинах, входящих в систему.
    • Использование, где это возможно, асинхронной связи — передачи сообщений без приостановки работы до прихода ответа.
    • Использование комбинированных систем организации взаимодействия, основанных на следующих схемах.
      • Иерархическая организация систем, хорошо масштабирующая задачи поиска информации и ресурсов.
      • Репликация — построение копий данных и их распределение по системе для балансировки нагрузки на разные ее элементы. Частным случаем репликации является кэширование, при котором результаты наиболее часто используемых запросов запоминаются и хранятся как можно ближе к клиенту, чтобы переиспользовать их при повторении запросов.
      • Взаимодействие точка-точка (peer-to-peer, P2P) обеспечивает независимость взаимодействующих машин от других машин в системе.
  • Безопасность (safety).

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

Понятие безопасности включает следующие характеристики:

    • Сохранность и целостность данных.

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

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

    • Защищенность данных и коммуникаций.

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

    • Отказоустойчивость и способность к восстановлению после ошибок.

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

Еще важнее для распределенных систем уметь восстанавливаться после сбоев. Уровни этого восстановления могут быть различными. Обычно данные одного короткого сеанса работы считается возможным не восстанавливать, поскольку такие данные часто малозначимы или легко восстанавливаются (иначе стоит серьезно рассмотреть необходимость восстановления сеансов). Но так называемые постоянно хранимые (persistent) данные чаще всего требуется восстанавливать в их последнем непротиворечивом состоянии.

 

Перед разработчиками систем, удовлетворяющих перечисленным свойствам, встает огромное количество проблем. Решать их все сразу просто невозможно в силу ограниченности человеческих способностей. Чтобы хоть как-то структурировать эти проблемы, их разделяют по следующим аспектам [3].

  • Связь.

Организация связи и передачи данных между элементами системы.

В связи с этим аспектом возникают следующие задачи:

    • Какие протоколы использовать для передачи данных?
    • Как реализовать обращения к процедурам и методам объектов одних процессов из других?
    • Какой способ передачи данных выбрать — синхронный или асинхронный? В первом случае сторона, инициировавшая передачу, приостанавливает свою работу до прихода ответа другой стороны на переданное сообщение. Во втором случае первая сторона имеет возможность продолжить работу, пока данные передаются и обрабатываются другой стороной.
    • Нужно ли, и если нужно, то как, организовать хранение (асинхронных) сообщений в то время, когда и отправитель, и получатель сообщения могут быть неактивны.
    • Как организовать передачу непрерывных потоков данных, представляющих собой аудио-, видеоданные или смешанные потоки данных. Этот вопрос имеет большое значение, поскольку заметные человеку прерывания в передаче таких данных приводят к значительному падению качества предоставляемых услуг.
  • Именование.

Поддержка идентификации и поиска отдельных ресурсов внутри системы.

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

Организация работ в рамках процессов и потоков.

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

Синхронизация параллельно выполняемых потоков работ.

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

Поддержка целостности данных и непротиворечивости вносимых изменений.

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

Организация отказоустойчивой работы.

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

Организация защищенности данных и коммуникаций.

    • Как организовать защиту системы в целом?

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

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

Из перечисленных тем отдельного рассмотрения заслуживают вопросы организации передачи сообщений и транзакций, тем более что все рассматриваемые далее технологии используют эти механизмы. Более того, практически любая распределенная система сейчас строится на основе программного обеспечения промежуточного уровня (middleware – программное обеспечение, которое предназначено для облегчения интеграции ПО, размещенного на нескольких машинах, в единую распределенную систему и поддержки работы такой системы), содержащего ту или иную их реализацию.