четверг, 19 декабря 2013 г.

SOAP vs RESTful

Поучаствовал в бурных дебатах с коллегами на тему отличий SOAP- и REST-подходов. Вопрос довольно общий, возникает часто, поэтому я решил поделиться своим мнением в блоге.

Обычно при сравнении SOAP- и RESTful-сервисов заводят разговор о том, что мол "ну SOAP же тяжелый протокол, а REST-легкий, это всем известно". Но что тяжелого в SOAP-запросе? Пустой SOAP-запрос с заголовком выглядит следующим образом:


<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
   <soapenv:Header/>
   <soapenv:Body>
   </soapenv:Body>
</soapenv:Envelope>

Данный запрос занимает всего 158 байт. Говорить о том, что что-то тяжелое только потому что оно на 158 байт длиннее чего-то "легкого" несерьезно. Естественно, что различия между данными подходами гораздо глубже.

понедельник, 9 декабря 2013 г.

Команда программистов в Челябинске ищет заказчика.

Коллеги, если у вас есть интересный проект, но вы испытываете затруднение с поиском команды для его реализации, то предлагаю вам обратиться к этим людям. Удаленная работа приветствуется.

Состав команды:
- два разработчика фронтэнд;
- один разработчик Windows-приложений, классификаторов, алгоритмов анализа данных;
- руководитель команды, очень опытный и грамотный специалист, за него могу поручиться лично.

Парни имеют опыт работы со следующими технологиями:

- ASP.NET MVC;
- DevExpres;
- node.js;
- noSQL СУБД mongodb;
- Amazon Web Services.

Естественно, все обучены ООП и знают, что такое SOLID, GoF-паттерны, архитектурные паттеры, CQRS. В своей работе применяют методологии гибкой разработки (Agile): Scrum, Kanban, активно используют CI (TeamCity), модульное и интеграционное тестирование, автоматическое развертывание.

Пример работы команды - портал закупок строительных материалов broxer.ru. "Фишкой" проекта является интеллектуальный анализ прайс-листов компаний-поставщиков: каждый прайс разбивается на позиции и классифицируется относительно товаров из каталога сайта (используются линейные классификаторы в два этапа, около 150 тыс. предложений в базе классификатора, эффективность в районе 95-98% на обученных категориях), для этого разработан комплекс Windows-приложений, в основном на DevExpress.

Команда сработавшаяся, слаженная. Эффективность такой команды будет выше, чем у совокупности вновь нанятых разработчиков.

По вопросам сотрудничества вы можете связаться с руководителем. Его зовут Лизунов Игорь, e-mail: igor.lizunov@gmail.com, тел: +79823120053, skype: petrovich_evm.

Понравилось сообщение - подпишитесь на блог

среда, 20 ноября 2013 г.

Новый механизм экспорта OSB проектов - OSB Offline Configuration Export или configjar

Начиная с версии 11.1.1.7 в состав Oracle Service Bus добавлена утилита для экспорта конфигурации без использования Eclipse. Данная утилита расположена в каталоге OSB_HOME/tools/configjar и позволяет экспортировать настройки шины из исходников в jar-файл для последующего развертывания.

Полная документация по утилите представлена в приложении B. Exporting an Oracle Service Bus Configuration Offline официального руководства Oracle Fusion Middleware Developer's Guide for Oracle Service Bus 11g Release 1 (11.1.1.7). Не вижу смысла пересказывать данное руководство, напишу только об опыте использования утилиты.

Экспортировать конфигурацию с использованием configjar можно из командной строки, Apache Ant и WebLogic Scripting Tool (WLST). В качестве аргумента во всех случаях необходимо передать путь к конфигурационному файлу, содержащему настройки экспорта. Подразумевается, что перед использованием утилиты пользователь выполнит скрипт OSB_HOME/tools/configjar/setenv.bat и тем самым установит нужные переменные окружения, настроит CLASSPATH и подготовит среду к работе. Я же стараюсь писать скрипты сборки таким образом, чтобы они работали без необходимости настраивать окружение. Только build.xml и конфигурационные файлы. Такой перфекционизм создает ряд проблем.

Во-первых, мне не удалось заставить работать команду для Apache Ant - com.bea.alsb.tools.configjar.ant.ConfigJarTask. Данная команда требует установленной переменной окружения weblogic.home. Разобраться как передать значение данной переменной окружения команде не удалось. Однако выход есть - запускать экспорт с помощью команды java, используя класс com.bea.alsb.tools.configjar.ConfigJar:


<java fork="true" 
      dir="${deploy.dir}"
      classname="com.bea.alsb.tools.configjar.ConfigJar"            
      failonerror="true" 
      maxmemory="${osb.export.maxmem}">
    <jvmarg line="-XX:MaxPermSize=256m"/>
    <arg line="-settingsfile ${export.config.file}"/>
    <sysproperty key="weblogic.home" value="${wl.home}"/>
    <sysproperty key="osb.home" value="${osb.home}"/>   
    <sysproperty key="user.language" value="en"/>
    <sysproperty key="user.country" value="US"/>
    <classpath refid="osb_classpath"/>
</java>

Во-вторых, для работы класса com.bea.alsb.tools.configjar.ConfigJar нужно подобрать CLASSPATH. Экспорт удалось настроить, используя следующие классы:


<property name="weblogic.classpath" value="${wl.home}/server/lib"/>
<property name="osb.lib.classpath" value="${osb.home}/lib"/>
<property name="osb.tools.classpath" value="${osb.home}/tools/configjar"/>
<property name="osb.modules.classpath" value="${osb.home}/modules"/>
<property name="osb.soa.modules.classpath" value="${osb.home}/soa/modules"/>
<property name="common.modules.classpath" value="${mw.home}/oracle_common/modules"/>

