Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Сеансовые протоколы и протоколы представления

Поиск

Глава 2 Связь

2.1.Уровни протоколов

2.2.Удаленный вызов процедур

2.3.Обращение к удаленным объектам

2.4.Связь посредством сообщений

2.5.Связь на основе потоков данных

2.6.Итоги

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

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

1. удален­ный вызов процедур (Remote Procedure Call, RPC),

2. удаленное обращение к ме­тодам (Remote Method Invocation, RMI),

3. ориентированный на сообщения про­межуточный уровень (Message-Oriented Middleware, MOM) ) и

4. потоки данных (streams).

Нашей первой моделью взаимодействия в распределенных системах станет удаленный вызов процедур. Механизм RPC нацелен на сокрытие большей части проблем передачи сообщений и идеален для приложений архитектуры клиент-сервер. Усовершенствованный вариант модели RPC имеет вид удаленного обра-

 

82 Глава 2. Связь

щения к методам, которое основано на представлении распределенных объектов. Механизмы RPC и RMI рассматриваются в отдельных разделах.

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

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

Уровни протоколов

В условиях отсутствия совместно используемой памяти вся связь в распределен­ных системах основана на обмене (низкоуровневыми) сообщениями. Если про­цесс А хочет пообщаться с процессом В, он должен сначала построить сообщение в своем собственном адресном пространстве. Затем он выполняет системный вы­зов, который пересылает сообщение по сети процессу В. Хотя основная идея выглядит несложной, во избежание хаоса А и В должны договориться о смысле пересылаемых нулей и единиц. Если А посылает потрясающий новый роман, на­писанный по-французски, в кодировке IBM EBCDIC, а В ожидает результаты пе­реучета в супермаркете, на английском языке и в кодировке ASCII, их взаимо­действие будет не слишком успешным.

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

Чтобы упростить работу с множеством уровней и понятий, используемых в передаче данных, Международная организация по стандартам (International Standards Organization, ISO) разработала эталонную модель, которая ясно опре­деляет различные уровни, дает им стандартные имена и указывает, какой уро­вень за что отвечает. Эта модель получила название Эталонной модели взаимо­действия открытых систем (Open Systems Interconnection Reference Model) [120].

 

 

2.1. Уровни протоколов 83

Это название обычно заменяется сокращением модель ISO OSI, или просто мо­дель OSI. Следует заметить, что протоколы, которые должны были реализовы-вать части модели OSI, никогда не получали широкого распространения. Однако сама по себе базовая модель оказалась вполне пригодной для исследования ком­пьютерных сетей. Несмотря на то что мы не собираемся приводить здесь полное описание этой модели и всех ее дополнений, небольшое введение в нее будет нам полезно. Дополнительные детали можно почерпнуть в [446].

Модель OSI разрабатывалась для того, чтобы предоставить открытым систе­мам возможность взаимодействовать друг с другом. Открытая система — это система, которая способна взаимодействовать с любой другой открытой систе­мой по стандартным правилам, определяющим формат, содержимое и смысл от­правляемых и принимаемых сообщений. Эти правила зафиксированы в том, что называется протоколами {protocols). Для того чтобы группа компьютеров могла поддерживать связь по сети, они должны договориться об используемых прото­колах. Все протоколы делятся на два основных типа. В протоколах с установле­нием соединения {connection-oriented) перед началом обмена данными отправи­тель и получатель должны установить соединение и, возможно, договориться о том, какой протокол они будут использовать. После завершения обмена они должны разорвать соединение. Системой с установлением соединения является, например, телефон. В случае протоколов без установления соединения {connec­tionless) никакой подготовки не нужно. Отправитель посылает первое сообще­ние, как только он готов это сделать. Письмо, опущенное в почтовый ящик, — пример связи без установления соединения. В компьютерных технологиях ши­роко применяется как связь с установлением соединения, так и связь без уста­новления соединения.

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

