Logo Море(!) аналитической информации!
IT-консалтинг Software Engineering Программирование СУБД Безопасность Internet Сети Операционные системы Hardware
2004 г.

Веб-сервисы в гетерогенных средах

Олег Ремизов, "Комиздат"

Данная статья посвящена рассмотрению некоторых практических аспектов технологии web-services на платформах DOT.NET и Java. Такой метод обмена информацией, хотя не является наиболее оптимальным, тем не менее, имеет много преимуществ по сравнению с другими современными технологиями создания распределенных приложений.

Благодаря поддержке таких гигантов рынка как Microsoft, IBM, Sun эта технология быстро набирает вес и становится стандартом де-факто для создания распределенных приложений. Использование данной технологии в последнее время является наиболее актуальным конкурентным преимуществом при продвижении на рынок нового поколения распределенных приложений.

Определение

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

Протоколы уровня представления — это XML-RPC и SOAP. Они определяют, каким образом в строке представлены структуры данных.

Идея представить структуры данных в виде строки возникла задолго до появления протоколов представления XML-RPC и SOAP. И именно существование великого множества доморощенных протоколов послужило толчком для создания этих стандартов. Оба протокола построены на основе XML.

Достоинства

Первое достоинство такого рода служб (которое, собственно, и является определяющим) — это простота создания. Что можно объяснить, прежде всего, существованием всякого рода кодогенераторов и  визардов.

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

Если нам необходимо оперативно изменить какую-то цифру  в табличном представлении, мы должны перегрузить всю HTML-страницу или фрейм; браузер, в свою очередь, должен потратить некоторое время на рендеринг нового представления. Примером такого рода приложений могут служить всякого рода форексподобные сайты и веб-чаты. Если же принять во внимание разницу в диалектах DHTML-скриптов и в поведении фреймов для разных браузеров, то картина и подавно становится нерадостной.

Несколько спасало положение то, что в местах, где информация должна передаваться достаточно оперативно, разработчики использовали Java Applets (в этом случае в качестве протокола можно также использовать веб-сервисы).  Но в последнее время, в результате выяснения отношений с Sun, Microsoft удалила Java-машину из последних версий своих браузеров,  что привело к некоторым неудобствам на стороне пользователя, который теперь вынужден загружать Java-машину отдельно. То же самое касается Flash- и SVG-технологий.

Такой букет проблем подтолкнул разработчиков к выводу о том, что необходимо использовать решения в виде настольных и комбинированных приложений. Поскольку основным транспортным протоколом в технологии веб-сервисов является HTTP, то и все проблемы, связанные с дополнительными настройками брандмауэров и роутеров отпадают автоматически. Приложение может без проблем работать не только в Intranet-, но и в Internet-сетях. Кроме того, эта технология не привязана к какой-либо одной платформе, что открывает возможность создания распределенных приложений в гетерогенных средах. Отличная интеграция этой технологии с DOT.NET является, пожалуй, единственной известной уступкой Microsoft мировому сообществу разработчиков за последнее время.

Недостатки

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

Прежде всего, если вы создаете приложение реального времени, то вам, вероятно, придется отказаться от применения этой технологии в пользу сокетов, DCOM, Remouting, RMI  или других протоколов-оберток для создания распределенных приложений. Это объясняется достаточно большим временем отклика и некоторой избыточностью пересылаемой информации, что при больших нагрузках может привести к перегруженности сетевого трафика. Если же у вас нет критических требований к времени отклика (а таких приложений в реальном мире где то 90%), то смело можете брать эту технологию на вооружение.

Еще один недостаток этой технологии заключается в отсутствии возможности асинхронной связи. Программистам, работавшим с DCOM, хорошо знакома такая сущность, как события,— в случае с веб-сервисами такая возможность отсутствует.

Протоколы уровня представления

Протоколами уровня представления информации (wire protocols) сейчас являются два стандарта — SOAP и XML-RPC.