<path id="osb_classpath">
    <fileset dir="${weblogic.classpath}">
        <include name="weblogic.jar"/>     
    </fileset>
    <fileset dir="${osb.lib.classpath}">
 <include name="alsb.jar"/>   
 <include name="external/log4j_1.2.8.jar"/>
    </fileset>  
    <fileset dir="${osb.modules.classpath}">
 <include name="features/osb.server.modules_11.1.1.7.jar"/>      
    </fileset>  
    <fileset dir="${osb.soa.modules.classpath}">
 <include name="oracle.soa.common.adapters_11.1.1/oracle.soa.common.adapters.jar"/>
    </fileset>  
    <fileset dir="${common.modules.classpath}">
 <include name="oracle.jrf_11.1.1\jrf-api.jar"/>
        <include name="oracle.http_client_11.1.1.jar"/>
 <include name="oracle.xdk_11.1.0\xmlparserv2.jar"/>
 <include name="oracle.webservices_11.1.1\orawsdl.jar"/>
 <include name="oracle.wsm.common_11.1.1\wsm-dependencies.jar"/>   
    </fileset>
    <fileset dir="${osb.tools.classpath}">
 <include name="configjar.jar"/>
 <include name="L10N"/>
    </fileset>
</path>

В-третьих, утилита экспорта может работать в двух режимах: экспорт на уровне проектов и экспорт на уровне отдельных ресурсов. В любом из режимов соответствующие сущности - проекты и ресурсы - требуется явно перечислить. В моей разработке необходимо организовать взаимодействие со многими (более сорока) экземплярами одной и той же информационной системы, при этом используется подход "один проект для взаимодействия с одним экземпляром системы". Получается, что нужно каким-то образом динамически сформировать список проектов для экспорта. Так как файл с настройками экспорта представляет собой XML, то для его формирования идеально подходит технология XSLT, тем более, что Apache Ant ее поддерживает из коробки. Нужно лишь сформировать XML-файл с перечислением проектов и прогнать его через преобразование. За одно можно так же в зависимости от среды (продуктив, разработка, тестирование), для которой осуществляется сборка, указать наименование jar-файла, который будет содержать результаты экспорта.

Исходными данными для формирования списка проектов является свойство projects из файла настроек сборки (например, build.properties). Значением данного свойства являются собираемые проекты, перечисленные через запятую. Наша задача обойти данное перечисление и сформировать XML со списком проектов. Для формирования XML можно использовать команду echo:


<echo message="&lt;projects&gt;" file="${deploy.dir}/projects.xml"/>
<for list="${osb.projects}"
     delimiter=","
     param="project.name">
    <sequential>
        <echo message="&lt;project&gt;@{project.name}&lt;/project&gt;"
       file="${deploy.dir}/projects.xml"
       append="true"/>
    </sequential>
</for>
<echo message="&lt;/projects&gt;" file="${deploy.dir}/projects.xml"
      append="true"/>

Теперь полученный файл со списком проектов можно отправить на XSLT-преобразование. Так же в качестве параметра передадим требуемое имя выходного файла с кодом для шины:


<xslt in="${deploy.dir}/projects.xml"
      out="${export.config.file}"
      style="${deploy.dir}/export.settings.xsl">          
    <param name="exportfile" expression="${osb.export.jar}"/>
</xslt>

Само XSLT-преобразование выглядит следующим образом:


<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    version="2.0">
    <xsl:param name="exportfile" required="yes" as="xs:string"/>
    <xsl:output method="xml" omit-xml-declaration="yes" indent="yes"/>
    
    <xsl:template match="/">
        <configjarSettings xmlns="http://www.bea.com/alsb/tools/configjar/config">
            <source>
                <xsl:for-each select="projects/project">
                    <project>
                        <xsl:attribute name="dir">build/<xsl:value-of select="."/></xsl:attribute>
                    </project>
                </xsl:for-each>    
                <system dir="build/_OSB Integration"/>
            </source>
            <configjar>
                <xsl:attribute name="jar">
                    <xsl:value-of select="$exportfile"/>
                </xsl:attribute>
                <projectLevel includeSystem="true"/>
            </configjar>
        </configjarSettings>
    </xsl:template>
</xsl:stylesheet>

Других проблем при использовании configjar не было.

Субъективные впечатления от новой утилиты исключительно положительные. Описанные выше проблемы тем или иным образом решаются, а кода теперь требует значительно меньше, чем для вызова Eclipse из Apache Ant. Памяти новый процесс сборки потребляет гораздо меньше, а работает быстрее. Экспорт шины, состоящей из 48 проектов и содержащей 954 прокси-, 28 бизнес-сервисов и 2300 XQuery-преобразований осуществляется за две минуты.

Концептуально конечно же завязывать сборку проектов на среду исполнения неверно. Представим себе, что компиляция Java EE-приложения не работала бы без установленного сервера приложений. Гораздо логичнее, когда сборка выполняется с помощью только средства разработки, без привлечения среды исполнения, как в том же IBM WebSphere Message Broker'е. Однако в Oracle Service Bus нельзя установить Eclipse и соответствующие плагины без самой OSB. Тяжелое наследие BEA. В итоге, если раньше человеку, ответственному за сборку, нужно было устанавливать и Eclipse, и OSB, то сейчас достаточно только установить OSB, что дает некоторый выигрыш во времени и числе подготовительных действий. В конце концов можно вообще ничего не устанавливать, а сборку производить на сервере разработки, сгружая туда исходники из SVN.

Понравилось сообщение - подпишитесь на блог

четверг, 14 ноября 2013 г.

Сравнение производительности механизмов ввода-вывода в Java: классического (блокирующего), неблокирующего и асинхронного