Когда процесс А на машине 1 хочет пообщаться с процессом В на машине 2, он строит сообщение и посылает его прикладному уровню своей машины. Этот уровень может представлять собой, например, библиотечную процедуру или реа-лизовываться как-то иначе (например, внутри операционной системы или внеш­него сетевого процессора). Программное обеспечение прикладного уровня до­бавляет в начало сообщения свой заголовок {header) и передает получившееся сообщение через интерфейс с уровня 7 на уровень 6, уровень представления. Уровень представления, в свою очередь, добавляет в начало сообщения свой за­головок и передает результат вниз, на сеансовый уровень и т. д. Некоторые уров­ни добавляют не только заголовок в начало, но и завершение в конец. Когда со­общение дойдет до физического уровня, он осуществит его реальную передачу, как это показано на рис. 2.2.

 

84 Глава 2. Связь

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

В качестве примера важности многоуровневых протоколов рассмотрим обмен информацией между двумя компаниями, авиакомпанией Zippy Airlines и постав­щиком продуктов Mushy Meals, Inc. Каждый месяц начальник отдела обслужи­вания пассажиров Zippy просит свою секретаршу связаться с секретаршей ме­неджера по продажам Mushy и заказать 100 000 коробок «резиновых» цыплят. Обычно заказы пересылались почтой. Однако из-за постепенного ухудшения ка­чества почтовых услуг в один прекрасный момент секретарши решают больше не писать друг другу письма, а связываться по факсу. Они могут делать это, не беспокоя своих боссов, поскольку протокол касается физической передачи зака­зов, а не их содержания.

 

2.1. Уровни протоколов 85

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

В модели OSI, как было показано на рис. 2.1, не два уровня, а семь. Набор протоколов, используемых в конкретной системе, называется комплектом, или стеком протоколов. Важно отличать эталонную модель от реальных протоколов. Как мы отмечали, протоколы OSI никогда не были популярны. В противополож­ность им протоколы, разрабатывавшиеся для Интернета, такие как TCP и IP, используются повсеместно. В последующих пунктах мы кратко рассмотрим каж-лый из уровней модели OSI, начиная с нижнего. Однако вместо того, чтобы при­водить примеры соответствующих протоколов OSI, мы рассмотрим протоколы 11нтернета, используемые на каждом из этих уровней.

Низкоуровневые протоколы

Мы начнем с обсуждения трех нижних уровней комплекта протоколов OSI. Эти три уровня совместно реализуют основные функции компьютерной сети.

Физический уровень

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

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

Канальный уровень

Физический уровень только пересылает биты. Пока нет ошибок, все хорошо. Од­нако в реальных сетях происходят ошибки, и их нужно как-то находить и исправ­лять. Это и является главной задачей канального уровня. Он группирует биты в модули, обычно называемые кадрами {frames), и следит за тем, чтобы каждый кадр был передан правильно.

Канальный уровень делает это путем помещения специальной битовой маски в начало и конец каждого кадра для их маркировки, а также путем вычисления контрольной суммы {checksum), то есть суммирования всех байтов кадра опреде-

 

86 Глава 2. Связь

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

На рис. 2.3 мы видим случай (отчасти патологический) посылки двух сооб­щений 1 и 2 с машины А на машину В. Сообщение с данными 0 посылается с ма­шины А в момент времени 0. Когда в момент времени 1 это сообщение достигает машины В, обнаруживается, что оно повреждено помехами в линии передачи и контрольная сумма не соответствует действительности. Машина В обнаружи­вает это и в момент времени 2 запрашивает повторную посылку, отправляя соот­ветствующее контрольное сообщение 0. К сожалению, в тот же самый момент машина А посылает сообщение 1. В ответ на полученный машиной А запрос на повторную посылку отправляется сообщение 0. Когда машина В получает сооб­щение с данными 1 (а ведь она запрашивала сообщение с данными 0!), она посы­лает машине А новое контрольное сообщение 1, настаивая на том, что она хочет получить сообщение с данными 0, а не 1. Когда контрольное сообщение 1 дохо­дит до машины А, та посылает сообщение с данными 0 в третий раз.

