Версия для печати

Поднимаем XML веб-сервис на Пайтоне
1. Python:

В системе должен быть установлен python, версии не ниже 2.3

2. Устанавливаем apache ( httpd-2.2.8 ):

$ ./configure  --prefix=/usr/local/apache2-soap \
--with-mpm=prefork \
--enable-so \
--enable-mods-shared="actions alias asis auth rewrite ssl" \
--disable-userdir \
--disable-cgi \
--disable-include \
--disable-autoindex
$ make
$ make install

Здесь, в общем-то, обычная установка apache. И если у вас уже есть apache, можно использовать его. Здесь я попытался собрать «лёгкий» апач, с минимумом модулей. Использовать можно как apache 1.3, так и apache 2.0 или 2.2

3. Устанавливаем mod_python ( mod_python-3.3.1 )

$ ./configure \
--with-apxs=/usr/local/apache2-soap/bin/apxs \
--without-flex
$ make
$ make install

Обратите внимание, что mod_python 3.3.1 только для apache версии 2.0 и 2.2. Если у вас apache 1.3, используйте mod_python 2.7.11

4. Устанавливаем ZSI ( The Zolera Soap Infrastructure ):

Берём ZSI не ниже версии ZSI-2.1-a1, ZSI-2.0 имеет баги. Установка либо традиционным для python образом:

$ python ./setup.py install

Или можно использовать уже собранный пакет ZSI для python нужной версии, например так:

$ easy_install http://heanet.dl.sourceforge.net/sourceforge/pywebsvcs/ZSI-2.1_a1-py2.4.egg

5. Конфигурируем Apache:

Конфигурируем Apache и виртуальный хост по вкусу.

Если предположить, что скрипты для обработки запросов будут расположены тут: /usr/local/apache2-soap/soapagent, то добавляем Location для обработки веб-сервиса:

<Location /soapagent>
  SetHandler mod_python
  PythonPath "['/usr/local/apache2-soap/soapagent']+sys.path"
  PythonHandler soapagent_handler
# PythonAutoReload On
# PythonDebug On
</Location>

Oпиции PythonAutoReload On и PythonDebug On удобно использовать при отладке, но для продакшин использования лучше выключить.

Если у вас apache 1.3 с mod_python 2.7.11, то конфигурация Location будет немного иной:

<Location /soapagent>
  SetHandler python-program
  PythonPath "['/usr/local/apache2-soap/soapagent']+sys.path"
  PythonHandler soapagent_handler
# PythonAutoReload On
# PythonDebug On
</Location>

6. Конвертируем WSDL в python методы:

При установке ZSI в системе должен появиться скрипт, который умеет конвертировать WSDL файлы в python методы. Это делается так:

$ wsdl2py http://kocmuk.ru/files/2008/05/soapagent.wsdl

Конвертация возможна как с удалённого wsdl, так и с локального:

$ wget http://kocmuk.ru/files/2008/05/soapagent.wsdl
$ wsdl2py ./soapagent.wsdl

В результате получаем три файла: soapagent_client.py, soapagent_server.py, soapagent_types.py. На основе soapagent_client.py можно сделать клиента, но для сервера достаточно soapagent_server.py, soapagent_types.py. Эти два скрипта нужно положить туда же, где, как мы договорились, будут расположены скрипты для обработки запросов, т.е. в /usr/local/apache2-soap/soapagent

Для данного примера WSDL файл можно взять тут:http://kocmuk.ru/files/2008/05/soapagent.wsdl

Обратите внимание, что URL, на котором будет жить веб-сервис указан внутри wsdl. В данном случает он такой: location="http://localhost:8080/soapagent". Потому веб-сервис надо поднимать именно на этом URL или изменить location в wsdl на требуемый. А так же, хорошо бы сам WSDL выложить в общий доступ, что бы клиенты могли его свободно получать и использовать.

7. Скрипты для обработки XML запросов:

Исходя из договорённости выше, выкладываем их в: /usr/local/apache2-soap/soapagent

Набор скриптов:
soapagent_handler.py — это mod_python handler, который выполняет начальную подготовку и начинает диспетчеризацию XML сервисов.

###### soapagent_handler.py ##########

from ZSI import dispatch
from mod_python import apache              

import soapagent_services  as ss

mod = __import__('encodings.utf_8', globals(), locals(), '*')
mod = __import__('encodings.utf_16_be', globals(), locals(), '*')              
def handler(req):
    # Опция "PythonAutoReload On" из конфига mod_python не перегружает вложенные модули.
    # В стадии разработки можно добавить принудительню перезагрузку модуля сервисов при каждом запросе.
    # ВНИМАНИЕ! Это будет происходить при КАЖДОМ запросе! Для продакшин использования это надо выключить!
    #reload(ss)
    dispatch.AsHandler(modules=(ss,), request=req)
    return apache.OK