SOAP является основным стандартом, принятым многими фирмами разработчиками. В том числе и Microsoft. Собственно SOAP родился в результате сотрудничества между тремя фирмами UserLand, DevelopMentor и, конечно же, Microsoft. Позже протокол был переработан и дополнен W3C.

Протокол XML-RPC менее известен, однако используется не менее широко. Его реализации тоже существуют для большинства сред и языков. Основное достоинство этого протокола — меньшая избыточность и, как следствие, легковесность. Естественно, за все надо платить — и в результате XML-RPC не сможет похвастаться той гибкостью, какую предоставляет SOAP. Но при этом, у него есть серьезное одно достоинство: этот протокол более безопасен. В отличие от SOAP, не предусмотрена возможность просмотра экспонируемых методов посредством discovery- и description-сервисов.

Существенный недостаток этого протокола — отсутствие интеграции в средах разработки. Как следствие: вам придется самостоятельно выбрать реализацию библиотеки и загрузить ее с сайта разработчика. Исчерпывающую информацию по этому протоколу вы можете найти на www.xml-rpc.com.

Фактически, прототипом для  XML-RPC явился один из черновиков протокола SOAP. Поэтому, если посмотреть на фрагменты строк, взятых из двух протоколов, становится ясно, что у них достаточно много общего. В текущем состоянии SOAP поддерживает XML-схемы, перечисления, странные гибриды структур и массивов, а также определяемые пользователем типы — в то время как у XML-RPC более скромный набор. В то же время, некоторые аспекты SOAP не документированы и поэтому оставлены на усмотрение разработчика. Поэтому фактически окончательным стандартом SOAP можно считать его реализацию предоставленную Microsoft.

Вот как выглядит строка-запрос в XML-RPC-протоколе:

Этот фрагмент дает возможность оценить, насколько проще и нагляднее выглядит XML-RPC по сравнению с SOAP. Именно этим обусловлено меньшее время отклика в реализациях протокола XML-RPC.

Справедливости ради стоит отметить, что Microsoft в качестве альтернативы предлагает использовать классические HTTP-GET и HTTP-POST методы передачи параметров, результат при этом возвращается в виде очень простой XML-строки. Время отклика в этом случае будет еще меньшим, чем у XML-RPC. Но эти альтернативные методы не могут работать со сложными типами данных, так что рассматривать их в качестве кандидатов для использования в реальных приложениях не имеет смысла.

Возможности интеграции со средами разработки

В качестве демонстрации того, насколько просто создать такое приложение с использованием современных средств разработки, приведем пример, в котором создадим веб-сервис в среде DOT.NET и Java-клиент, вызывающий этот веб-сервис (для демонстрации гетерогенных возможностей технологии).

На практике подобная задача встречается довольно часто. Так что рассмотрим ситуацию из реальной жизни. Система учета супермаркета использовала в качестве базы данных MSSQL-сервер. Таким образом, серверная сторона была привязана к Win2k. Дабы сэкономить на лицензиях Win2k, для торговых терминалов решено было создать рабочее место оператора с использованием UNIX-машин. Для реализации проекта был создан свой протокол с использованием Berkley Sockets. Его создание и отладка отняла значительную часть то общего времени реализации проекта, которое в результате составило примерно полгода! Если бы разработчики использовали веб-сервисы, время разработки значительно сократилось бы.

Приступим непосредственно к созданию нашего примера. В начале создадим проект сервиса. Для этой цели я использовал VS7.1. Запускаем его и создаем новый проект C# на основе шаблона Web Service. При этом в IIS будет создан виртуальный каталог (на диске в соответствие ему ставится реальный каталог), в котором будут размещены файлы проекта.

Рис. 1. Создаем Web Service в среде разработки Visual Studio 7.1