Задача этого обсуждения — не показать, насколько хорош описанный прото­кол (он очень плох), а объяснить, что на каждом уровне существует необходи­мость во взаимодействии между отправителем и получателем. Типичные сооб­щения: «Пошли, пожалуйста, сообщение п заново» — «Уже посылал дважды» —

 

 

2.1. Уровни протоколов 87

«Нет, ты этого не делал» — «А я говорю, делал» — «Ну ладно, пускай делал, все равно пошли еще раз» и т. д. Это взаимодействие происходит в полях заголовка, где определены различные запросы и ответы и могут поддерживаться параметры (например, номера кадров).

Сетевой уровень

В локальных сетях у отправителя обычно нет необходимости находить местопо­ложение получателя. Он просто бросает сообщение в локальную сеть, а получа-тель забирает его оттуда. Глобальные сети, однако, содержат множество машин, каждая из которых имеет собственные линии связи с другими машинами. Так на крупномасштабной карте показано множество городов и соединяющих их дорог. Сообщение, посылаемое от отправителя к получателю, должно пройти массу сетевых сегментов, на каждом из которых происходит выбор исходящей линии. Задача выбора наилучшего пути называется маршрутизацией (routing) и является

основной задачей сетевого уровня.

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

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

протоколом является не требующий установки соединения протокол Интерне- (Internet protocol, IP), входящий в комплект протоколов Интернета. На сете-

вом уровне сообщение именуется термином пакет (packet). IP-пакет может быть

послан без какой-либо предварительной подготовки. Маршрут каждого из 1Р-па-

кетов до места назначения выбирается независимо от других пакетов. Никакие внутренние пути не выбираются заранее и не запоминаются.

Протоколом с соединением, приобретающим популярность в настоящее вре-мя является виртуальный канал (virtual channel) па базе сетей ATM. Виртуальный канал в ATM — это непрямое соединение, устанавливаемое от источника к приемнику, возможно, проходящее через несколько промежуточных АТМ-комутаторов. Чтобы между двумя компьютерами не устанавливать каждый из виртуальных каналов по отдельности, набор виртуальных каналов может быть сгрупирован в виртуальный путь (virtual path). Виртуальный путь сравним с предопределенным маршрутом между двумя узлами, вдоль которого выстраиваются его виртуальные каналы. Изменение маршрута виртуального пути означает юматическую перекладку всех ассоциированных с ним каналов [194].

2.1.2. Транспортные протоколы (метод_Метелап ЛР_1)

;нспортный уровень — это последняя часть того, что называют базовым стеком

евых протоколов, поскольку в нем реализованы все службы, которые необхо-

димы для построения сетевых приложений и которые не вошли в интерфейс се-

 

88 Глава 2. Связь

тевого уровня. Другими словами, транспортный уровень дает возможность разра­ботчикам приложений использовать базовую сеть, лежащую в его основе.

Функции транспортного уровня

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

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

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

Транспортный протокол для Интернета называется протоколом управления передачей (Transmission Control Protocol, TCP). Он детально разобран в книге [109]. Комбинация TCP/IP в настоящее время является стандартом де-факто при сете­вых взаимодействиях. Комплект протоколов Интернета также включает в себя не требующий соединения транспортный протокол под названием UDP (Univer­sal Datagram Protocolуниверсальный протокол датагралш), который, по сути, представляет собой IP с некоторыми небольшими дополнениями. Пользователь­ские программы, не нуждающиеся в протоколе с соединениями, обычно исполь­зуют UDP.

Официальный транспортный протокол ISO имеет пять разновидностей — от ТР0 до ТР4. Различия относятся к обработке ошибок и к возможности работать с несколькими транспортными соединениями на базе одного соединения низко­го уровня (особенно Х.25). Выбор того, какой из них использовать, зависит от свойств лежащего ниже сетевого уровня. Никогда ни один из них не должен пе­регружаться.