Не всегда при обеспечении взаимодействия нескольких программ можно полагаться на существующие транспортные механизмы. Да, у нас есть вся мощь веб-сервисов, при использовании серверов приложений нам доступна технология Java EE Connector Architecture (JCA), при взаимодействии с СУБД можно использовать JDBC, а в случае асинхронного взаимодействия можно использовать Java Message Service (JMS). Однако, не смотря на такое обилие технологий, бывает нужно обеспечить нетривиальное взаимодействие с системами, используя сокеты и самостоятельно реализуя протокол прикладного уровня. В данной заметке приведены результаты сравнения производительности трех существующих на данный момент в Java механизмов обеспечения сетевого взаимодействия: классического блокирующего, неблокирующего и асинхронного.

Краткая характеристика существующих подходов к организации ввода-вывода


В ответе на вопрос на сайте StackOverflow приведено сравнение имеющихся в Java механизмов ввода-вывода, при этом логика работы каждого из них продемонстрирована на соответствующей диаграмме. Кратко охарактеризуем данные подходы на примере сетевого взаимодействия.

Блокирующий ввод-вывод (IO). Данный механизм взаимодействия появился в Java самым первым и долгое время оставался единственным возможным подходом к обеспечению сетевого взаимодействия. Суть его заключается в том, что со стороны сервера и клиента создается сокет (со стороны клиента явно, со стороны сервера - в ответ на запрос соединения со стороны клиента). С каждым сокетом связаны два потока (InputStream и OutputStream): один служит для отправки сообщений, другой - для их приема. При этом все операции с данными потоками являются блокирующими, т.е. исполнение команд прерывается на время выполнения данных операций. Предположим, нам необходимо разработать индексатор сайтов (Web Crowler), являющийся частью поискового робота. Обращение к одному сайту занимает 300 мс. Если нам нужно проиндексировать 1000 сайтов, то в блокирующем режиме это займет 300 x 1000 мс, т.е. 300 секунд.

Путем ускорения работы приложений при использовании IO является многопоточность - задача делится на части, каждая из которых выполняется своим потоком управления. Например, чтобы обойти 1000 сайтов можно разбить их на четыре группы по 250 сайтов и обойти сайты из каждой группы параллельно. Самой популярной моделью взаимодействия является создание отдельного потока на каждое подключение. Таким образом все соединения обслуживаются параллельно и не мешают друг-другу. Недостатком такого подхода является линейный рост числа потоков и объема требуемой памяти при увеличении числа обслуживаемых соединений. Если потоков будет создано очень много (десятки тысяч), то операционная система сервера будет занята переключенем контекстов потоков, а на полезную работу времени может не остаться.

Неблокирующий ввод-вывод (NIO). Для решения проблем с блокирующим вводом-выводом был придуман механизм, основанный на мультиплексировании каналов. Данный механизм появился в Java 1.4.2 и был назван New IO (NIO). Суть механизма в следующем: существует мультиплексор (в терминах Java называемый селектором, java.nio.channels.Selector), который в одном потоке, последовательно, производит опрос каналов (в случае сетевого взаимодействия реализуемых классами java.nio.channels.SocketChannel и java.nio.channels.ServerSocketChannel). В результате каждого опроса селектор возвращает идентификаторы каналов, готовых к выполнению операций ввода-вывода (т.е. канал соединился с удаленной системой и в него теперь можно отправлять запрос или, наоборот, удаленная система что-то записала в канал и из него теперь эти данные можно читать). Такие идентификаторы называются "ключами" (java.nio.channels.SelectionKey). Каждый ключ содержит информацию о том, к выполнению какой операции готов канал. Задача приложения - в цикле обойти все ключи и выполнить соответствующие операции.

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

Асинхронный ввод-вывод (AIO, NIO.2). NIO является хорошим средством масштабирования приложений, активно использующих сетевые соединения, но данный подход имеет серьезный недостаток. Поток NIO вынужден явно опрашивать каналы (по-другому это называется "полинг"). При этом, если готовых к осуществлению взаимодействия каналов нет, то данный поток блокируется. Не будет ли лучше, если инициатором взаимодействия с каналами будет не приложение, а сама операционная система? Именно операционная система знает какие каналы готовы к осуществлению взаимодействия, ведь именно она осуществляет обслуживание сетевых карт, портов и прочих механизмов ввода-вывода. Как говорится, ей и карты в руки.

В Java 7 появились механизмы для обеспечения асинхронного сетевого взаимодействия. Это каналы java.nio.channels.AsynchronousSocketChannel и java.nio.channels.AsynchronousServerSocketChannel. Данные каналы содержат методы для неблокирующего установления соединения, приема соединения, записи и чтения. Каждый метод имеет два варианта: один реализован с использованием java.util.concurrent.Future - метод запускает требуемую операцию в отдельном потоке и сразу же возвращает в качестве результата объект класса java.util.concurrent.Future. Для получения результата операции необходимо вызвать Future#get(). Т.к. операция уже запущена в отдельном потоке, то она к моменту вызова Future#get() может быть уже выполнена, тогда метод get() сразу же вернет результат. В противном случае данный метод блокирует поток, в котором он вызван, до завершения операции. Другой вариант реализации асинхронных методов сетевого взаимодействия основан на использовании обработчиков обратного вызова - callback. Данный вариант реализует паттерн Proactor. Суть в следующем - каждый метод, например write, принимает в качестве параметра обработчик завершения - реализацию интерфейса java.nio.channels.CompletionHandler. Метод запускает требуемую операцию в отдельном потоке и передает управление дальше. Когда требуемая операция полностью выполняется, срабатывает один из методов переданного при старте операции обработчика завершения. Основное отличие между асинхронным и неблокирующим вводом-выводом заключается в том, что асинхронный ввод-вывод работает в многопоточной среде: операции выполняются не в тех потоках, из которых были запущены. Операции неблокирующего ввода-вывода выполняются в одном потоке путем мультиплексирования каналов.