Интерес для нас представляют три файла:

  • *.asmx — файл в формате XML, точнее WSDL (это язык, созданный на базе XML; можно также встретить определение, что WSDL — это XML-схема, оно тоже верно) специально для описания методов, экспонированных сервисом. IIS на лету преобразует WSDL в HTML-представление для отображения в браузере пользователя. Этот файл представляет информацию для description service. Для каждого сервиса (службы) существует свой файл описания;
  • *.disco — файл в формате XML, предназначенный для просмотра (listing) всех существующих веб-служб по указанному адресу: discovery service. Посредством этих двух файлов и IIS пользователь, вооруженный браузером, может найти исчерпывающую информацию об инсталлированных веб-сервисах;
  • *.asmx.cs — файл, ответственный за реализацию методов сервиса.

Переименуйте файл сервиса и класс службы, для того чтобы они несли определенную смысловую нагрузку. Для тестового приложения я выбрал имя файла AccountState.asmx, а для класса службы — AccountState, поскольку наше тестовое приложение будет отображать состояние некоего счета в банке.

Существует распространенное заблуждение, что веб-сервис представляет сущность без состояния. Это не совсем так, мы вполне можем хранить промежуточные данные в статических переменных класса или в переменных приложения. Эти данные будут оставаться живыми вплоть до перегрузки веб-сервера. Верно то, что при каждом новом запросе создается новый экземпляр класса веб-службы. После закрытия клиентом соединения с сервером экземпляр класса будет разрушен — при этом все нестатические члены класса должны быть сохранены в базу данных или посредством serializing. Точно так же они должны быть загружены при новом запросе. Если мы хотим оптимизировать работу сервера, избежав многочисленных обращений к диску или базе данных, оптимальным решением будет сохранение результатов в статической коллекции объектов и сохранение той в хранилище данных через некоторые промежутки времени. Из кода, сгенерированного wizard, несложно догадаться, что место для инициализации — это конструктор класса. Когда нам надо освободить ресурсы, то делать мы следует в методе Dispose().

Код методов нашего веб-сервиса выглядит так:

 [WebMethod]
 public string GetBankName()
 {
   return "Baby Bank";
 }
 [WebMethod]
 public void Deposit(int ammount)
 {
   state += ammount;
 }
 [WebMethod]
 public int GetState()
 {
   return state;
 }

 [WebMethod]
 public int Withdraw(int ammount)
 {
   state -= ammount;
   if (state < 0)
   {
     state = 0;
     return state;
   }
   else
   {
     return ammount;
   }
 }

Не забудьте определить переменную state как static (полный код этого примера вы сможете найти на КП-диске).

При вызове сервиса в Internet Explorer мы сможем прочитать пару "запрос-ответ" в формате SOAP. Для примера приведем текст запроса и ответа для функции int GetState() будет выглядеть следующим образом:

Если сравнить формат SOAP с ранее приведенным фрагментом в формате XML-RPC, сразу видно, что при наличии большого количества сложных объектов размер строки XML-RPC будет гораздо меньшим.

Возможность тестировать методы прямо из Internet Explorer делает разработку сервисов еще более простым занятием. Внизу приведены рисунки, отображающие некоторые экраны в процессе тестирования.

Рис. 2. Мы можем просмотреть все методы web службы прямо в Internet Explorer

Рис. 3. Есть возможность вызвать любой метод web службы

Рис. 4. Результат вызова службы в Internet Explorer представлен виде XML

Протестировав наш сервис в Internet Explorer, напишем небольшой консольный клиент, проверяющий его работу.

Код простейшего клиента будет выглядеть так:

[STAThread]
static voidMain(string[] args)
{
  try
  {
    AccountClient.AccountState.AccountState ac
      = new AccountClient.AccountState.AccountState();
    Console.WriteLine("Try to invoke service from URL : " +  ac.Url);
    Console.WriteLine("Bank name : " + ac.GetBankName());
    Console.WriteLine("Accaunt initial state : " + ac.GetState());
    ac.Deposit(10);
    ac.Withdraw(5);
    Console.WriteLine("After Operations accaunt state : " +     ac.GetState());
    ac.Dispose();
    Console.WriteLine("Press key 'Enter' to complete program execution");
    Console.ReadLine();
  }
  catch (Exception ex)
  {
    Console.WriteLine(ex.Message);
  }
}