Время от времени предлагаются дополнительные транспортные протоколы. Так, например, для поддержки передачи данных в реальном времени был опре­делен транспортный протокол реального времени (Real-time Transport Protocol, RTP). RTP — это кадровый протокол, который определяет формат пакета для

 

2.1. Уровни протоколов 89

данных реального времени, ничего не говоря о механизмах гарантированной дос­тавки этих данных. Кроме того, в нем определен протокол для мониторинга и управления передачей RTP-пакетов [406].

TCP в архитектуре клиент-сервер

Взаимодействие клиент-сервер в распределенных системах часто осуществляется путем использования транспортного протокола базовой сети. С ростом популяр­ности Интернета нередко можно наблюдать построение приложений клиент-сер­вер и систем на базе TCP. Преимущества протокола TCP по сравнению с UDP состоят в том, что он надежно работает в любой сети. Очевидная оборотная сто­рона — протокол TCP создает значительную дополнительную нагрузку на сеть, особенно в тех случаях, когда базовая сеть высоконадежна, например, в локаль­ных сетях.

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

Протокол TCP во многих случаях непривлекателен из-за невозможности при­способить его для поддержки синхронного поведения запрос-ответ, используемого во многих взаимодействиях клиент-сервер. На рис. 2.4, а показано применение протокола TCP для поддержки взаимодействия клиент-сервер в нормальных ус­ловиях (когда сообщения не пропадают). Сначала клиент инициирует установ­ление соединения, которое происходит по трехэтапному протоколу установле­ния связи (первые три сообщения на рисунке). Этот протокол необходим для достижения договоренности о порядке нумерации пакетов, пересылаемых через соединение (детали можно найти в [446]). Когда соединение установлено, кли­ент посылает свой запрос (сообщение 4), сопровождаемый пакетом, требующим от сервера разорвать соединение (сообщение 5).

Сервер отвечает немедленным подтверждением приема запроса от клиента, которое скомпоновано с подтверждением разрыва соединения (сообщение 6). Затем сервер выполняет требуемую работу и посылает клиенту ответ (сообще­ние 7), также сопровождаемый требованием разорвать соединение (сообщение 8). Клиент должен только послать подтверждение разрыва связи на сервер (сообще­ние 9).

Ясно, что большая часть дополнительной нагрузки на сеть связана с управле­нием соединением. При использовании TCP для управления взаимодействием клиент-сервер гораздо дешевле будет скомбинировать установление соединения с немедленной посылкой запроса, а посылку ответа — с разрывом соединения. Получившийся протокол носит название TCP для транзакций (TCP for Tran­sactions), сокращаемое до Т/ТСР. То, как функционирует этот протокол в нор­мальных условиях, можно увидеть на рис. 2.4, б.

В нормальной обстановке происходит следующее: клиент посылает одно со­общение (сообщение 1), содержащее три порции информации: запрос на уста-

 

92 Глава 2. Связь

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

Сервер отвечает только после того, как обработает запрос. Он может послать данные, для передачи которых и создавалось соединение, и немедленно потребо­вать его разрыва, что иллюстрирует сообщение 2. После этого клиенту остается только подтвердить разрыв соединения (сообщение 3).

Протокол Т/ТСР, созданный как расширение TCP, автоматически преобра­зуется в нормальный протокол TCP, если другая сторона не поддерживает это расширение. Дополнительную информацию по TCP/IP можно найти в [437].

Протоколы верхнего уровня

Поверх транспортного уровня OSI указывает на наличие трех дополнительных уровней. На практике используется только прикладной уровень. На самом деле в комплекте протоколов Интернета все, что находится выше транспортного уров­ня, собирается в одну «кучу». В этом пункте мы увидим, почему с точки зрения систем промежуточного уровня нас не устраивает ни подход OSI, ни подход Ин­тернета.