среда, 6 ноября 2013 г.

Event-Driven Architecture на Oracle SOA Suite 11g - компонент Event Delivery Network (EDN)

Термин "управляемая событиями архитектура" (Event Driven Architecture, EDA) предложил Roy W. Schulte, аналитик Gartner в работе The Growing Role of Events in Enterprise Applications, опубликованной в 2003-м году. Одно время подход с архитектурой, управляемой событиями, рассматривали чуть ли не как замену сервисно-ориентированной архитектуре (Service-Oriented Architecture, SOA), существовал даже термин SOA 2.0. В последнее время интерес к EDA поутих, но на мой взгляд у данной концепции есть будущее. В своей заметке четырехлетней давности - Событийная модель построения приложения - Суровый пытался рассказать что такое EDA и какие компоненты необходимы для построения архитектуры, управляемой событиями, в данной же заметке рассмотрим средства, предоставляемые для этого программным продуктом Oracle SOA Suite 11g.

Сначала давайте рассмотрим зачем вообще могут быть нужны события в вашей реализации сервисно-ориентированной архитектуры. Что дает внедрение EDA простому разработчику? Прежде всего это полное разделение между системой-источником событий и системами-приемниками, что по-английски называется Super Decoupling. Что это значит? В классической SOA клиент сервиса должен знать конечную точку, предоставляемую или провайдером сервиса, или сервисной шиной предприятия. Таким образом и при смене конечной точки, и при подключении новой системы-приемника сообщений клиента необходимо изменить, как минимум перенастроить. В случае же управляемой событиями архитектуры, единственное, что должен сделать клиент - опубликовать событие. Он не должен даже знать, есть ли вообще сервисы-обработчики данного события и сколько их.

Можно провести следующую аналогию. В современных компаниях часто существует такая должность, как специалист по внутренним коммуникациям. Задача данного специалиста знать все новости компании и оповещать о них сотрудников. При этом одному сотруднику интересны новости о зарплате, другому - о каких-то кадровых изменениях, третьему - дни рождения коллег. При этом одни сотрудники работают, например, в Москве, а другие - в Челябинске. Специалист по внутренним коммуникациям заводит списки рассылки для каждого типа оповещения, а так же рассылки в разрезе городов и добавляет в них желающих получать ту или иную информацию. Затем заносит новых желающих. Затем убирает уволенных и нежелающих более получать информацию. В итоге специалист начинает что-то подозревать. В частности то, что он занимается какой-то непонятной работой. После этого он заводит корпоративный Twitter, в который начинает добавлять все новости компании, снабжая их различными хэштегами. Желающие получать определенные новости подписываются на этот Twitter, возможно с фильтром по тегам. Специалист по внутренним коммуникациям в данной метафоре является публикатором событий, желающие получать новости - подписчиками или приемниками событий, а Twitter - диспетчером событий.

При использовании шаблона проектирования "многоуровневая архитектура" необходимо обеспечить реализацию следующего правила: вызовы между слоями передаются только сверху вниз. Т.е. только верхний уровень вызывает нижний, ни в коем случае не наоборот. Нижние уровни ничего не знают о том, кто к ним обращаются. В теории все выглядит замечательно, на практике же зачастую необходимо передавать какую-то информацию от нижних уровней к верхним. Например, информацию о каких-то сервисных действиях, к примеру о выключении оборудования или о разрыве сети. Зачем передавать? К примеру, для информирования пользователя. Здесь как нельзя кстати на помощь приходит механизм событий. В стройной многоуровневой архитектуре нижний слой не знает, кто его вызывает и кого именно информировать о проблемах. Это и не нужно. Достаточно только опубликовать событие. А уже компоненты верхнего слоя подписываются на нужные им события. В итоге и канал связи между нижними и верхними слоями установлен, и стройность многоуровневой архитектуры не нарушена.

среда, 25 сентября 2013 г.

Шаблон "Обобщенный сервис" (Generic Service)

При разработке приложений на Java сразу бросается в глаза ее многословность. Причем дело здесь не столько в самом языке, сколько в принятых подходах к разработке. Например, при разработке корпоративных приложений часто используют подход с разделением системы на слои. Само по себе разделение на слои это замечательный архитектурный шаблон, правда его реализация выглядит зачастую следующим образом: есть слой представления из которого вызывается слой бизнес-логики, представляющий собой набор сервисов (по другому это называется анемичная модель предметной области). Из слоя сервисов вызывается слой объектов доступа к данным (DAO), который может быть реализован с помощью некоторого фреймворка объектно-реляционного отображения. При этом, т.к. хочется независимости реализации слоя бизнес-логики от слоя доступа к данным, то каждый DAO реализует некий интерфейс. Обращение к самим сервисам также осуществляется через интерфейсы. В итоге имеем следующую структуру:


Описание проблемы


Рассмотрим процесс поддержки приведенной выше структуры. Чтобы добавить в сервис новую операцию, необходимо выполнить следующие действия:

1. Добавить метод в интерфейс сервиса.

2. Добавить метод в реализацию сервиса.

3. Добавить метод в интерфейс DAO.

4. Добавить метод в реализацию DAO, при этом иногда встречаются проекты с разными реализациями DAO для различных окружений, поэтому метод нужно добавить в каждую.

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

понедельник, 16 сентября 2013 г.

Возможности Oracle SOA Suite для интеграции унаследованных приложений

В данной заметке мы рассмотрим возможности, которые предоставляет Oracle SOA Suite для подключения унаследованных приложений к сервисно-ориентированной инфраструктуре предприятия.