При этом необходимо создать в проекте веб-ссылку, для того чтобы Visual Studio мог сгенерировать промежуточную proxy-сборку. Таким образом, среда разработки берет всю черновую работу на себя, нам остается только создать экземпляр класса и вызвать его методы.

Чтобы создать веб-ссылку, щелкните по контекстному меню на дереве проекта нашего клиента и выберите пункт add web reference. Появится интуитивный дружественный wizard. На рисунке показано его финальное диалоговое окно, где название ссылки изменено с localhost на AccountState.

Рис. 5. Окно визарда, создающего proxy-сборку

Если заглянуть внутрь папки проекта [имя проекта]\Web References, мы обнаружим исходный код нашего proxy-класса. Благодаря применению  атрибутов он достаточно компактен. Стартуйте клиент на выполнение и убедитесь, что все работает.

Рис. 6. Клиент DOT.NET, опрашивающий веб-службу

Если вы запустите его несколько раз, то обнаружите, что данные, хранящиеся в статической переменной state, не будут уничтожены. Но если пересобрать проект, что приведет к перезагрузке приложения в IIS, эти данные все же исчезнут. Поэтому вам в любом случае необходимо позаботиться об их сохранении. Глобальные данные можно сохранять при помощи класса Application.

Первая часть проекта завершена, создадим теперь аналогичный консольный проект Java при помощи среды разработки JBuilder X. Создайте проект, после чего добавьте объект Web Services Designer из меню New. На следующей вкладке визарда установите параметры, как это показано на рисунке 7.

Рис. 7. Настраиваем объект Web Services Designer в среде разработки JBuilder X

После этого в дереве проекта выберите  Web Services Designer > Import WSDL > From URL. Из контекстного меню выберите пункт Add. Будет добавлен новый сервис. Вставьте URL нашего сервиса с постфиксом ?WSDL. Все остальное визард сделает сам — по удобству и интуитивности он ничем не уступает своему аналогу из Visual Studio.

На рисунке ниже показано окно визарда с URL.

Рис. 8. Окно Web Services Designer с импортированным объектом веб-сервиса в среде разработки JBuilder X