Прикладные протоколы

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

Чего в этой модели нет — так это четкого разграничения приложений, специ­альных протоколов приложений и протоколов общего назначения. Так, напри­мер, популярный в Интернете протокол передачи файлов (File Transfer Protocol, FTP) [203, 361] определяет передачу файлов между клиентской машиной и сер­вером. Этот протокол не следует путать с программой ftp, которая представляет собой законченное приложение для передачи файлов и совпадает (но не полно­стью) с реализацией протокола FTP для Интернета.

Другим примером сугубо специального прикладного протокола [142] может служить протокол передачи гипертекста (Hypertext Transfer Protocol, HTTP), раз­работанный для удаленного управления и загрузки web-страниц. Протокол реа­лизован в таких приложениях, как web-браузеры и web-серверы. Однако сейчас этот протокол используется и в системах, связь которых с Web не предполагает­ся. Так, например, в RMI в языке Java протокол HTTP используется для обра­щения к удаленному объекту, защищенному брандмауэром [441].

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

Удаленный вызов процедур

Основой множества распределенных систем является явный обмен сообщениями между процессами. Однако процедуры send и receive не скрывают взаимодейст­вия, что необходимо для обеспечения прозрачности доступа. Эта проблема была известна давно, но по ней мало что было сделано до появления в 1980 году статьи [62], в которой предлагался абсолютно новый способ взаимодействия. Хотя идея была совершенно простой (естественно, после того как кто-то все придумал), ее реализация часто оказывается весьма хитроумной. В этом разделе мы рассмот­рим саму концепцию, ее реализацию, сильные и слабые стороны.

Если не вдаваться в подробности, в упомянутой статье было предложено по­зволить программам вызывать процедуры, находящиеся на других машинах. Когда процесс, запущенный на машине А, вызывает процедуру с машины В, вызываю-

 

94 Глава 2. Связь

щий процесс на машине А приостанавливается, а выполнение вызванной проце­дуры происходит на машине В. Информация может быть передана от вызываю­щего процесса к вызываемой процедуре через параметры и возвращена процессу в виде результата выполнения процедуры. Программист абсолютно ничего не за­метит. Этот метод известен под названием удаленный вызов процедур (Remote Procedure Call, RPC).

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

Базовые операции RPC

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

Общепринятые вызовы процедур

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

count = read(fd, buf, bytes);

Здесь fd — целое, указывающее на файл; buf — массив символов, в который будут считываться данные; bytes — другое целое, говорящее, сколько байт следует считать. Если вызов производится из главной программы, стек до вызова выгля­дит так, как показано на рис. 2.6, а. Делая вызов, вызывающая программа поме­щает параметры в стек в порядке «последний первым», как показано на рис. 2.6, б. Причина, по которой компилятор С помещает параметры в стек в обратном по­рядке, заключается в функциях типа printf. Чтобы выполняться, функция printf всегда должна знать, где искать свой первый аргумент — строку формата. После завершения read система помещает возвращаемое значение в регистр, удаляет адрес возврата и возвращает управление назад, в вызвавшую программу. Затем вызвавшая программа удаляет из стека параметры, приводя его в исходное со­стояние.

Следует особо отметить некоторые моменты. Во-первых, в С параметры мо­гут передаваться как по значению, так и по ссылке. Параметр-значение, такой как fd или bytes, просто копируется в стек, что и показано на рис. 2.6, б. Для вы­зываемой процедуры параметр-значение представляет собой просто инициали­зированную локальную переменную. Вызываемая процедура может ее изменить,

 

 

 
 

 

2.2. Удаленный вызов процедур 95

 


но все эти изменения не могут повлиять на ее оригинальное значение на вызы­вающей стороне.