Прежде всего стоит оговориться, что под унаследованными приложениями мы будем понимать приложения, которые не предоставляют возможности подключения с помощью стандартного механизма интеграции - Web Service'ов и в то же время не являются хорошо известными и широко используемыми корпоративными приложениями, т.е. к ним не существует стандартных адаптеров. Таким образом такие лидеры рынка как SAP, OeBS, JDEdwards и Siebel не попадают под наше определение унаследованных приложений.

Теперь можно рассмотреть конкретные механизмы интеграции, предлагаемые стеком продуктов Oracle Fusion Middleware. Для Oracle SOA Suite данными механизмами являются технологические адаптеры.

вторник, 20 августа 2013 г.

Как мы обеспечили передачу с гарантированной доставкой 5 000 000 сообщений в сутки с помощью Oracle Service Bus

Сейчас работаю над проектом интеграции вновь внедряемой централизованной бизнес-системы с другими системами, установленными в филиалах заказчика. При этом основная задача заключается в том, чтобы синхронизировать данные в филиалах и центре с помощью сервисной шины предприятия (ESB), реализованной на платформе Oracle Service Bus. Мы смогли обеспечить передачу с гарантированной доставкой боле 5 000 000 сообщений в сутки. В данной статье хочу рассказать о том, как это было сделано.


Постановка задачи


Нам необходимо передавать изменения данных из одной системы (системы-источника) в другую - систему-приемник. Данные должны передаваться сразу, а не с помощью пакетной обработки. Соответственно, нужно каким-то образом захватывать события об изменении данных и публиковать их для сервисной шины. Хорошо зарекомендовал себя следующий паттерн: при изменении данных пользователем с помощью триггера в БД системы-источника формируется событие, которое записывается в специальную таблицу. У события есть идентификатор, признак типа - какая именно сущность была создана или изменена, тип операции: создание, изменение или удаление, статус: новое, на обработке, обработанное успешно или обработанное с ошибкой. По идентификатору события мы с помощью соответствующего типу сущности представлению можем получить актуальные на момент обработки события данные. Сервисная шина последовательным опросом таблицы событий (по-другому это называется "полинг") считывает порцию измененных данных, затем для каждого считанного события обращается к соответствующему представлению и получает данные. Данные трансформируются в канонический формат шины, при этом на одну считанную запись может быть сформировано от нуля до пяти сообщений. Сообщения записываются в JMS-очередь, а записям в таблице событий проставляется статус "на обработке". Другой компонент адаптера - прокси-сервис, использующий транспорт JMS, считывает сообщения в каноническом формате из очереди, преобразует их в формат системы-приемника и вызывает веб-сервис, предоставляемый данной системой. Адаптер ждет окончания работы сервиса, после чего получает статус обработки сообщения и записывает его в специальную очередь ответов. Статус считывается шиной из очереди ответов и обновляется в таблице событий системы-источника.

На диаграмме UML данный процесс будет выглядеть следующим образом:


Стоит заметить, что с одной стороны события считываются из базы порциями, по 120 событий за один раз. Таким образом 5 000 000 событий в сутки это 41 600 транзакций. С другой стороны каждая запись раскладывается на от нуля до пяти сообщений, в среднем примем два. Каждое такое сообщение должно быть передано в систему-приемник, получается 10 000 000 транзакций. После этого для каждого события необходимо обновить статус - 5 000 000 транзакций. При этом все транзакции распределенные, т.к. в них участвует по меньшей мере два ресурса: база - очередь или очередь - очередь. Итого получается, что производительность системы должна быть не меньше 180 транзакций в секунду. Это конечно не то, что пафосно называют словом HighLoad, но уже возможно всего в одном - двух порядках от него.

среда, 14 августа 2013 г.

Подготовка релиза сервисной шины предприятия на нашем проекте

На своем текущем месте работы Суровый занимается интеграцией внедряемой CRM с другими информационными системами телеком-оператора: биллингами, техническим учетом, ERP, активацией, Ordering Management System (OMS) и т.д. Сейчас у нас подключено к сервисной шине четыре макрорегиональных филиала, при этом стоит отметить, что в каждом макрорегиональном филиале свой IT-ландшафт, что делает проект еще более интересным.

О чем хочется рассказать в данной заметке. Нам на проекте необходимо обеспечить работоспособность конкретного подмножества сервисов на шине для одного основного клиента (CRM), при этом у нас есть временной лаг между разработкой клиента (CRM), разработкой сервисной шины и разработкой (внедрением) внешних систем - поставщиков сервисов. При этом нам нужно иметь гарантированно стабильный и готовый для развертывания код шины.

Ситуация в целом характерная для большинства интеграционных проектов. Проблема в том, что данная ситуация требует разработки подхода к подготовке релизов шины, чтобы при установке очередного релиза в продуктив не сломалось ни взаимодействие клиента с шиной, ни взаимодействие шины с внешними системами.

При этом у нашего проекта есть следующие особенности.

1. Небольшая команда разработки сервисной шины - порядка 5-ти человек.

2. Несмотря на скромный размер команды за год разработано и внедрено 13 сервисов и 46 экземпляров адаптеров к информационным системам. Сложность логики сервисов весьма разнообразна - от простого оборачивания вызова хранимой процедуры в SOAP, до сложной оркестровки с использованием компонента Split-Join.

3. В качестве системы контроля версий исходного кода используется SVN.

4. Технологическая платформа - Oracle Service Bus - не поддерживает "из коробки" версионирование сервисов, т.е. мы не можем иметь в продуктиве несколько версий одного и того же сервиса одновременно. С учетом того, что у нас всего один основной клиент и с его разработчиками всегда можно договориться, то мы вполне можем обойтись без данной возможности.

