| Средства вызова удаленных процедур |
|
Как правило, причиной создания сценариев для работы с сетью становится необходимость организации взаимодействий между процессами. Часто бывает вполне достаточно ограничиться простыми взаимодействиями, например, с помощью протокола HTTP или сокетов. Однако, иногда возникает необходимость выполнять программный код в разных процессах и даже на разных компьютерах, как если бы это был один и тот же процесс. Если бы у вас имелась возможность выполнять программный код удаленно, в некотором другом процессе, запущенном из программы на языке Python, то вы, скорее всего, хотели бы, чтобы возвращаемые значения таких удаленных вызовов были объектами языка Python, работать с которыми намного проще, чем с фрагментами текста, которые необходимо анализировать вручную. Так вот, существует несколько инструментов, позволяющих организовать вызов удаленных процедур (Remote Procedure Call, RPC). XML-RPC Технология XML-RPC, позволяющая организовать вызов удаленных процедур, основана на обмене специально сформированными документами XML между двумя процессами. Однако пусть вас не беспокоит часть XML в названии - вам, скорее всего, даже не придется вникать в формат документов, которыми будут обмениваться процессы. Единственное, что вам действительно необходимо знать, чтобы использовать технологию XML-RPC - это то, что в стандартной библиотеке языка Python имеются реализации как клиентской, так и серверной частей этой технологии. К тому же, вам полезно будет узнать, что реализации XML-RPC имеются в большинстве языков программирования и что эта технология очень проста в использовании. В примере 5.6 приводится реализация простого сервера XML-RPC. Пример 5.6. Простой сервер XML-RPC
Этот сценарий создает новый объект SimpleXMLRPCServer и связывает его с портом 8765 и с петлевым интерфейсом, имеющим IP-адрес 127.0.0.1, что делает его доступным только для процессов, выполняющихся на данном компьютере. Затем сценарий регистрирует функции ls() и ls_ boom(), которые определены тут же, в сценарии. Назначение функции cb() мы объясним чуть погодя. Функция ls() с помощью os.listdir() получает содержимое указанного каталога и возвращает его в виде списка. Функция ls() маскирует любые исключения OSError, которые только могут возникнуть. Функция ls_boom() не выполняет обработку исключений и возвращает их клиенту XML-RPC. После этого сценарий входит в бесконечный цикл serve_forever(), в котором он ожидает поступления запросов от клиентов и обрабатывает их. Ниже приводится пример взаимодействия с этим сервером в оболочке IPython:
Прежде всего мы создали объект ServeгРгоху, указав ему адрес сервера XML-RPC. Затем мы вызвали функцию х. ls('.'), чтобы получить содержимое текущего рабочего каталога. Сервер был запущен из каталога, содержащего программный код примеров, поэтому список включает файлы примеров. Самое интересное, что на стороне клиента функция х. ls('.') возвращает список языка Python. Независимо от языка реализации сервера - Java, Perl, Ruby или С# - можно рассчитывать на получение подобного результата. На языке реализации сервера может быть получен перечень файлов в каталоге, создан список, массив или коллекция имен файлов; после этого программный код сервера XML-RPC может преобразовать этот список или массив в формат XML и передать его обратно клиенту. Мы также попробовали вызвать функцию ls_boom(). Благодаря тому, что в функции ls_boom() не предусматривается обработка исключений, в отличие от ls(), мы смогли увидеть, как исключение передается от сервера клиенту. Более того, на стороне клиента мы увидели даже диагностическую информацию. Возможности функциональной совместимости, которыми обладает технология XML-RPC, безусловно интересны. Но гораздо более интересен тот факт, что существует возможность написать некоторый программный код, запустить его на произвольном числе машин и затем вызывать этот код удаленно в случае необходимости. Однако в технологии XML-RPC имеются свои ограничения. Эти ограничения могут представлять определенную проблему, или сама технология может не соответствовать нуждам и чаяниям разработчика. Например, когда удаленному программному коду передается нестандартный объект на языке Python, библиотека XML-RPC преобразует этот объект в словарь, переводит его в формат XML и отправляет удаленной стороне. Безусловно, вы сможете обработать эту ситуацию, но для этого потребуется написать программный код, который будет извлекать данные из XML-версии словаря, чтобы превратить его обратно в оригинальный объект. Так почему бы не использовать объекты непосредственно на сервере RPC, чтобы избежать таких сложностей с преобразованиями? Это нельзя сделать с помощью XML-RPC, но существуют другие возможности. Руrо Руrо - это платформа, которая лишена некоторых недостатков, свойственных XML-RPC. Название Руrо происходит от Python Remote Objects (удаленные объекты Python). Она позволяет реализовать те же самые действия, которые позволяет XML-RPC, но вместо того, чтобы преобразовывать объекты в форму словаря, она обеспечивает возможность передачи информации о типе вместе с самим объектом. Если вы действительно захотите воспользоваться платформой Руrо, вам придется установить ее отдельно. Она не поставляется вместе с Python. Кроме того, вы должны понимать, что Pyrо работает только со сценариями на языке Python, тогда как технология XML-RPC в состоянии обеспечить взаимодействие между сценариями на языке Python и программами, написанными на других языках. В примере 5.7 приводится реализация той же самой функции ls(), что и в примере, использующем технологию XML-RPC.
Пример 5.7. Простой сервер Руго Пример на базе Pyro похож на пример XML-RPC. Сначала мы создали класс PSAExample с методами ls(), ls_boom() и cb(). Затем из глубин Pyro был извлечен демон. После этого мы связали объект PSAExample с демоном. Наконец, мы запустили демон для обслуживания запросов. Ниже приводится сеанс взаимодействия с сервером Pyro в оболочке IPython:
Отлично. Мы получили те же результаты, что и в примере XML-RPC. Именно этого мы и ожидали. Но что произойдет, если попробовать передать нестандартный объект? Попробуем определить новый класс, создать из него объект и передать его функции cb() в реализации на основе XML-RPC и методу cb() в реализации на основе Pyro. В примере 5.8 приводится фрагмент программного кода, который будет выполняться. Пример 5.8. Различия между XML-RPC и Pyro
Обращение к функции cb() в обеих реализациях, XML-RPC и Pyro, должно привести к вызову метода cb() переданного объекта. И в обоих случаях этот метод должен вернуть строку PSA callback. Ниже показано, что произошло, когда мы запустили этот сценарий:
Реализация на основе Pyro работает, но реализация на основе XML-RPC потерпела неудачу и оставила нас наедине с кучей диагностической информации. Последняя строка в этом блоке информации сообщает, что в объекте diet отсутствует атрибут cb. Эта строка обретет смысл, если взглянуть на вывод, полученный от сервера XML-RPC. Вспомните, что в функции cb() имеется пара инструкций print, которые выводят дополнительную информацию о том, что происходит. Ниже приводится вывод сервера XML-RPC:
После преобразования в словарь объекта, который был создан в клиенте, реализованном на базе XML-RPC, атрибут some_attribute превратился в ключ словаря. Атрибут сохранился при передаче объекта на сервер, а метод cb() был утрачен. Ниже приводится вывод сервера Pyro:
Обратите внимание, что класс объекта - PSACB, т.е. тот, который и был создан. На стороне сервера на основе Pyro мы должны включить программный код, импортирующий тот же программный код, который используется клиентом. Это означает, что сервер Pyro вынужден импортировать программный код клиента. Для сериализации объектов платформа Pyro использует стандартный модуль pickle, что объясняет, почему Pyro обладает схожим поведением. Подводя итоги, можно сказать: если вам необходимо простое решение RPC, не имеющее внешних зависимостей, если вам не мешают имеющиеся ограничения XML-RPC, и вам важна поддержка функциональной совместимости с другими языками программирования, то, скорее всего, хорошим выбором будет XML-RPC. С дPyroй стороны, если ограничения XML-RPC слишком тесны для вас, вы не возражаете против установки дополнительных библиотек и предполагаете ограничиться только языком Python, то наилучшим вариантом для вас будет Pyro.
Related Articles
Set as favorite
Bookmark
Email This
Hits: 298 Комментарии (0)RSS feed CommentsНаписать комментарий |