Параметр-ссылка в С — это указатель на переменную (то есть адрес перемен­ной), а не ее значение. В вызове read второй параметр является параметром-ссылкой, поскольку массивы в С всегда передаются через ссылку. В стек на са­мом деле будет помещен адрес символьного массива. Если вызванная процедура использует этот параметр для помещения чего-либо в символьный массив, это приведет к изменению массива в вызывающей программе. Мы увидим, что разница между параметрами-значениями и параметрами-ссылками крайне важ­на для RPC.

Существует еще один механизм передачи параметров, не применяющийся в С. Он называется вызов через копирование/восстановление {call-by-copy/restore). В этом случае до вызова вызывающей программой производится копирование переменной в стек, как при вызове по значению, а после завершения вызова — копирование этой переменной из стека назад, с удалением исходного значения этой переменной. В большинстве случаев это дает тот же эффект, что и при вы­зове по ссылке. Однако иногда, например, если один и тот же параметр присут­ствует в списке аргументов многократно, их семантика различается. Во многих языках вызов через копирование/восстановление отсутствует.

Решение об использовании того или иного механизма передачи параметров принимается обычно разработчиками языка и является его фиксированным свой­ством. Раньше это решение зависело от типов передаваемых данных. В С, напри­мер, как мы видели, целые и другие скалярные типы всегда передаются по значе­нию, а массивы — по ссылке. Некоторые компиляторы языка Ада поддерживают вызов через копирование/восстановление для изменяемых {in out) параметров, передавая остальные по ссылке. Определение языка позволяет выбрать любой вариант, который хоть немного упрощает семантику.

 

96 Глава 2. Связь

Заглушки для клиента и сервера

Идея, стоящая за RPC, состоит в том, чтобы удаленный вызов процедур выглядел точно так же, как и локальный. Другими словами, мы ждем от RPC прозрачно­сти — вызывающая процедура не должна уведомляться о том, что вызываемая процедура выполняется на другой машине, и наоборот. Предположим, программа хочет считать некоторые данные из файла. Для чтения из файла необходимых данных программист помещает в код вызов read. В традиционной (однопроцес­сорной) системе процедура read извлекается компоновщиком из библиотеки и вставляется в объектный код программы. Это короткая процедура, которая обыч­но реализуется путем системного вызова read. Другими словами, процедура read — это интерфейс между кодом пользователя и локальной операционной сис­темой.

Даже если read — это системный вызов, он производится аналогичным обра­зом, путем помещения параметров в стек, как показано на рис. 2.6, б. Таким обра­зом, программист так и не узнает, что read делает что-то хитрое.

RPC организует свою прозрачность аналогичным образом. Если read являет­ся удаленной процедурой (то есть будет исполняться на машине файлового сер­вера), в библиотеку помещается специальная версия read, называемая клиент­ской заглушкой {client stub). Как и оригинальная функция, она также вызывается в соответствии с последовательностью, показанной на рис 2.6, б. Как и оригинал, она также производит вызов локальной операционной системы, только в от­личие от оригинальной функции клиентская заглушка ие запрашивает данные у операционной системы. Вместо этого она упаковывает параметры в сообщение и путем вызова процедуры send требует переслать это сообщение на сервер, как показано на рис. 2.7. После вызова процедуры send клиентская заглушка вызыва­ет процедуру recei ve, блокируясь до получения ответа.

Когда сообщение приходит на сервер, операционная система сервера передает его серверной заглушке {server stub). Серверная заглушка эквивалентна клиент­ской, но работает на стороне сервера. Это фрагмент кода, который преобразует приходящие по сети запросы в вызовы локальных процедур. Обычно серверная заглушка запускает процедуру recei ve и блокируется, ожидая входящих сообще­ний. После получения сообщения серверная заглушка распаковывает его, извле­кая параметры, и традиционным способом (то есть так, как показано на рис. 2.6)

 

2.2. Удаленный вызов процедур 97

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

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

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



Поделиться:


Последнее изменение этой страницы: 2016-09-19; просмотров: 631; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 18.222.44.156 (0.019 с.)