5. Разработка ведется по гибкой методологии. К сожалению это иногда приводит к непродуманности технических решений и несогласованности изменений, особенно с поставщиками внешних систем.

понедельник, 10 июня 2013 г.

Коммуникация в кластере серверов приложений Oracle WebLogic

В данной заметке мы рассмотрим довольно важный для понимания настройки и поддержки серверов приложений Oracle WebLogic вопрос - вопрос коммуникации в кластере.

Общие положения


Прежде всего стоит отметить, что для коммуникации серверов приложений в кластере используется две базовые технологии:

  • IP-сокеты - для коммуникации вида точка-точка между участниками кластера;

  • IP unicast и multicast для распространения информации о доступности серверов и их состоянии, а так же для построения кластерного JNDI-дерева.

При создании кластера с помощью Configuration Wizard по умолчанию устанавливается режим обмена unicast, а при создании кластера с помощью WLST - multicast. Если есть проблемы с распространением JNDI-дерева на кластер с помощью unicast, то может помочь использование нового свойства - ClusterMBean.MessageOrderingEnabled. По умолчанию данное свойство не включено. Чтобы его включить нужно добавить следующую строчку в config.xml:

<message-ordering-enabled>true</message-ordering-enabled>.

Если данная настройка не решает проблему, то нужно перейти на использование multicast режима.

среда, 29 мая 2013 г.

Интересное про сервер администрирования домена WebLogic

Как ведет себя домен сервера приложений WebLogic, если сервер администрирования аварийно завершает свою работу или по каким-то другим причинам становится недоступным?

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

суббота, 18 мая 2013 г.

Сценарии использования JMS вне системной интеграции

Подсистема Java Message Service (JMS), появившаяся в уже далеком 2001-м году, завоевала заслуженную популярность у разработчиков и архитекторов. Действительно, с помощью JMS можно легко реализовать сценарии интеграции путем асинхронного обмена сообщениями с гарантированной доставкой, а так же в модели "публикация/подписка" еще и в отношении один-ко-многим: одно сообщение из системы источника может быть доступно нескольким системам-приемникам.

В данной же заметке хотелось бы рассмотреть сценарии использования JMS вне контекста системной интеграции, т.е. ответить на вопрос: "А что может дать использование JMS в рамках одного приложения?".

среда, 15 мая 2013 г.

Удаление Oracle Fusion Middleware

Иногда нам нужно удалить из MIDDLEWARE_HOME какой-либо компонент, а может быть и MIDDLEWARE_HOME целиком. Сделать это можно следующим способом:

1. Удалить ненужный вам более компонент, например SOA Suite:
MIDDLEWARE_HOME/Oracle_SOA1/oui/bin/setup.exe -deinstall -jreLoc jre

здесь jre - путь к JRE на вашей машине. При необходимости можно удалить остальные компоненты Oracle Fusion Middleware, например OSB.

2. После удаления компонентов необходимо удалить oracle_common:
MIDDLEWARE_HOME/oracle_common/oui/bin/setup.exe -deinstall -jreLoc jre

3. После удаления Oracle Fusion Middleware можно удалить сервер приложений WebLogic:
MIDDLEWARE_HOME\wlserver_10.3\uninstall\uninstall.cmd

Если вы устанавливали WebLogic под одной JDK, а потом ее обновили или удалили и сейчас используете другую, то данная команда может не выполниться. Необходимо прописать правильный путь к JDK в переменной окружения JAVA_HOME в файле MIDDLEWARE_HOME\utils\uninstall\uninstall.cmd, после чего можно запустить данный файл.

4. Аналогичным образом удалить JDeveloper.

5. Удалить каталог MIDDLEWARE_HOME.

6. Удалить запись о MIDDLEWARE_HOME из файла C:\bea\beahomelist.

7. На ОС Windows необходимо удалить соответствующую группу программ из главного меню.

Понравилось сообщение - подпишитесь на блог и Twitter

среда, 24 апреля 2013 г.

Соображения по использованию WorkManager'ов на сервере приложений Oracle WebLogic

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

Показания для вмешательства в работу пула потоков


Прежде всего следует помнить, что использование стандартного WorkManager'а (default) как правило является вполне допустимым решением: на каждое развернутое на сервере приложение будет создан свой WorkManager, имеющий настройки по-умолчанию. Дополнительные менеджеры потоков нужно определять лишь в следующих случаях:

  • Приоритеты потоков по-умолчанию - все потоки имеют равный приоритет - нас не устраивают (Fair Share).

  • Необходимо задать время ответа, к которому сервер приложений должен стремиться (Response Time).

  • Возможны взаимоблокировки при взаимодействии сервер-сервер, в данном случае необходимо настроить WorkManager с явно заданным ограничением числа потоков снизу (Minimum Threads Constraint).

  • При работе приложения используется общий для нескольких потоков пул соединений JDBC, тогда необходимо ограничить число этих потоков сверху (Maximum Threads Constraint).

Отдельно стоит заметить, что если на сервере приложений Oracle WebLogic развернута Oracle Service Bus, то для избежания взаимоблокировок при использовании Service Callout'ов необходимо, чтобы вызываемые таким образом сервисы имели отдельные WorkManager'ы. Подробнее про модель потоков OSB можно прочитать в одноименной статье.

понедельник, 22 апреля 2013 г.

О производительности: RouterRuntimeCache в Oracle Service Bus


В настройках Oracle Service Bus присутствует интересный параметр: com.bea.wli.sb.pipeline.RouterRuntimeCache.size. Данный параметр отвечает за то, сколько скомпилированных прокси-сервисов будет храниться в кэше. По-умолчанию его значение равно 100.

