- 17 октября 2001 г.
"Мыльный" SOAP
Вторая статья знакомит читателя с протоколом SOAP, с помощью которого
строятся Web-службы. В ней объясняется, зачем нужен этот протокол, обсуждаются
некоторые аспекты его применения.
В предыдущей статье мы дали определение Web-службе. Теперь самое время перейти к изучению одного из основных протоколов, с помощью которых строятся службы, а именно протокола SOAP (Simple Object Access Protocol). Первоначальная спецификация SOAP версии 0.9, было опубликована в сентябре 1999 года, после чего, претерпев две редакции, вышла в свет в декабре 1999 года как версия 1.1. SOAP 1.1 фактически стал стандартом, он признан большинством поставщиков программного обеспечения и широко используется в реализациях клиент- сервер. Спецификация определяет ряд соглашений по обмену XML-сообщениями, в том числе правила по кодированию структур данных, алгоритм расширяемости, присоединение к HTTP-протоколу, требования к вызовам типа RPC (Remote Procedure Call, Удаленный вызов процедуры). Международный консорциум W3C (World Wide Web Consortium) намерен добиться того, чтобы SOAP был придан статус Рекомендации W3C - этим вопросов занимается Рабочая группа протокола XML (XML Protocol Working Group). В настоящий момент группа работает над SOAP 1.2, используя в качестве отправной точки SOAP 1.1; в спецификацию вносятся некоторые изменения и уточнения.
Прежде чем продолжить разговор о SOAP, давайте зададимся простым вопросом: а зачем нам вообще нужен протокол, например, SOAP? Другими словами, что нам даст SOAP? Если две стороны используют Web-службу для обмена информацией, записанной в виде XML, что может помешать им договориться о словаре и структуре XML и определить свой собственный протокол? Тогда каждая пара участников обмена неизбежно создаст свой собственный, специфический протокол. Таким образом, если n - это число участников обмена, то потенциально число протоколов может достичь n-1 включительно. Хотя реализация одного протокола не представляет особых трудностей, при увеличении n, например при n > 6, бремя внедрения становится весьма ощутимым. Наличие одного стандартного протокола приносит единообразие в определенных аспектах коммуникации и, следовательно, существенно снижает сложности реализации. В результате, появляется возможность устанавливать средства обработки в другие приложения, например, серверные продукты, клиентские продукты, операционные системы. В этом случае отдел внедрения Web-службы (или же клиенты этой службы) сможет сконцентрироваться на специфических задачах данной службы, а не на общих вопросах, характерных для всех Web-служб.
Распознавание сообщения
SOAP определяет внешний элемент для всех SOAP-сообщений, которыми
обмениваются Web-служба и ее клиент. Подобно тому, как элемент
stylesheet в пространстве имен XSLT сообщает XSLT-процессору, что в
действительности это XML - преобразование, элемент Envelope в SOAP
пространстве имен показывает SOAP-процессору, что это XML - SOAP-сообщение.
Тогда процессор сможет искать индивидуальную часть сообщения: обязательный
элемент Body, который содержит действительный запрос, и
факультативный элемент Header, который содержит элементы расширения.
Ниже показан скелет SOAP-сообщения:
soap:Envelope xmlns:soap=
'http://www.w3.org/2001/10/soap-envelope'>
<soap:Header>
<-- Headers go here -->
</soap:Header>
<soap:Body>
<-- Request goes here -->
</soap:Body>
</soap:Envelope>
Заголовки (Header) и расширяемость
Элемент Header обеспечивает в SOAP механизм расширяемости. Этот
элемент может содержать любое число квалифицированных дочерних элементов
пространства имен. Каждый из этих элементов - некая разновидность расширения в
базовом SOAP-протоколе. Скажем, один элемент может содержать данные, связанные
с управлением диалогом или сессией между клиентом и сервером. Другой может
содержать информацию об аутентификации или даже сведения о текущей транзакции.
С другой стороны он может содержать и локальную информацию. Каково бы ни было
их содержание или семантика, каждый элемент header некоторым образом
модифицирует SOAP-протокол, обеспечивая дополнительный контекст для обработки
тела сообщения. Для клиента имеет огромное значение, что сервер принимает на
обработку некоторые расширения; классический пример - аутентификация. Другие
расширения, такие как локальная информация, могут быть менее критичными. Каждый
заголовочный элемент (header) может быть снабжен комментариями с
помощью атрибута mustUnderstand. Если этот атрибут имеет значение
true или 1, то заголовок считается обязательным. Если
получатель сообщения не распознает заголовок или не понимает его, он должен
генерировать SOAP-сообщение об ошибке. Заголовки без атрибута
mustUnderstand (или же если mustUnderstand имеет значение
false или 0) считаются факультативными. Получателю таких
заголовков не требуется их обрабатывать. Ниже приведен пример SOAP-сообщения,
содержащий одно обязательное и одно факультативное расширение:
<soap:Envelope xmlns:soap=
'http://www.w3.org/2001/10/soap-envelope'>
<soap:Header>
<h:Log xmlns:h=
'http://example.org/cvs/logging'>
<trace>4</trace>
</h:Log>
<h:PServer xmlns:h=
'http://example.org/cvs/pserver'
soap:mustUnderstand='true' >
<username>anoncvs@example.org</username>
<password>anoncvs</password>
</h:PServer>
</soap:Header>
<soap:Body>
<m:Checkout xmlns:m=
'http://example.org/cvs'>
<source>/xml/soap/webservices/cvs</source>
<revision>1.1</revision>
<destination>/etc/usr/marting/source/xml
</destination>
</m:Checkout>
</soap:Body>
</soap:Envelope>
Модель расширяемости обеспечивает стандартное размещение расширений протокола, а также стандартный механизм обозначения расширений как обязательных. Повторимся: этот подход упрощает внедрение приложений или кода, используемого для обработки расширений на уровне инфраструктуры.
Заголовки и модель обработки SOAP
При простом обмене "клиент-сервер" используется обыкновенная модель обработки сообщений, не содержащих заголовки. Обычно сервер распознает содержание элемента Body как запрос на предоставление некой услуги. Сервер выполняет эту работу и может факультативно отправить ответ обратно. Если же он не распознает содержание элемента Body, или в процессе обработки возникают какие-либо иные ошибки, сервер генерирует SOAP-сообщение об ошибке, в котором описан характер погрешности.
Заголовочные элементы в некоторой степени усложняют эту модель обработки, что создало почву для долгих споров о многих аспектах обработки заголовков. Например, значение атрибута mustUnderstand (букв. должен понимать). Что значит "понимать" отдельно взятый атрибут? И если данный процессор понимает заголовок, требуется ли обрабатывать его? В результате был предложен дополнительный атрибут mustProcess. При его задании получатель должен был бы не только понимать заголовок, но и обрабатывать его. Подобным образом можно было бы ужесточить определение атрибута mustUnderstand (что и предлагается в черновом варианте SOAP 2.1), потребовав, чтобы обязательные заголовки обрабатывались в соответствии со спецификацией для заголовка, или чтобы SOAP-процессор генерировал сообщение об ошибке. Помимо этого, процессор для SOAP 1.2, прежде чем приступить к обработке любой части сообщения, должен гарантировать, что он понимает все обязательные заголовки в данном сообщении, включая содержание элемента Body. В результате, модель обработки несколько проясняется, однако ситуация усложняется при реализации потоков, которые, возможно, будут пытаться обработать заголовки всякий раз, как только с ними столкнутся. Если заголовков обрабатываются подобным образом, должна быть гарантия того, что будет возможен "откат" результатов обработки заголовков, если затем обязательный заголовок не понимается SOAP-процессором.
Еще один спорный момент - порядок, в котором будут обрабатываться заголовки. Спецификация SOAP не определяет порядок обработки заголовков или тела. Порядок определяется исключительно SOAP-процессором. Очевидный подход - обрабатывать заголовки в лексическом порядке, однако возможны случаи, когда этот порядок окажется неприемлемым, возможно из-за того, что получатель сообщения не осведомлен о взаимодействии между определенными заголовками в этом сообщении. Не составляет труда определить расширение заголовка, которое модифицирует семантику SOAP для указания того, что заголовки должны обрабатываться в определенном порядке. Обозначение такого заголовка как обязательного гарантировало бы, что SOAP-процессор, получив сообщение, содержащее этот заголовок, прежде чем начать обработку других заголовков в сообщении, знал бы о требовании порядка.
Именно эта возможность модифицировать семантику стандартного протокола делает модель расширяемости, основанную на заголовках, впечатляющей и одновременно открытой к критике. Возможность определить обязательные заголовки разрешает распределить богатую функциональность, но в то же время чревата нарушением базового протокола. Спецификация SOAP позволяет заголовкам изменять семантику своих родительских или одноранговых элементов. Например, можно определить обязательный заголовок, который отключит обработку других обязательных заголовков. Заказчикам Web-служб необходимо иметь информацию и о заголовках, которые ожидаются другими участниками обмена, и о семантике этих заголовков. Небрежность в этом вопросе может привести к тому, что клиенты будут получать семантику, которая им на самом деле не нужна.
В настоящий момент описано всего несколько заголовков, и не один из них не является стандартным. Со временем различные участники этого сектора экономики дадут свое определение. Некоторые заголовки станут стандартом и будут опираться на многочисленные реализации, другие исчезнут в небытие. Важно, что стандартные заголовки хорошо определены и не нарушают работу базового протокола. Стоит также заметить, что некоторые службы, например, Biztalk Server, используют фирменные заголовки. И хотя, строго говоря, эти Web-службы подчиняются спецификации SOAP, они не могут взаимодействовать с клиентами (или другими службами), которые не понимают эти нестандартные заголовки. Остается посоветовать как разработчикам, которые планируют стать клиентами Web-служб, равно как всем, кто будет внедрять эти службы, хорошенько подумать о том, какие заголовки, если они, конечно, их заинтересуют, они готовы использовать.
Автор: Мартин Гуджин (Martin Gudgin), Тимоти Эуолд (Timothy Ewald)