Оглавление
2. Среды для параллельной обработки 3
3. Технологии клиент-серверных и распределенных систем 4
4 Сервисы распределенных систем. Служба имен. Связывание клиентов и серверов. 5
5. Сервисы распределенных систем. Сервисы распределенного обмена сообщениями. 6
6. Сервисы распределенных систем. Сервисы - сокеты. Обмен сообщениями через порты 7
8. ПО промежуточного слоя и технологии создания распределенных систем. Вызовы удаленных процедур. 9
9. Вызов удаленных методов в языке Java 10
11. Брокер объектных запросов 12
12. Статическое и динамическое связывание 13
13. Сервисы CORBA. Интеграция унаследованных приложений в каркас распределенных объектов. 14
16. Структурированные типы языка IDL. 17
18. Репозитарный идентификатор 19
19. Важнейшие типы архитектур распределенных систем. Клиент-сервер. Модель сервиса20
21. Важнейшие типы архитектур распределенных систем. Мобильный агент. Тонкий клиент. 21
22. Важнейшие типы архитектур распределенных систем. Архитектура P2P 22
23. Транзакции. Свойства транзакций. 23
24. Параллелизм. Проблема потери результатов обновления. 24
25. Параллелизм. Проблема незафиксированной зависимости. 25
26. Параллелизм. Проблема несовместного анализа. 26
28. Решение проблем параллелизма. 28
30. Двухфазный протокол фиксации транзакций 28
Распределенное приложение - это параллельное приложение, которое исполняется в среде, состоящей из нескольких географически разнесенных узлов. Каждый узел представляет собой отдельную вычислительную систему, причем эти системы связаны локальной или глобальной сетью.
Рис. 1. Распределенная среда обработки
Распределенная обработка имеет следующие преимущества:
- повышенная доступность. Если некоторые узлы временно недоступны, то операция выполняется в редуцированной конфигурации. Отсутствует единая точка отказа;
- гибкая конфигурация. Одно и то же приложение допустимо сконфигурировать различными способами, разместив его на подходящем числе узлов;
- более локализованное управление и администрирование. Распределенную подсистему, выполняемую на своем собственном узле, можно спроектировать так, что она будет автономной, то есть практически независимой от других подсистем, работающих на прочих узлах;
- постепенное расширение системы. Если нагрузка сильно возрастает, систему легко расширить за счет добавления новых узлов;
- уменьшение затрат. Зачастую распределенное решение оказывается дешевле централизованного, особенно если принять во внимание стремительно уменьшающуюся стоимость и возрастающую производительность микро компьютеров;
- балансирование нагрузки. В некоторых приложениях общая нагрузка на систему может быть распределена между различными узлами;
- уменьшение времени отклика. Запросы пользователей локальных систем обрабатываются быстрее.
Инфраструктуру распределенных систем обеспечивают операционная система, вычислительная сеть и ПО промежуточного слоя.
Мультипрограммная среда
В мультипрограммной (или многозадачной) среде несколько задач разделяют единственный процессор. Виртуальный параллелизм обеспечивается операционной системой, которая управляет выделением процессора отдельным задачам, так что создается иллюзия, будто у каждой задачи есть свой процессор.
Рис. 2. Мультипрограммная среда (с одним процессором)
Симметричная мультипроцессорная среда
В симметричной мультипроцессорной среде есть два или несколько процессоров с общей памятью. Для всех процессоров существует единое физическое адресное пространство, поэтому все процессы находятся в общей памяти. В такой среде поддерживается реальный параллелизм, поскольку процессоры работают одновременно. Задачи, исполняемые на разных процессорах, могут обмениваться информацией с помощью разделяемой памяти.
Рис. 1. Симметричная мультипроцессорная среда
Распределенная среда
На Рис.1 показана типичная распределенная среда, где есть несколько узлов, связанных между собой сетью. Каждый узел - это компьютер с собственной локальной памятью, который обычно представляет собой мультипрограммную или симметричную мультипроцессорную среду. Кроме того, в каждом узле имеется сетевая карта. Важным отличием распределенной среды является то, что у узлов нет общей памяти. Следовательно, распределенное приложение состоит из параллельных процессов, работающих в разных узлах. Каждый процесс может иметь несколько потоков, исполняемых в том же узле.
Клиент-серверная система логически состоит из двух компонентов: клиента, который запрашивает сервисы, и сервера, который эти сервисы предоставляет. Клиент-серверная система - это распределенное приложение, в котором клиент и сервер (или серверы) географически удалены друг от друга. Сеть, соединяющая клиентов с серверами, может быть локальной или глобальной. Клиент посылает серверу запрос по сети. Сервер выполняет этот запрос и возвращает клиенту результаты.
Рис. 4. Базовая конфигурация системы клиент/сервер
Обычно клиенты и серверы работают на разных машинах. Они могут быть реализованы на разных платформах, под разными операционными системами и в различных сетях. Клиент - это, как правило, настольный ПК или рабочая станция. Часто он поддерживает графический интерфейс пользователя. У сервера обычно имеется большой объем памяти и дисков, мощный процессор и средства повышения надежности. Помимо управления данными, он предоставляет услуги прикладного характера. В простейшей системе клиент-сервер имеется один сервер и много клиентов.
В более сложной системе работает несколько серверов. Клиент может обращаться к различным серверам, а сами серверы - друг к другу.
В распределенном приложении помимо трафика между клиентом и сервером обычно присутствует обширный трафик между равноправными узлами на основе асинхронного обмена сообщениями.
Служба имен
В распределенной среде желательно обеспечить независимость сервисов от местоположения. Это значит, что компонент, желающий послать сообщение другому компоненту, не обязан знать, где находится адресат. Если требовать, чтобы компонент А явно указывал местоположение компонента В, система получится негибкой: при перемещении компонента В придется обновлять компонент А. Поэтому необходима глобальная служба именования, обеспечивающая отделение имен от местоположения сервисов.
При наличии службы именования сервер имен хранит имена глобальных сервисов. Предполагается, что местоположение самого сервера имен хорошо известно. Каждый сервер регистрирует имена и местоположения предоставляемых им сервисов у сервера имен. Если клиент хочет получить доступ к некоторому сервису, он запрашивает информацию о нем у сервера имен.
Пример службы имен - это система доменных имен (DNS), используемая в сети Internet. Поскольку число пользователей Internet очень велико, служба имен распределена между многими серверами.
Cвязывание клиентов и серверов
Термин связывание относится к ассоциации между клиентом и сервером. Статическое связывание выполняется на этапе компиляции и означает, что все обращения клиента к серверу жестко зашиты в код.
Динамическое связывание производится во время выполнения. Оно характеризуется большей гибкостью, чем статическое, но меньшей эффективностью.
Прозрачный обмен сообщениями между распределенными задачами можно реализовать с помощью распределенного ядра распределенной операционной системы. На Рис. 2 приведен пример межзадачной коммуникации с использованием такого ядра.
Рис. 2. Прозрачный поиск сервисов в распределенных приложениях
В каждом узле существует один экземпляр распределенного ядра. Сервер имен хранит главную копию таблицы имен. В тех распределенных приложениях, где число задач относительно постоянно, каждое распределенное ядро также может содержать собственную копию этой таблицы. На стадии начальной загрузки системы распределенное ядро посылает запрос серверу имен с просьбой загрузить таблицу имен.
Когда задача-отправитель посылает сообщение задаче-получателю, локальное ядро определяет местоположение адресата по своей таблице имен. Если получатель находится в том же узле, что и отправитель, то локальное ядро направляет сообщение непосредственно по назначению. Так, на Рис. 2 сообщение от задачи В доставляется напрямую задаче С, так как обе они работают в узле 1. Если же задача-получатель находится в другом узле, то локальное ядро посылает сообщение удаленному ядру, расположенному на нужном узле. Получив сообщение, удаленное ядро переправляет его задаче-получателю.
Сервисы сокетов
Сокеты - это интерфейс прикладных программ (API), предоставляемый многими операционными системами. Он определяет набор операций, доступных приложению для организации обмена данными по сети с другим приложением (например, между клиентом и сервером) по заданному протоколу, например TCP/IP. Сокеты - низкоуровневый механизм коммуникаций, поэтому впоследствии были разработаны более абстрактные интерфейсы, снимающие с приложения заботу о низкоуровневых деталях. К их числу относятся и различные технологии ПО промежуточного слоя.
Обмен сообщениями через порты
В некоторых распределенных системах обмен сообщениями между удаленными узлами реализован с помощью портов, что позволяет максимально ослабить связанность. Компонент (процесс или поток) в одном узле посылает сообщение, не указывая явно имя получателя, а задавая выходной порт. Компонент-получатель забирает сообщения из своего входного порта. На стадии конфигурации системы выходной порт одного компонента подключается к входному порту другого компонента (это называется связыванием). Подобная организация повышает гибкость и имеет больше шансов на повторное использование, поскольку на этапе проектирования компонент не должен явно знать, с кем он будет соединен. Такие решения принимаются позднее, поэтому экземпляры одного и того же компонента могут исполняться в различных средах и приложениях.
Распределенным системам часто приходится работать в гетерогенных средах, когда в разных узлах установлено различное оборудование и операционные системы. Например, когда клиенту на ПК под управлением Windows нужно общаться с сервером под управлением системы UNIX.
ПО промежуточного слоя - это слой программного обеспечения, располагаемый поверх ОС с целью создания однородной платформы, на которой могут функционировать распределенные приложения. Примеры ПО промежуточного слоя: механизм вызова удаленных процедур RPC, технология вызова удаленных методов (RMI) в языке Java, а также технологии СОМ и CORBA.
Предоставляя единообразный метод взаимодействия объектов, технологии ПО промежуточного слоя, такие как CORBA, COM и Java Beans, поощряют повторное использование компонентов, поэтому их часто называют компонентными технологиями.
Платформы для распределенных вычислений
Изначально платформы для распределенных вычислений базировались на модели клиент-сервер. Но в последнее время все большую популярность завоевывает объектная модель. Коммуникации в модели клиент-сервер часто основаны на вызове удаленных процедур. При таком подходе процедуры находятся в адресном пространстве сервера и дистанционно запрашиваются клиентами. Сервер получает от клиента запрос, активизирует нужную процедуру и возвращает ответ.
В объектной модели объекты получают глобальные имена и могут вызываться непосредственно на сервере. Существует два подхода к распределенным вычислениям: модель распределенных объектов и модель мобильного кода. В первом случае объекты размещаются на сервере и вызываются дистанционно, как в Java RMI и CORBA. Во втором случае требуемые объекты мигрируют с сервера на клиент - ярким примером такого метода служат Java-апплеты.
Распределенным системам часто приходится работать в гетерогенных средах, когда в разных узлах установлено различное оборудование и операционные системы. Например, когда клиенту на ПК под управлением Windows нужно общаться с сервером под управлением системы UNIX.
ПО промежуточного слоя - это слой программного обеспечения, располагаемый поверх ОС с целью создания однородной платформы, на которой могут функционировать распределенные приложения. Примеры ПО промежуточного слоя: механизм вызова удаленных процедур RPC, технология вызова удаленных методов (RMI) в языке Java, а также технологии СОМ и CORBA.
Предоставляя единообразный метод взаимодействия объектов, технологии ПО промежуточного слоя, такие как CORBA, COM и Java Beans, поощряют повторное использование компонентов, поэтому их часто называют компонентными технологиями.
Вызовы удаленных процедур
Некоторые распределенные системы поддерживают механизм вызова удаленных процедур (RPC). Клиент в одном узле запрашивает удаленную процедуру сервера, находящегося в другом узле. Вызов удаленной процедуры аналогичен вызову локальной процедуры. Процедура, необходимая клиенту, часто называется клиентской заглушкой (Client Stub). Она принимает запрос и произвольные параметры, упаковывает их в сообщение (данный процесс называется маршалингом) и отправляет сообщение серверу.
Удаленная серверная заглушка (Server Stub) распаковывает сообщение (демаршалинг) и вызывает нужную процедуру, передавая ей параметры. Когда серверная процедура заканчивает обработку запроса, она возвращает результаты серверной заглушке, которая упаковывает их в ответное сообщение и отправляет клиентской заглушке. Клиентская заглушка извлекает результаты из сообщения и возвращает их клиенту в виде выходных параметров. Таким образом, роль клиентской и серверной заглушек сводится к тому, чтобы представить вызовы удаленных процедур так, как если бы они были локальными.
Локально вызывается клиентская заглушка, которая упаковывает имя и параметры процедуры в сообщение, отправляемое по сети. Интерфейсный уровень удаленного узла получает сообщение и передает его серверной заглушке, которая распаковывает сообщение и вызывает указанную процедуру серверного объекта. После завершения процедуры серверная заглушка упаковывает ответ и посылает его по сети. Затем клиентская заглушка распаковывает сообщение и передает его клиентскому объекту.
Среда программирования на языке Java (она называется Java Development Kit - JDK) поддерживает технологию ПО промежуточного слоя RMI (Remote Method Invocation - вызов удаленных методов), которая позволяет распределенным Java-объектам общаться друг с другом [Orfali and Harkey 1998]. В этом случае вместо отправки сообщения некоторой процедуре (как в RPC) клиентский объект посылает сообщение другому объекту и вызывает метод этого объекта (процедуру или функцию).
Роль клиентской заглушки из RPC играет клиентский заместитель (Client proxy) рис. 4.16. Заместитель предоставляет клиентскому объекту тот же интерфейс, что и серверный объект, и скрывает от клиента все детали коммуникации. Соответственно серверный заместитель выполняет функцию серверной заглушки, пряча детали коммуникации от серверного объекта. Серверный заместитель вызывает метод объекта. Если серверного объекта не существует, заместитель создает его.
CORBA (Common Object Request Broker Architecture - единая архитектура брокера объектных запросов) - это стандарт открытых систем, разработанный группой OMG, который обеспечивает взаимодействие между объектами на гетерогенной платформе. Брокер объектных запросов (ORB) выполняет функции ПО промежуточного слоя, поддерживающего отношения вида клиент-сервер между распределенными объектами. Серверные объекты предоставляют сервисы, которые клиенты могут запрашивать с помощью ORB. В общем случае клиенты и серверы - это всего лишь роли объектов. Таким образом, объект способен выступать в роли клиента в отношениях с одним объектом и в роли сервера - в отношениях с другим. С помощью ORB клиентский объект в состоянии вызывать операции серверного объекта, не зная, где тот находится, на какой платформе (аппаратной или программной) исполняется, какие коммуникационные протоколы нужны для связи с ним и на каком языке он написан.
Клиент, имеющий ссылку на серверный объект, может вызывать любые сервисы (операции интерфейса), поддерживаемые этим объектом, через посредство ORB. ORB обладает следующими достоинствами:
В случае статического вызова заглушки и каркасы заранее скомпонованы с исполняемыми файлами. Статические интерфейсы определены в IDL-описаниях, созданных разработчиком. Эти описания транслируются в код заглушек, каркасов и заголовочных файлов, как определено в правилах отображения на конкретный язык. Такой подход проиллюстрирован на рис. 4.17.
Большую гибкость обеспечивает динамическое связывание. В этом случае клиентский объект во время выполнения решает, с каким серверным объектом он будет общаться. Сервер регистрирует IDL-описания в репозитарии интерфейсов, который можно опрашивать во время выполнения.
Клиент пользуется интерфейсом динамического вызова (см. рис. 4.17), который представляет собой обобщенную заглушку, не зависящую от IDL-описания интерфейса вызываемого объекта. Подобный подход позволяет клиенту обращаться к объекту во время выполнения, ничего не зная о его интерфейсе на стадии компиляции.
CORBA поддерживает также интерфейс динамического каркаса на стороне сервера, то есть механизм динамического связывания для серверов, которые должны обрабатывать входящие запросы на обслуживание от объектов, не имеющих скомпилированных из IDL-описаний каркасов. Это полезно для общения с такими внешними объектами, как шлюзы или браузеры.
Сервисы CORBA
Брокер объектных запросов позволяет клиенту прозрачно вызывать операцию серверного объекта, предоставляя службу имен. Когда создается объект CORBA, ему присваивается уникальная объектная ссылка. Получить ссылку можно с помощью просмотра каталога.
Другой сервис, предоставляемый CORBA, - это трейдинг. Он позволяет получить ссылку на объект путем сопоставления характеристик известных объектов (например, типа обслуживания) с характеристиками, посланными клиентом.
Интеграция унаследованных приложений в каркас распределенных объектов.
Многие унаследованные приложения достаточно сложно интегрировать в каркас, состоящий из распределенных объектов. Один из применяемых для этой цели методов состоит в написании объектов-оберток (wrappers). Объект-обертка - это объект распределенного приложения, который обрабатывает запросы клиентов к унаследованной программе. Обертки регистрируют свои сервисы в службе имен, поэтому в состоянии получать запросы от клиентов.
Большинство унаследованных приложений создавались как автономные программы. В некоторых случаях унаследованный код допустимо модифицировать, чтобы объекты-обертки могли получить доступ к нему. Однако часто это неприемлемо, так как документации практически нет, а разработчики уже недоступны. Поэтому обертки обычно общаются с унаследованным кодом при помощи таких грубых механизмов, как файлы - последовательные или индексированные. Обертывающий объект должен читать и модифицировать файлы, создаваемые унаследованным приложением. Если унаследованное приложение пользуется базой данных, то к ней легко обратиться с помощью оберток, скрывающих детали доступа. Например, в случае реляционной базы данных обертка способна содержать предложения на языке SQL для доступа к базе. Возможен и такой вариант, когда обертка имитирует ввод с клавиатуры или переадресует на себя вывод, направленный на экран или принтер.
Спецификация CORBA определяет IDL следующим образом: 'Язык IDL(Interface Defenition Language) является средством описания интерфейсов' к которым обращаются клиенты и которые должны быть реализованы на стороне сервера.
Язык IDL является декларативным, т.е. языком описания типов, интерфейсов, методов и т.д. В качестве основы был использован С++. Помимо объявлений IDL может содержать директивы предпроцессора, полностью взятые из С++.
IDL используется следующим образом: после создания необходимого набора IDL-деклараций и помещение их в один или несколько файлов с расширением .idl. Эти файлы обрабатываются специальными компиляторами, результатом работы которых является набор файлов,часть которых используется на стороне сервера,а часть ; на стороне клиента. Файлы на стороне сервера определяют структуру серверных объектов поэтому их часто называют скелетами(скелетон) Задача програмиста написать код всех методов всех интерфейсов.
Файлы на стороне клиента обрабатывают '' стаб ''(stub), содержащий полностью готовый к выполнению код, который превращает вызовы клиентом локальных методов стаба в вызов соответствующих им удаленных
методов реальных серверных объектов.
Язык стабов и интерфейсов определяется выбором компилятора:
idl2cpp ; текст на С++
idl2Java ; на Java
idl2pas ; Delphi
После этого файлы стабов и скелетов включаются в проект создания клиентских и серверных приложений соответственно.
Любые типы данных, кроме octet, нельзя использовать для передачи произвольной двоичной информации. Это связанно с тем, что данные при выполнении удаленных вызовов может пересекать границы ОС и аппаратных платформ. В этом случае может выполняться, например, перекодировка символов или изменение порядка байтов в целых числах. Только тип octet передается без малейших изменений. Синтаксис работы с символами в IDL такой же как в C++
Под структурированным типом данных будем понимать массивы, последовательности, структуры и объединения.
typedf(определение синонимов типа) используется для задания синонима типа. Не следует делать никаких универсальных предположений об эквивалентности двух синонимов одного типа при отображении на различных языках программирования.
typedf string 20 string20;
Массивы
IDL позволяет задавать многомерные массивы. При создании массивов обязательно использовать typedf. Массив может содержать элементы любых типов. При объявлении массива необходимо явно указать число элементов для каждой размерности.
typedf long longArray [10] [20];
Последовательности Последовательности задаются следующим образом:
typedf sequence string stringSeq;
typedf sequence string unb_string_seq;
В качестве первого аргумента указывается имя типа элементов последовательности. Если необходимо ограничить максимальный размер последовательности то необходимо указать в качестве второго параметра целочисленное значение, известное на стадии компиляции IDL-файла. Такая последовательность называется ограниченной. Главное отличие от массивов состоит в том, что размерности массива должны быть заданы явно. Последовательности могут быть любой длины.
Структуры
Практически аналогичен синтаксису структур С.
Объединения
Пример объявления:
union MyUnion switch (short)
{
case 0:
long Long Field;
case 1:
case 2:
octet OneTwoField;
default:
string StringField;
};
Семантика объединений IDL аналогична C++.
Определить интерфейс ; значит определить тип серверного CORBA-объекта. Заметим,что сам CORBA-объект как экземпляр данного типа на языке IDL создать нельзя, т.к. этот язык не может создавать переменные и выполнять над ними действия.
CORBA-объект чисто логическое понятие.
Пример объявления интерфейса:
interface MyProgram
{ // определение синонимов типов
typedf sequence string CommandLineArgs;
typedf long ResultType;
// константы
const double pi=3,14159828
const string Title='' Программа-оболочка'';
// атрибуты
readonly attribute ResultType retCode
// определение операций
ResultType runProgram(in CommandLineArgs: args);
string getTitle();
void getWerName(out string name);
};
С каждым аргументом метода может быть сопоставлен признак: in,out или inout. Главная задача, которая решает явное исчисление этих признаков ; явное задание того, кто отвечает за выделение памяти под объекты: клиент или сервер.
Спецификация IDL определяет такие атрибуты следующим образом:
in ; парметр передается от клиента к серверу. За выделение памяти под объект и за ее последующее освобождение отвечает клиент. Предполагается, что реализация метода не пытается изменить значение этого параметра.
out ; параметр передается от сервера клиенту. За выделение памяти под объект отвечает сервер. За освобождение ; клиент. Начальное значение параметра не определено и не должно использоваться.
inout ; параметр, создаваемый клиентом, затем передаваемый на сервер. После того как сервер использовал его начальное значение он может уничтожить объект и создать новый, хотя это и не обязательно.За освобождение памяти отвечает клиент.
Атрибуты задаются с помощью ключевого слова atribute. Объявление атрибута не имеет никакого отношения к созданию полей для интерфейсов, т.е. построение интерфейсов с состояниями. Нет возможности задать интерфейс с состоянием на уровне IDL. Хотя CORBA-объект может иметь состояние.
Использование в интерфейсе атрибутов ; просто краткий способ определения методов для данного интерфейса
Следующее объявление:
attribute long MyValue();
эквивалентно следующим двум:
long get_MyValue();
void set_MyValue(in long v);
Если атрибут объявлен как readonly то функция установки значения(set..) отсутствует.
Наследование интерфейсов является очень мощной концепцией. Главным ее достоинством является то, что она позволяет объявлять в IDL методы с аргументами типа объектная ссылка, указывающая в качестве типа такого аргумента базовый интерфейс некоторой их иерархии:
interface Ibase{...};
interface Idevived1{...};
interface Idevived2{...};
....
void MyMethod(in Ibase);
В качестве аргумента при вызове метода MyMethod можно будет использовать объекты типов Ibase, Idevived1 и Idevived2.
Все интерфейсы IDL неявно наследуют интерфейс Object. В частности это означает что некоторому методу в качестве аргумента можно передавать любые интерфейсы, если указать,что типом этого аргумента является Object.
При работе с интерфейсами можно использовать множественное наследование.
interface Ibase1 {...};
interface Ibase2 {...};
interface Idevided: Ibase1, Ibase2 {...};
Обеспечение информации об удаленных объектах подразумевает ее хранение в БД CORBA ; репозитариях интерфейсов. При использовании любой БД для обеспечения доступа к той или иной информации необходимо сопоставить с этой информацией уникальный идентификатор ; ключ. В репозитариях интерфейсов хранится информация о модулях, интерфейсах, типах, константах, операциях и т.д. то есть, практически то же самое, что в idl-файлах. Доступ к тем или иным элементам обеспечивается с помощью ключей которые называются репозитарными идентификаторами.
Спецификация CORBA определяет 4 стандартных формата Read:
Клиент-серверная система состоит из двух компонентов: клиента, который запрашивает сервисы, и сервера, который эти сервисы предоставляет. Клиент-серверная система - это распределенное приложение, в котором клиент и сервер (или серверы) географически удалены друг от друга. Сеть, соединяющая клиентов с серверами, может быть локальной или глобальной. Клиент посылает серверу запрос по сети. Сервер выполняет этот запрос и возвращает клиенту результаты.
Рис. 4. Базовая конфигурация системы клиент/сервер
Обычно клиенты и серверы работают на разных машинах. Они могут быть реализованы на разных платформах, под разными операционными системами и в различных сетях. Клиент - это, как правило, настольный ПК или рабочая станция. Часто он поддерживает графический интерфейс пользователя. У сервера обычно имеется большой объем памяти и дисков, мощный процессор и средства повышения надежности. Помимо управления данными, он предоставляет услуги прикладного характера. В простейшей системе клиент-сервер имеется один сервер и много клиентов.
Модель сервиса представляет собой реализацию ситуации при которой одну услугу реализуют не один, а несколько серверов, представленных клиенту как единое целое. Строго говоря, предложенная модель является клиент-серверной у которой сервер имеет сложную структуру. Этот вариант хорошо подходит для критичных сервисов для которых недопустима приостановка обслуживания. Поскольку сервис реализуется сразу несколькими серверами, остановка одного из них не является критичной.
Для прекращения обслуживания клиентов необходима остановка всех серверов. При такой схеме может быть существенно увеличена как производительность системы, так и ее устойчивость к сбоям. Однако данная модель обладает и недостатками. Самый большой из них ; сложная реализация по сравнению с базовой архитектурой. Поскольку все серверы обеспечивают один и тот же сервис, возникает проблема либо с реализацией обрабатываемых данных, либо с поддержанием целостности распределенных данных.
Технология подключения через прокси.
Отличием от ранее рассмотренных моделей является то, что клиент соединяется не с сервером, а с неким промежуточным посредником. Этот посредник в свою очередь от имени клиента передает запрос серверу. При этом посредник может сам решать на какой из серверов послать запрос. Кроме того, он может поддерживать кэш последних запросов и при очередном запросе пользователя вернуть ему ответ, не обращаясь к серверу.
Сервер, инициирующий соединение.
В классической архитектуре клиент-сервер инициатором диалога всегда выступает клиент. Однако, можно представить и другую ситуацию, когда диалог инициирует сервер. Роль клиента в таком случае сводится к реакции на сообщение сервера. Типичным примером является работа ''по подписке''. Допустим, что сервер получает какие либо события из внешнего источника. События имеют тип. Клиент, заинтересованный в получении события определенного типа собирает о сообщает о своей заинтересованности серверу. Сервер, получив очередное событие передает его всем заинтересованным клиентам.
Мобильные агенты.
Идея рассматриваемой модели состоит в том, что часто клиент сам в состоянии выполнить ту задачу, решение которой он запросил у сервера. Более того, данные необходимые для решения этой задачи располагается на клиенте. В таком случае для разгрузки сервера целесообразно решать эту задачу на клиенте. Для этого необходимо отправить соответствующей программой модуль клиенту. Клиент, получив модуль(мобильный агент) может выполнить его локально решив, таким образом, задачу. В качестве примера можно рассмотреть взаимодействие браузера и web-сервера, возвращающего страницу, содержащую объект. Апплет также передается клиенту и выполняется в браузере, т.е. на клиенте выполняются какие то значимые для пользователя действия.
Основная проблема такого подхода состоит в сложности реализации механизма передачи и выполнения мобильных агентов, а также в сложности контроля безопасности.
Тонкий клиент.
Последнее время наблюдается постоянное увеличение количество применяемых портативных устройств ; сотовых телефонов, КПК и т.д. В таких устройствах есть возможность использовать сервисы ИС посредством wap или web-браузера. Интерфейс, предоставляемый браузерами весьма ограничен. С другой стороны на мобильных устройствах сложно реализовать приложения со сложной бизнес-логикой. Решить эту проблему можно используя технологию тонкого клиента. Суть этой технологии состоит в том, что клиент выполняет ограниченную по функциональности задачу. Схема работы подобных систем в простейшем случае следующая:
Клиентская программа передает весь ввод пользователя(нажатие клавиши и т.п.) по сети серверу. Сервер разбирает и отображает этот ввод и передает клиенту готовые экраны, которые он просто отображает. Этот принцип используется в системах семейства Windows. Таким образом, сервер фактически берет на себя не только задачу управления, но и вообще все задачи по логике клиентского интерфейса.
Приложения выполняемые в такой архитектуре не имеют четкого разделения на серверные и клиентские модули. Все его части равноправны и могут выполняться на любых узлах. Таким образом, на одном и том же узле в один момент выполняются части системы, обрабатывающие запросы других частей. А в другой момент времени ; части системы посылающие запросы. Причем приложение может быть устроено так, что вызывающая часть не знает локально или удаленно расположена вызываемая. Построенное таким образом приложение обладает уникальными свойствами ; его части никак не привязаны друг к другу и к другим узлам, на которых они исполняются. Таким образом, от запуска к запуску может меняться состав модулей, расположенных на узле.
Это позволяет организовывать очень изощренные политики распределения загрузки, а также обеспечивать очень хорошие показатели масштабируемости и отказоустойчивости. Такая архитектура активно используется для разработки параллельных вычислительных систем для решения сложных вычислительных задач.
Это основной элемент управления параллельными процессами в распределенных корпоративных приложениях. Транзакция представляет собой ограниченную последовательность действий с явно определенной начальной и завершающей операцией. Все ресурсы затрачиваемые транзакцией прибывают в согласованном состоянии в момент ее начала и остается в таковом после ее завершения, транзакция должна либо выполняться целиком, либо не выполняться вообще.
Свойства транзакций.
1.Атамарность ; в контексте транзакций либо выполняются все действия, либо не выполняется ни одно из них. Частичное или избирательное выполнение недопустимо. Фиксация (COMMIT) результатов служит свидетельством успешного окончания транзакций, отказ (ROLLBACK) приводит систему в состояние в котором она прибывала до начала транзакций.
2. Согласованность ; системные ресурсы должны прибывать в целостном и непротиворечивом состоянии, как до начала транзакций, так и после ее окончания.
3. Изолированность ; промежуточные результаты транзакции должны быть закрыты для доступа со стороны любой другой действующей транзакции до момента их фиксации. Другими словами транзакция протекает так как будто в тот же период времени других параллельных транзакций не существует.
4. Устойчивость ; результат выполнения транзакций не должен, быть утрачен, не при каких условиях.
Термин параллелизм означает возможность одновременного выполнения многих процессов с доступом к одним и тем же данным, происходящим в одно и то же время. В такой системе для корректной обработки данных параллельными процессами без возникновения конфликтных ситуаций необходимо использовать некоторый метод управления. Стандартный метод разрешения таких проблем ; метод блокировок. Данный метод чаще других встречается на практике.
Каждый метод управления параллелизмом предназначен для решения конкретной задачи. Основные проблемы, возникающие при параллельной обработке транзакций:
Проблема потери результатов обновления.
t |
Транзакция 1 |
Транзакция 2 |
1 |
BeginTransaction |
BeginTransaction |
2 |
B1=Иванов.balance |
|
3 |
B2=Иванов.balance | |
4 |
B1=B1+200 |
|
5 |
Иванов.balance=B1 |
|
6 |
Commit |
Иванов.balance=B2 |
7 |
Commit |
Таблица ; Ситуация, иллюстрирующая потерю результатов в обновлении
Первая транзакция извлекает значение баланса, изменяет его и затем фиксирует. Проблема состоит в том, что вторая транзакция, которая также изменяет состояние баланса, делает это относительно старого, еще неизмененного первой транзакцией значения. Таким образом, при выполнении двух транзакций в указанном порядке, изменения, выполненные первой транзакцией, в худшем случае могут быть просто утеряны.
Проблема появляется, если в некоторой транзакции осуществляется извлечение данных, которая в этот же момент времени обновляет другую транзакцию, но это обновление еще не завершено. Таким образом, некоторая вероятность, что оно не будет завершено никогда (например, может быть выполнен откат транзакции). В таком случае в первой транзакции будут принимать участие данные, которые больше не существуют.
t |
Транзакция 1 |
Транзакция 2 |
1 |
BeginTransaction |
BeginTransaction |
2 |
Иванов.balance+=100 | |
3 |
B=Иванов.balance |
B2=Иванов.balance |
4 |
B=B+200 |
|
5 |
Иванов.balance=B1 |
|
6 |
Commit |
|
7 |
Rollback |
В том случае, если изменения, сделанные второй транзакцией сразу становятся видны всем остальным (режим;грязного; чтения), первая транзакция читает измененные данные. Проведя вычисления, первая транзакция фиксирует результат. Вторая транзакция производит откат изменений. То есть фактически значение баланса, прочитанное первой транзакцией, никогда не существовало. Несмотря на то, что вторая транзакция была отменена, результаты первой транзакции были зафиксированы и отменены не будут.
Возникает в том случае, если одна из транзакций в силу длительного выполнения застает часть данных в одном состоянии (не изменены), а часть в другом (уже изменены). Представим банковское приложение, которое подсчитывает изменение средств на счетах клиентов банка.
Фамилия |
t 1 |
t 2 |
Иванов |
120 |
20 |
Петров |
150 |
150 |
Сидоров |
240 |
240 |
Яковлев |
400 |
500 |
Процедура подсчета идет сверху-вниз по таблице счетов и суммирует их. Допустим, процедура была запущена в момент времени t1. Далее в момент времени t1 и t2 была запущена транзакция, которая состоит из двух действий ; снять 100 рублей у Иванова и перечислить Яковлеву (к этому моменту процедура суммирования уже учла сумму на счете Иванова, но до Яковлева еще не дошла). Вторая транзакция была очень короткой, и после ее завершения, ее результаты стали видны первой процедуре. Таким образом, когда она дойдет до записи со счета Яковлева, она учтет сумму в 500 рублей. В результате сумма счетов будет на 100 рублей завышена.
Основная идея блокировок заключается в том, что если для выполнения некоторой транзакции необходимо, чтобы некоторый объект не изменялся без ведома этой транзакции, то этот объект должен быть заблокирован, т.е. доступ к этому объекту со стороны других транзакций ограничивается на время выполнения транзакции, вызвавшей блокировку.Различают два типа блокировок:
Если транзакция A блокирует объект при помощи X-блокировки, то всякий доступ к этому объекту со стороны других транзакций отвергается.
Если транзакция A блокирует объект при помощи S-блокировки, то
Правила взаимного доступа к заблокированным объектам можно представить в виде следующей матрицы совместимости блокировок.
X |
S | |
X |
0 |
0 |
S |
0 |
1 |
Три случая, когда транзакция B не может блокировать объект, соответствуют трем видам конфликтов между транзакциями.
Доступ к объектам базы данных на чтение и запись должен осуществляться в соответствии со следующим протоколом доступа к данным:
Если все транзакции выполняются на уровне способности к упорядочению, то чередующееся выполнение любого множества параллельных транзакций может быть упорядочено. Если некоторые транзакции выполняются на более низких уровнях, то имеется множество способов нарушить способность к упорядочению. Выделены три особых случая нарушения способности к упорядочению, фактически именно те, которые были описаны как проблемы параллелизма:
Потеря результатов обновления стандартом SQL не допускается, т.е. на самом низком уровне изолированности транзакции должны работать так, чтобы не допустить потери результатов обновления. Различные уровни изоляции определяются по возможности или исключению этих особых случаев нарушения способности к упорядочению.
Уровень изоляции
Неаккуратное считывание
Неповторяемое считывание
Фантомы
Уровень незавершенного считывания
Да
Да
Да
Уровень завершенного считывания
Нет
Да
Да
Уровень повторяемого считывания
Нет
Нет
Да
Уровень способности к упорядочению
Нет
Нет
Нет
30. Двухфазный протокол фиксации транзакций
Суть его состоит в следующем: 1. В системе выделяется менеджер транзакций. 2. Фиксация изменений происходит в 2 этапа:
на 1 этапе изменения верифицируются, производятся все необходимые проверки, которые гарантируют что все изменения готовы к переходу в долговременную память (некоторые реализации уже на этой фазе переносят изменения в долговременную память помечая их как незафиксированные).
2 фаза начинается только после того как узлы вовлеченные в транзакцию сообщает координатору об успешном завершении первой фазы. 2 фаза состоит в простом переносе уже подготовленных изменений в долговременную память.