OSB реализует следующую логику - прокси-сервис компилируется при первом использовании и помещается в кэш. Если кэш переполнен (т.е. прокси-сервисов более 100), то сервисы удаляются из кэша, а затем, при последующих обращениях, повторно компилируются. Соответственно, если на шине развернуто много прокси-сервисов, что характерно для больших SOA-окружений, развернутых в крупных предприятиях со множеством филиалов, то ее производительность падает. Нужно увеличивать значение данного параметра.

Сделать это можно с помощью аргумента командной строки:

-Dcom.bea.wli.sb.pipeline.RouterRuntimeCache.size=3000


Данный параметр можно добавить в определение переменной окружения EXTRA_JAVA_PROPERTIES в файле setDomainEnv.sh/cmd.

Понравилось сообщение - подпишитесь на блог и Twitter

вторник, 2 апреля 2013 г.

Локальная оптимизация вызовов сервисов в Oracle SOA Suite

В Oracle SOA Suite реализован механизм локальной оптимизации вызовов сервисов, реализованных так же на Oracle SOA Suite. Т.е. если мы из одного композита вызываем с помощью Web Service Adapter сервис, реализованный в другом композите, то в реальности Oracle SOA Suite не будет формировать SOAP-сообщение и делать вызов по протоколу HTTP. Вместо этого он просто выполнит соответствующий код на JVM, на которой запущен Oracle SOA Suite, а значит и клиент сервиса, и его реализация.

Соответствующая оптимизация обладает как преимуществами, так и недостатками.

Преимущества:

  • Повышение быстродействия: не тратится время на сериализацию параметров вызова в SOAP-сообщение, передачу данных по сети, а так же обратную десериализацию SOAP-сообщения с ответом.

  • Распространение контекста транзакции: т.к. в реальности вместо сетевого взаимодействия вызывается код, работающий на той же JVM, то и инициатор вызова, и вызываемый сервис работают в рамках одной транзакции - если после изменения данных сервисом на клиенте произошел сбой, то транзакция откатывается и изменения не будут сохранены.

Недостатки:

  • Отсутствие возможности балансировки нагрузки: при локальной оптимизации всегда будет вызван экземпляр сервиса, расположенный на том же узле кластера, на котором расположен клиент сервиса.

  • Проблемы при работе механизма политик OWSM, в частности, связанных с безопасностью. Не все политики OWSM работают в режиме локальной оптимизации вызовов, соответственно, разработчик может ожидать, что для вызова из композита сервиса, реализованного в другом композите, будет требоваться авторизация, а в реальности, т.к. политика не сработала, то никакой авторизации не потребуется, сервис будет доступен любому пользователю.

Локальная оптимизация вызовов включена по-умолчанию, но ее можно отключить. Делается это путем выставления значения свойства oracle.webservices.local.optimization в false. Выставить данное свойство в false можно как в композите-провайдере сервиса, тогда локальная оптимизация будет отключена для всех вызовов сервиса, так и в композите-клиенте, тогда локальная оптимизация будет отключена только для этого клиента.

<binding.ws
    port="http://xmlns.oracle.com/CalledBPELProcessApp_
    jws/CalledBPELProcess/CalledBPELProcess#wsdl.endpoint(calledbpelprocess_client_
    ep/CalledBPELProcess_pt)"
    location="http://localhost:8001/soa-infra/services/default/CalledBPEL
    Process!1.0/calledbpelprocess_client_ep?WSDL">
      <wsp:PolicyReference URI="oracle/wss_username_token_client_policy"
                           orawsp:category="security"
                           orawsp:status="enabled"/>
      <wsp:PolicyReference URI="oracle/log_policy"
                           orawsp:category="management"
                           orawsp:status="enabled"/>
      <property name="oracle.webservices.local.optimization">false</property>
</binding.ws>


Понравилось сообщение - подпишитесь на блог и Twitter

суббота, 23 марта 2013 г.

Практический пример построения сервиса на Oracle Service Bus

В данной заметке мы рассмотрим практический пример построения веб-сервиса, работающего по протоколу HTTP с использованием сообщений в формате SOAP (SOAP over HTTP), функциональность которого заключается в предоставлении доступа к бизнес-логике существующего приложения. Приложением является биллинговая система, реализованная на основе двухзвенной архитектуры. Связь сервисной шины предприятия и приложения будет осуществляться с помощью JDBC путем вызова хранимых процедур в базе данных биллинга. Разрабатываемый сервис будет предоставлять доступ к управлению счетами: получение данных о счете, создание счета и отмена счета.

Предполагается, что мы пройдем по всем этапам разработки интеграционного решения от создания адаптеров и проекта OSB, до настройки среды исполнения и развертывания разработанного сервиса. Так же рассмотрим процесс тестирования с помощью SOAP UI. Будет интересно!

вторник, 26 февраля 2013 г.

Включение административного канала на сервере приложений WebLogic

Сервер приложений Oracle WebLogic позволяет включить специальный защищенный сетевой канал для доступа администратора к запущенным экземплярам. Трафик по данному каналу имеет приоритет перед обычными запросами, обрабатываемыми сервером, поэтому даже, если все сервера домена будут находиться под высокой нагрузкой, администратор сможет выполнять свои задачи. Помимо этого административный канал можно применять для тестирования приложений. Так же следует отметить, что взаимодействие управляемых серверов и сервера администрирования так же осуществляется по административному каналу.

Перед включением административного канала необходимо настроить SSL для всех серверов домена. Рассмотрим настройку SSL с использованием сгенерированного самоподписанного сертификата.

пятница, 22 февраля 2013 г.

Правильное тестирование и обновление приложения на сервере приложений WebLogic

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

вторник, 19 февраля 2013 г.

