Э. Таненбаум, М. ван Стеен - Распределённые системы (принципы и парадигмы) (1162619), страница 23
Текст из файла (страница 23)
Так, например, в следующих двухпунктах мы обсудим протоколы, которые позволяют процессам прозрачно вызывать процедуры или обращаться к объектам на удаленных машинах. Существуюттакже коммуникационные службы высокого уровня для запуска и синхронизациипотоков данных в реальном времени, что характерно, например, для мультимедийных приложений. В качестве последнего примера приведем предоставляемыенекоторыми системами промежуточного уровня надежные службы групповойрассылки, способные поддерживать тысячи получателей, разбросанных по глобальной сети.Некоторые из коммуникационных протоколов промежуточного уровня могутбыть помещены и на транспортный уровень, но для их «повышения» имеютсяособые причины.
Так, например, службы надежной групповой рассылки с гарантированной масштабируемостью могут быть реализованы, только если принимаютсяво внимание требования к приложению. Соответственно, системы промежуточного уровня могут предоставлять те или иные протоколы (настраиваемые), каждый из которых реализует различные транспортные протоколы, но предоставляет одинаковый интерфейс.2.2.
Удаленный вызов процедур93Такой подход к подразделению на уровни приводит нас к слегка измененнойэталонной модели взаимодействия (рис. 2.5). По сравнению с моделью OSI сеансовый уровень и уровень представления заменены одним промежуточным уровнем, который содержит не зависящие от приложений протоколы. Как мы говорили, эти протоколы нельзя поместить на более низкие уровни. Истинныетранспортные службы также могут быть представлены в виде служб промежуточного уровня.
Для этого не потребуется даже модрхфикации. Этот подход аналогичен переносу UDP на транспортный уровень. Точно так же службы промежуточного уровня могут включать в себя службы пересылки сообщегп^й, схожиес теми, которые предоставляются на транспортном уровне.^^ПриложениеПромежуточный уровеньТранспортСетьПередача данныхФизическое воплощение^-^^-^~wПромежуточный протоколТранспортный протокол^-Ы--^^-^^-^tПрикладной протоколСетевой протоколКанальный протокол--WW_wW--WW--W1111wФизический протокол_w1wСетьРис. 2.5. Измененная эталонная модель сетевого взаимодействияВ оставшейся части этой главы мы сосредоточимся на четырех высокоуровневых коммуникационных службах промежуточного уровня: удаленном вызове процедур, удаленном обращении к объектам, очередям сообщений и потокамданных.2.2. Удаленный вызов процедурОсновой множества распределенных систем является явный обмен сообщениямимежду процессами.
Однако процедуры send и receive не скрывают взаимодействия, что необходимо для обеспечения прозрачности доступа. Эта проблема былаизвестна давно, но по ней мало что было сделано до появления в 1980 году статьи[62], в которой предлагался абсолютно новый способ взаимодействия. Хотя идеябыла совершенно простой (естественно, после того как кто-то все придумал), еереализация часто оказывается весьма хитроумной. В этом разделе мы рассмотрим саму концепцию, ее реализацию, сильные и слабые стороны.Если не вдаваться в подробности, в упомянутой статье было предложено позволить программам вызывать процедуры, находяицтеся на других машинах.
Когдапроцесс, запущенный на машине Л, вызывает процедуру с машины Б, вызываю-94Глава 2. Связьщий процесс на машине Л приостанавливается, а выполнение вызванной процедуры происходит на машине В. Информация может быть передана от вызывающего процесса к вызываемой процедуре через параметры и возвращена процессув виде результата выполнения процедуры.
Программист абсолютно ничего не заметит. Этот метод известен под названием удаленный вызов процедур {RemoteProcedure Call, RPC).Базовая идея проста и элегантна, сложности возникают при реализации. Дляначала, поскольку вызывающий процесс и вызываемая процедура находятся наразных машинах, они выполняются в различных адресных пространствах, что тутже рождает проблемы. Параметры и результаты также передаются от машинык машине, что может вызвать свои затруднения, особенно если машины не одинаковы. Наконец, обе машины могут сбоить, и любой возможный сбой вызовет разнообразные сложности. Однако с большинством из этих проблем можносправиться, и RPC является широко распространенной технологией, на которойбазируются многие распределенные системы.2 .
2 . 1 . Базовые операции RPCМы начнем с обсуждения общепринятых вызовов процедур, а затем рассмотрим,как вызов может быть распределен между клиентской и серверной частями системы, каждая из которых выполняется на различных машинах.Общепринятые вызовы процедурДля того чтобы понять, как работает RPC, важ]1о сначала разобраться, как осуществляются общепринятые (в пределах одной машины) вызовы процедур. Рассмотрим вызов в языке типа С:count = readCfd. buf. bytes):Здесь fd — целое, указывающее на файл; buf — массив символов, в которыйбудут считываться дaн^H:)Ie; bytes — другое целое, говорящее, сколько байт следуетсчитать.
Если вызов производится из главной программы, стек до вызова выглядит так, как показано на рис. 2.6, а. Делая вызов, вызывающая программа помещает параметры в стек в порядке «последний первым», как показано на рис. 2.6, б.Причина, по которой компилятор С помещает параметры в стек в обратном порядке, заключается в функциях типа printf. Чтобы выполняться, функция printfвсегда должна знать, где искать свой первый аргумент — строку формата. Послезавершения read система помещает возвращаемое значение в регистр, удаляетадрес возврата и возвращает управление назад, в вызвавшую программу. Затемвызвавшая программа удаляет из стека параметры, приводя его в исходное состояние.Следует особо отметить некоторые моменты. Во-первых, в С параметры могут передаваться как по значению, так и по ссылке.
Параметр-значение, такойкак fd или bytes, просто копируется в стек, что и показано на рис. 2.6, б. Для вызываемой процедуры параметр-значение представляет собой просто инициализированную локальную переменную. Вызываемая процедура может ее изменить.2.2. Удаленный вызов процедур95но все эти изменения не могут повлиять на ее оригинальное значение на вызывающей стороне.Указатель стекаЛокальные переменныеглавной программыЛокальные переменныеглавной программыbytesbutfdАдрес возвратаЛокальные переменныепроцедуры readРис.
2.6. Передача параметров при локальном вызове процедуры: стек до вызовафункции read (а). Стек во время работы вызванной процедуры (б)Параметр-ссылка в С — это указатель на переменную (то есть адрес переменной), а не ее значение. В вызове read второй параметр является параметромссылкой, поскольку массивы в С всегда передаются через ссылку. В стек на самом деле будет помещен адрес символьного массива. Если вызванная процедураиспользует этот параметр для помещения чего-либо в символьный массив, этоприведет к изменению массива в вызывающей программе.
Мы увидим, чторазница между параметрами-значениями и параметрами-ссылками крайне важна для RPC.Существует еще один механизм передачи параметров, не применяющийся в С.Он называется вызов через копирование/восстановление {call-by-сору/restore).В этом случае до вызова вызывающей программой производится копированиепеременной в стек, как при вызове по значению, а после завершения вызова —копирование этой переменной из стека назад, с удалением исходного значенияэтой переменной.
В большинстве случаев это дает тот же эффект, что и при вызове по ссылке. Однако иногда, например, если один и тот же параметр присутствует в списке аргументов многократно, их семантика различается. Во многихязыках вызов через копирование/восстановление отсутствует.Решение об использовании того или иного механизма передачи параметровпринимается обычно разработчиками языка и является его фиксированным свойством.
Раньше это решение зависело от типов передаваемых данных. В С, например, как мы виделР!, целые и другие скалярные типы всегда передаются по значению, а массивы — по ссылке. Некоторые компиляторы языка Ада поддерживаютвызов через копирование/восстановление для изменяемых {in out) параметров,передавая остальные по ссылке.
Определение языка позволяет выбрать любойвариант, который хоть немного упрощает семантику.96Глава 2. СвязьЗаглушки для клиента и сервераИдея, стоящая за RPC, состоит в том, чтобы удаленный вызов процедур выгляделточно так же, как и локальный. Другими словами, мы ждем от RPC прозрачности — вызывающая процедура не должна уведомляться о том, что вызываемаяпроцедура выполняется на другой машине, и наоборот. Предположим, программахочет считать некоторые данные из файла. Для чтения из файла необходимыхданных программист помещает в код вызов read. В традиционной (однопроцессорной) системе процедура read извлекается компоновщиком из библиотеки ивставляется в объектный код программы.