Все установки на вкладках оставьте по умолчанию (я изменил только имя пакета для proxy-классов и имя самого сервиса). Соберите проект, в пакете со введенным вами именем возникнут сгенерированные классы. Добавьте новый класс с методом main() и вставьте туда следующий код:

 try
  {
   // here we will invoke our soup method :
   long time1 = System.currentTimeMillis();
   AccountStateSoapStub proxy = (org.tempuri.AccountStateSoapStub)
       new org.tempuri.AccountStateLocator().getAccountStateSoap(new URL("
http://localhost /Account/AccountState.asmx"));
   if (proxy != null)
   {
     proxy.setTimeout(60000);
     // operations:

     proxy.getBankName();
     System.out.println("Bank name : " + proxy.getBankName());
     System.out.println("Accaunt initial state : " + proxy.getState());
     proxy.deposit(10);
     proxy.withdraw(5);
     System.out.println("After Operations accaunt state : " +  proxy.getState());
     System.out.println("Name : " + proxy.getName());
     proxy.setName("Oleg");
     System.out.println("Name : " + proxy.getName());
     long time2 = System.currentTimeMillis();
     long delta = time2 - time1;
     System.out.println("Request take : " + Long.toString(delta) + " millisecond");
     System.out.println("Press key 'Enter' to complete program execution");
     System.in.read();
   }
 }
 catch (Exception ex)
 {
   ex.printStackTrace();
 }

Следует отметить, что JBuilder использует Apache Axis — самый известный пакет для работы с SOAP. Существуют другие реализации этого протокола — как платные, так и free. Не исключено, они более оптимальны — но если вы остановитесь на одной из них, то почти наверняка потеряете интеграцию с вашей средой разработки. А это означает снижение производительности вашего труда.

Быстродействие

Для тестирования быстродействия вызова веб-сервиса был включен код, отвечающий за вычисление времени, потраченного на создание proxy-сборки, на подключение к серверу и время выполнения; кроме того, для того чтобы получить более корректные результаты в ходе тестирования при повторных вызовах, был добавлен цикл while(). Этот подход позволяет исключить погрешность, обусловленную первоначальной загрузкой и инициализацией библиотек. Такой же код был включен в собранный ранее клиент C#.

Для клиента, реализованного с использованием C#, время, потраченное на вызовы, составило чуть более 2010 мс. В то время как для клиента на Java — около 2460 мс. Я не нашел логичного объяснения столь большому времени отклика, на некоторых машинах это время было меньшим на порядок и составляло около 250 мс. Но на большинстве машин, где проводилось тестирование, порядок цифр, тем не менее, оставался прежним — 2000 мс. Java-клиент, запущенный под управлением RH9 Linux, показал намного лучший результат. Время отклика в этом случае составило примерно 300 мс.

Данные приведены для Athlon 2000+ c 400 Мб RAM. Внизу представлен рисунок, демонстрирующий работу Java-клиента на Linux-системе.

Рис. 9. Результаты работы Java-клиента, запущенного под управлением RH9 Linux

Даже 0,25 с может быть многовато для некоторых критичных приложений реального времени. 2460 мс — эта величина может оказаться неприемлемой даже для очень нетребовательных приложений. На КП-диске также приведен пример простого XML-RPC-сервера и клиента с той же функциональностью, что и в первом примере. В отличие от первого примера, эта связка показала примерно одинаковые результаты — независимо от места тестирования. Время отклика в этом случае составило около 110 мс для Windows 2000, что более чем вдвое превышает показатели даже для наиболее оптимального для SOAP-сервиса случая.

Выводы

В ходе тестирования были обнаружены странные флуктуации производительности веб-сервисов, использующих SOAP. Если быстродействие приложения, использующего веб-сервисы, вас не устраивает, то возможным вариантом его оптимизации может стать отказ от протокола SOAP в пользу более легковесного XML-RPC.

На разных задачах DOT.NET-машина перегоняет JVM в полтора-два раза. Именно такого результата следовало ожидать в этом случае. В этом тесте не было замечено значительной разницы в производительности на стороне клиента.

Если принять во внимание тот факт, что объемы передаваемых данных в наших примерах просто смехотворны, а эксперимент проводился на одной машине (без реального сетевого взаимодействия), следует еще раз задуматься о целесообразности использования веб-сервисов вообще для приложений с повышенными требованиями к быстродействию (особенно в гетерогенных средах). Для сравнения: та же последовательность вызовов посредством RMI занимает всего 20…30 мс. К счастью, большинство реальных приложений таковыми не являются.

Новости мира IT:

Архив новостей

Последние комментарии:

Loading

IT-консалтинг Software Engineering Программирование СУБД Безопасность Internet Сети Операционные системы Hardware

Информация для рекламодателей PR-акции, размещение рекламы — adv@citforum.ru,
тел. +7 985 1945361
Пресс-релизы — pr@citforum.ru
Обратная связь
Информация для авторов
Rambler's Top100 TopList liveinternet.ru: показано число просмотров за 24 часа, посетителей за 24 часа и за сегодня This Web server launched on February 24, 1997
Copyright © 1997-2000 CIT, © 2001-2015 CIT Forum
Внимание! Любой из материалов, опубликованных на этом сервере, не может быть воспроизведен в какой бы то ни было форме и какими бы то ни было средствами без письменного разрешения владельцев авторских прав. Подробнее...