Некоторые изменения в сертификации по Oracle SOA Suite

Если вы хотите стать сертифицированным специалистом по Oracle SOA Suite, то вам следует ознакомиться с произошедшими изменениями. Oracle изменила программу экзамена, теперь вместо 1Z0-451 следует сдавать экзамен 1Z1-478. Программа экзамена представлена на официальной странице портала Oracle Certification.

Следует отметить, что добавились как более практические темы, например XPath, архитектура JCA-адаптеров, вопросы на знание лучших практик по установке системы, так и совершенно новые разделы, такие как SOA Governance.

Важно! Специалистам, уже сдавшим 1Z0-451, сдавать 1Z1-478 нет необходимости.

Другое изменение заключается в том, что теперь после успешного прохождения экзамена присваивается не статус Oracle Service Oriented Architecture Infrastructure Implementation Certified Expert, а статус Oracle SOA Suite 11g Certified Implementation Specialist. Данное изменение скорее всего направлено на унификацию требований к получению партнерской специализации.

Успехов вам на экзамене!

Понравилось сообщение - подпишитесь на блог и Twitter

понедельник, 18 февраля 2013 г.

Пример разработки веб-сервиса по контракту с использованием Oracle SOA Suite и Spring Framework

В прошлых заметках мы рассмотрели теоретические вопросы проектирования контракта сервиса и валидации сообщений с помощью XShema и Schematron. В данной статье продемонстрируем использование этих знаний на практике: создадим веб-сервис, основываясь на его контракте. В качестве технологической платформы будем использовать Oracle SOA Suite и Spring Framework.

Разработка контракта сервиса


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

вторник, 5 февраля 2013 г.

Очистка постоянных хранилищ (Persistent Store) сервера приложений WebLogic с помощью WLST

Для сохранения в долговременной памяти различных объектов, таких как сервисы диагностики, JMS-сообщения, логи транзакций, таймеры и т.д., сервер приложений Oracle WebLogic использует механизм постоянных хранилищ (Persistent Store). Постоянные хранилища могут работать как с диском (File Stores), так и с СУБД (JDBC Stores). При этом сервер приложений никогда не очищает файловое хранилище, т.е. не уменьшает его размер даже если в нем не осталось объектов.

Стоит отметить, что если объем файлового хранилища очень велик (более гигабайта), то процесс восстановления объектов из него при перезапуске сервера приложений существенно замедляется. Суровый наблюдал десятиминутное восстановление из хранилища объемом 1,3 Гб на продуктивном сервере, при этом реально считывалось всего порядка шестисот сообщений размером по 1-2 Кб.

Для очистки хранилища администратору сервера приложений доступна утилита командной строки weblogic.store.Admin и утилита WebLogic Scripting Tool (WLST). При использовании WLST необходимо выполнить команду compactstore, принимающую в качестве аргументов путь к каталогу, в котором содержатся файлы хранилища, и путь к каталогу временных файлов - в данном каталоге будет создана резервная копия хранилища. Последний аргумент является необязательным, однако если вы его указываете, то необходимо учитывать, что каталог для резервной копии не может находиться внутри каталога хранилища. Команду compactstore можно выполнять только при выключенном экземпляре сервера приложений WebLogic, использующем хранилище.

Пример:

wls:/offline> compactstore('/home/weblogic/user_projects/domains/esb_domain/store/RTKDSVStore_1')

Подробнее про использование постоянных хранилищ можно прочитать в разделе Using the WebLogic Persistent Store документа Configuring Server Environments for Oracle WebLogic Server 11g Release 1 (10.3.6).

Понравилось сообщение - подпишитесь на блог и Twitter

понедельник, 7 января 2013 г.

Валидация XML-сообщений

В статье Проектирование контракта сервиса мы отметили, что действительно самодокументируемый контракт подразумевает возможность автоматической валидации сообщений, которыми данный сервис общается с внешним миром. Пришло время рассмотреть данный процесс подробнее.

Прежде всего давайте разберемся в каких случаях необходима валидация сообщений.

  1. Мы можем ничего не знать о клиенте нашего сервиса, соответственно нам необходимо проверить запросы, поступающие от данного клиента, перед тем как их обрабатывать.

  2. Сообщения, поступающие от внешних сервисов, т.е. сервисов, которые мы не контролируем, должны подвергаться валидации.

Лучшей практикой считается вызов внешних сервисов через ESB. Данное решение позволяет вынести валидацию на шину и реализовать ее один раз, вместо того, чтобы реализовывать ее везде, где используется конкретный сервис.

Не обязательно осуществлять валидацию сообщений в следующих случаях:

  1. Если сообщение передается от одного компонента к другому внутри композитного приложения, то необходимости валидации нет: это наше приложение, мы его полностью контролируем.

  2. Во внутренних сервисах или других контролируемых нами приложениях валидация обычно не требуется, но может быть реализована. В случае, если внутренний сервис осуществляет обработку данных, вводимых пользователями, то валидация необходима.

В данной заметке мы рассмотрим некоторые приемы валидации сообщений, а так же способы обработки ошибок, возникающих при проверке некорректных сообщений.

воскресенье, 6 января 2013 г.

Паттерны проектирования XML-схем

В данной заметке мы продолжим тему разработки контрактов сервисов. В предыдущей статье мы отметили, что стандартом де-факто в настоящее время для представления контрактов сервисов является WSDL. Предполагается, что общение с сервисом осуществляется посредством сообщений, представленных в формате XML. Структура данных сообщений описывается с помощью языка XML Schema.

Существует несколько паттернов проектирования XML-схем. Использование данных паттернов позволяет описать одну и ту же структуру XML-документа разными способами, каждый из которых имеет свои преимущества и недостатки. Рассмотрим данные способы подробнее.