Объекты времени компиляции против объектов времени выполнения 


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



ЗНАЕТЕ ЛИ ВЫ?

Объекты времени компиляции против объектов времени выполнения



Объекты в распределенных системах существуют в различных формах. В наибо­лее распространенном варианте они соответствуют объектам выбранного языка программирования, например Java, C++ или другого объектно-ориентированного языка, и представляют собой объекты времени компиляции. В этих случаях объ­ект является экземпляром класса. Класс — это описание абстрактного типа в виде модуля, содержащего элементы данных и операций над этими данными [291].

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

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

 

 

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

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

При работе с объектами времени исполнения тот способ, которым они будут реализованы, обычно остается открытым. Так, например, разработчик может ре­шить написать на С библиотеку, содержащую набор функций, которые смогут работать с общим файлом данных. Главный вопрос состоит в том, как превра­тить эту реализацию в объект, методы которого будут доступны с удаленной ма­шины. Традиционный способ состоит в том, чтобы использовать адаптер объектов {object adapter), который послужит оболочкой {wrapper) реализации с единствен­ной задачей — придать реализации видимость объекта. Сам термин «адаптер» взят из шаблона проектирования, описанного в [157], который предоставляет ин­терфейс, преобразуемый в то, что ожидает клиент. Примером адаптера объектов может быть некая сущность, динамически привязываемая к описанной ранее библиотеке на С и открывающая файл данных, соответствующий текущему со­стоянию объекта.

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

Сохранные и нерезидентные объекты

Помимо деления на объекты, зависящие от языка программирования, и объекты времени выполнения существует также деление на сохранные и нерезидентные объекты. Сохранный объект {persistent object) — это объект, который продолжает существовать, даже не находясь постоянно в адресном пространстве серверного процесса. Другими словами, сохранный объект не зависит от своего текущего серве­ра. На практике это означает, что сервер, обычно управляющий таким объектом, может сохранить состояние объекта во вспомогательном запоминающем устрой­стве и завершить свою работу. Позже вновь запущенный сервер может считать состояние объекта из запоминающего устройства в свое адресное пространство и обработать запрос на обращение к объекту. В противоположность ему, нерези­дентный объект {transient object) — это объект, который существует, только пока сервер управляет им. Когда сервер завершает работу, этот объект прекращает су­ществовать. Использовать сохранные объекты или нет — это спорный вопрос. Некоторые полагают, что нерезидентных объектов вполне достаточно. Сейчас мы не будем вдаваться в детали и вернемся к этому вопросу, когда будем обсуждать объектные распределенные системы в главе 9.

Привязка клиента к объекту

Интересная разница между традиционными системами RPC и системами, под­держивающими распределенные объекты, состоит в том, что последние обычно

 

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

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

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

При неявной привязке (implicit binding) клиенту предоставляется простой ме­ханизм, позволяющий напрямую запрашивать методы, используя только ссылку на объект. Так, например, в C++ можно переопределить унарный оператор выбо­ра (->) для класса так, чтобы он позволял обращаться со ссылками на объекты как с простыми указателями (листинг 2.1). В случае неявной привязки клиент прозрачно связывается с объектом в момент разрешения ссылки и получения этого объекта в действительности. С другой стороны, в случае явной привязке (explicit binding) клиент должен до обращения к методам вызвать специальную функцию для привязки к объекту. При явной привязке обычно возвращается ука­затель на локально доступный заместитель, как показано в листинге 2.2.


Листинг 2.2.Пример явной привязки с использованием как глобальных, так и локальных переменных


Листинг 2.1. Пример неявной привязки с использованием только глобальных переменных

 

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

Реализация ссылок на объекты

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

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

Однако кодирование сетевого адреса машины сервера в ссылке на объект — вообще говоря, плохая идея. Проблема подобного подхода — в том, что сервер невозможно будет перенести на другую машину, не объявив недействительными все ссылки на объекты, которыми он управлял. Традиционное решение этой проблемы состоит в распространении идеи локальных демонов, поддерживаю­щих таблицы конечных точек, на сервер локализации {location server), следящий за постоянной работой серверов, на которых расположены объекты. Ссылка на объект в результате должна содержать сетевой адрес сервера локализации, а так­же действующий в системе идентификатор сервера. Как мы увидим в главе 4, это решение также имеет множество недостатков, особенно по части масштабируе­мости.

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

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

 

 

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

граммы UDP. При этом на клиенте лежит ответственность за реализацию замес­тителя как минимум для одного протокола, указанного в ссылке на объект.

Мы можем пойти еще дальше, включив в ссылку на объект дескриптор реали­зации {implementation handle), указывающий на полную реализацию заместителя. Эту реализацию клиент может динамически загрузить при привязке к объекту. Например, дескриптор реализации может принимать вид URL-адреса, указываю­щего на файл архива, типа ftp://ftp.clientware.org/proxies/java/proxy-v1.1a.zip. Про­токол привязки в этом случае будет нужен только для указания на то, что данный файл следует динамически загрузить, разархивировать, установить, а впоследст­вии создать экземпляр. Плюс такого подхода состоит в том, что клиент не дол­жен заботиться о том, доступна ли реализация данного протокола. Кроме того, это дает разработчику объекта полную свободу в разработке специфических для объекта заместителей. Однако, как мы увидим в главе 8, чтобы гарантировать клиенту, что он может доверять загруженному откуда-то коду, нам нужно пред­принимать специальные действия по обеспечению защиты.



Поделиться:


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

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