soapagent_services.py — непосредственно скрипт с реализованными обработчиками.

###### soapagent_services.py ##########
from soapagent_server import *

# svc: SUM
#
def SUM(ps):
    aVal = ps['aVal']
    bVal = ps['bVal']              

#   Здесь мы выполняем какие-то действия
    cVal = aVal + bVal              
#   А здесь мы возвращаем результат
    response = SUMResponse()
    response._result = cVal
    return response

8. Запускаем Apache:

$ /usr/local/apache2-soap/bin/apachectl start

Конфигурация сервера получилась такая:

Server: Apache/2.2.8 (Unix) mod_ssl/2.2.8 OpenSSL/0.9.8d mod_python/3.3.1 Python/2.4.3

9. Для теста можно выполнить клиенский XML запрос:

$ python
>>> from ZSI import ServiceProxy
>>> service = ServiceProxy.ServiceProxy('http://localhost:8080/wsdl/soapagent.wsdl')
>>> service.SUM(aVal=1, bVal=2)
{'result': 3}

Предполагается, что WSDL файл доступен по адресу: http://localhost:8080/wsdl/soapagent.wsdl

В качестве frontend web-сервера можно использовать и сам python. В библиотеке ZSI кроме mod_python диспетчера «AsHandler» есть еще: AsServer, AsCGI, AsJonPy. Так что можно выбрать по вкусу.

Я выбрал apache. Причины таковы:

  • возможность гибко управлять доступом к сервисам (ACL, парольный доступ, SSL и прочее)
  • многопоточность получившейся конструкции
  • проверенный и надёжный web-сервер, который удобен и знаком обслуживающим его администраторам
  • и всё это при достаточно простой схеме установки, настройки и обслуживании ПО
Google Bookmarks Digg Reddit del.icio.us Ma.gnolia Technorati Slashdot Yahoo My Web News2.ru БобрДобр.ru RUmarkz Ваау! Memori.ru rucity.com МоёМесто.ru Mister Wong

По теме:

Комментарии (6) на запись “Building a Web Services in Python”

  1. const пишет:

    В примере Apache использует MPM prefork. Опыт показывает, что даже не очень навороченное питоновское приложение легко может занять 20M памяти. И так на каждый апачевский процесс. Если использовать MPM worker, то память здорово экономится. Но надо учесть, что питоновский интерпретатор сможет обрабатывать два запроса параллельно только тогда, когда один из них занят операцией ввода-вывода (например, ждёт ответа от СУБД). Золотую середину можно поискать в конфигурации типа M worker'ов по N потоков. И в таком случае надо быть осторожным с глобальными объектами: они общие на все потоки в одном worker'е. Либо нужно от них отказаться, либо заворачивать их в threading.local.

  2. kocmuk.ru пишет:

    Всё именно так! И это надо учитывать. Спасибо за комментарий, const.

    Исходя из моего железа и предполагаемой нагрузки на это приложение — MPM prefork мой выбор. Apache в режиме MPM worker и multithreading-safe приложение — отдельный разговор.

  3. Slach пишет:

    а вы случайно не делали SOAP клиентов на Python с использованием WS Security?

  4. kocmuk.ru пишет:

    Привет.

    WS Security, когда безопасность на уровне самих сервисов — к сожалению, не делал. А вот безопасность на уровне транспорта (SSL, https) + Basic-аутентификация или аутентификация по SSL сертификатам — делал. ZSI отлично справляется с этим как клиент, а apache — как сервер. Вот так оно примерно выглядит.

  5. Valerikk пишет:

    Что-то не получается с сервером Апач :(

    Пишет:

    Traceback (most recent call last):

    File "", line 1, in

    File «build/bdist.linux-i686/egg/ZSI/ServiceProxy.py», line 324, in __call__

    File «build/bdist.linux-i686/egg/ZSI/ServiceProxy.py», line 300, in call_closure

    File «build/bdist.linux-i686/egg/ZSI/client.py», line 452, in Receive

    File «build/bdist.linux-i686/egg/ZSI/client.py», line 416, in ReceiveSOAP

    TypeError: Response is «text/html», not «text/xml»

    Где рыть?

  6. kocmuk.ru пишет:

    Я бы помотрел для начала вот это: Response is «text/html», not «text/xml»

    Это значит, что пришёл не XML ответ, а значит что-то не так. Можно включить трейс запросов и ответов через tracefile=sys.stdout. Или через tcpdump посмотреть запросы и ответы. Думаю, что там (в ответе) будет более понятная диагностика.

Оставить комментарий



Anti-spam image