Содержание


Повышение производительности и масштабируемости системы IBM Sterling Order Management

Рекомендации по проектированию и программированию

Comments

Обзор

IBM Sterling Order Management представляет собой OLTP-приложение; такие приложения считаются масштабируемыми, если их можно наращивать для обработки большего числа транзакций, добавляя новые процессоры и устройства хранения данных. Индивидуальный проект или код оказывает значительное влияние на масштабируемость всего приложения. Эта статья содержит практические рекомендации по проектированию, которые можно использовать при реализации Sterling Order Management для обеспечения масштабируемости приложений.

  1. Уменьшите влияние зависимости от внешних систем
  2. Определите оптимальную границу транзакций
  3. Исключите перегрузку при сборе мусора ( garbage collection – GC)
  4. Уменьшите нагрузку на систему ввода-вывода
  5. Уменьшите нагрузку на сеть

Рекомендация 1. Уменьшите влияние зависимости от внешних систем

Приложение IBM Sterling Selling and Fulfilment Suite® взаимодействует с различными внешними приложениями, такими как AVS (Address Verification System), системы платежей и системы расчета налогов в рамках цикла выполнения заказов. Эти взаимодействия создаются в результате транзакций на уровне приложения или на уровне агента. Транзакции уровня приложения, синхронные по своей природе, запускаются операцией запроса или ответа, а результат обработки возвращается инициатору сразу же после операции. Однако если уровень агента, создающий асинхронную транзакцию, запускается односторонней операцией, то результаты возвращаются путем запуска другой односторонней операции; синхронное взаимодействие с внешними системами приводит к сильной зависимости, которая влияет на опыт пользователей. Если внешняя система не отвечает, то клиентское приложение, такое как COM или SOM, отобразит окно, не реагирующее на действия пользователя. Несколько вызовов в пределах одной транзакции подрывают масштабируемость, так как поток веб-контейнера не будет вовремя возвращен в общий пул для обработки других запросов. Это приводит к недостижению настроенного оптимального числа потоков веб-контейнера. Сервер приложений имеет настраиваемые параметры ожидания потока, что позволяет гарантировать, что поток не зависнет на неопределенное время. Однако на уровне агента эта угроза сохраняется, поскольку там нет параметров настройки времени ожидания потока. Таким образом, жизненно важно включить реализацию ожидания либо на стороне Sterling Selling and Fulfilment Suite, либо в промежуточном ПО (при его наличии) и в случае отсутствия ответа от внешней системы выдавать на экран пользователя соответствующее сообщение о тайм-ауте.

Рекомендация 2. Определите оптимальные границы транзакции

Транзакция содержит задачу, которая выполняется в режиме «все или ничего», что обеспечивает атомарность. Для определения оптимальной границы транзакции требуется четкое понимание последовательности операций, которые происходят в пределах границ транзакции, чтобы обеспечить масштабируемость и восстанавливаемость приложения. Границы транзакции применимы как к синхронным, так и к асинхронным транзакциям. Время отклика для пользователя или пропускная способность и механизм блокировки – два важнейших аспекта, которые следует учитывать при определении оптимальной границы транзакции. API CreateOrder и ScheduleOrder, которые укладываются в границы одной транзакции для одной реализации, могут не соответствовать требованиям по пропускной способности или времени реакции для другой. Все синхронные транзакции должны быть короче и обеспечивать минимальную эксклюзивную блокировку строк для достижения наилучшего времени отклика. Неправильный шаблон расширения базовых API также может вызвать нежелательную блокировку.

Например, вызов API getShipmentDetails в версии 8.5 с шаблоном по умолчанию не приведет к блокировке, но если в шаблон добавить сведения о заказе, то произойдет эксклюзивная блокировка строк записи заказа. В таких сценариях, как changeOrder и manageOrganizationHierarchy, блокировка неизбежна; проектировщику необходимо определить более короткие границы транзакции, чтобы все блокировки, полученные операторами в рамках транзакции, происходили во время транзакции. Чем шире границы транзакции, тем выше вероятность блокировки строки как на уровне приложения, так и на уровне агента, что в конечном итоге препятствует масштабируемости.

Следующий пример помогает лучше понять проблему блокировки. Предположим, что API getOrderDetails и getShipmentList запускаются один за другим в границах одной транзакции. API getOrderDetails блокируется для записи заказа и не отпускается до тех пор, пока не завершится выполнение getShipmentList. Для сужения области поиска все API List должны запускаться со строгими параметрами критериев. Это особенно важно в том случае, когда API List предоставляются внешней системе в качестве компонента веб-сервиса. Если из базы данных извлекается несколько записей, и в коде SQL присутствует фраза ORDER BY, то вся транзакция выполняется гораздо дольше из-за операции сортировки со стороны базы данных. База данных всегда пытается выполнять сортировку в пространстве ОЗУ внутри sort_area_size и прибегает к сортировке на диске лишь тогда, когда ресурсы оперативной памяти исчерпаны. Если количество записей не укладывается в оперативную память, то сортировка происходит в диске, что приводит к еще большему количеству циклов процессора. Фразу ORDER BY можно исключить, добавив во входной XML-файл атрибут IgnoreOrdering=Y.

Рекомендация 3. Исключите перегрузку при сборе мусора (GC)

Для динамического выделения памяти уровень приложения и уровень агента используют JVM™. Когда неэффективный специальный код создает много объектов, в области кучи остается мало места для новых объектов, и JVM™ выполняет дополнительную работу, что приводит к частым операциям сбора мусора (GC). GC выявляет объекты данных, которые больше не вызываются, и освобождает память, занятую этими объектами. Создание объекта – одна из самых дорогостоящих операций с точки зрения использования памяти и производительности. Поэтому рекомендуется создавать или инициализировать объекты в коде только тогда, когда это необходимо. Следует избегать создания временных объектов в часто вызываемых методах. Лучше заранее создать объекты и хранить их, пока они нужны. Java™-программы проводят значительное количество времени в цикле. Поэтому никогда не создавайте временные объекты внутри цикла, чтобы оптимизировать цикл для достижения лучшей производительности. Следующий пример демонстрирует оптимизированный цикл for.

Листинг 1. Исходный пример кода цикла for
public loop control 1()
{
  String str = "Sudhanshu";
  for (int j = 0; j < str.length(); j++)
  {
    // код не изменяет длину строки.
  }
}

public loop control 2()
{
  String str = "Sudhanshu";
  int len = str.length();
  for (int j = 0; j < len; j++)
  {
    // код не изменяет длину строки.
  }
}

Цикл loop control2 можно еще больше улучшить, изменив счет на обратный. JVM™ оптимизирована для операций сравнения целых чисел от -1 до +5. Поэтому переписав цикл так, чтобы производить сравнение с 0, мы ускорим его. Цикл из листинга 1 можно изменить с использованием следующей инструкции.

Листинг 2. Измененный пример кода цикла for
for (int j = len-1; j >= 0; j-)

При объединении строк с помощью оператора «+» создается много временных объектов и увеличивается работа по сбору мусора, и оно выполняется гораздо медленнее, чем StringBuffer. Методы, работающие со строкой, возвращают новую строку, а не обновленную копию старой.

Листинг 3. Пример кода с объединением строк
String abc = "<OrderLineList>" +
		" <OrderLine DeliveryMethod="  "
		ItemGroupCode="  "
		OrderLineKey="  "
		OrderedQty="  " +
		" PrimeLineNo=" "
		SubLineNo="/>" + 
		" >) ";

Неправильное использование коллекций создает значительную нагрузку по сбору мусора. Например, ArrayList создает пространство и копирует все ссылки во время вставки; это обходится тем дороже, чем больше размер ArrayList. Важно также помнить, что TreeMap работает медленнее, чемHashMap.

Рекомендация 4. Обеспечьте надлежащее расширение базы данных

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

  • CHAR используется для хранения строк символов фиксированной длины. Перед сохранением на диске строковые значения дополняются пробелами. Применять этот тип для хранения строк переменной длины – значит неэффективно использовать дисковое пространство.
  • VARCHAR2, напротив, используется для хранения строк символов переменной длины. Длина строковой переменной хранится на диске вместе с самим значением, что приводит к эффективному использованию дискового пространства.

Таким образом, CHAR – это большее число, поэтому в Sterling Selling and Fulfilment Suite V9.1 все столбцы OOB типа CHAR заменены на VARCHAR2. Во время OLTP-транзакций Sterling Selling and Fulfilment Suite происходят частые вставки и обновления данных транзакций. Эти обновления повышают вероятность возникновения проблемы сцепления строк и миграции строк в случае неправильно выбранных типов данных для дополнительных столбцов.

  • Миграция строк - база данных Oracle® перемещает всю строку в новый блок данных, если строка вписывается в новый блок. Исходная строка перенесенной строки содержит указатель или «адрес пересылки», указывающий на новый блок, содержащий перенесенную строку.
  • Сцепление строк - база данных Oracle® хранит данные строки в цепочке из одного или нескольких блоков данных, зарезервированных для сегмента. Сцепление строк чаще всего происходит с большими строками.

База данных выполняет одну операцию ввода-вывода для чтения индекса и одну операцию ввода-вывода для считывания из таблицы неперенесенной строки, но для получения фактических данных из перенесенной или сцепленной строки ей требуются дополнительные операции ввода-вывода. Расширение OOB-таблицы, содержащее много столбцов, такое как YFS_ITEM – 152 столбца, YFS_ORDER_LINE – 179 столбцов,YFS_SHIPMENT – 156 столбцов для хранения данных типа CLOB, приведет к переносу строк в случае частого обновления. Если общее количество столбцов в таблице превышает 255, то создается сцепление строк. Таким образом, любые расширения этих таблиц Sterling Selling and Fulfilment Suite следует выполнять очень аккуратно. Для включения специальных столбцов с данными типа CLOB или VARCHAR (размер столбца > 1000) всегда оценивайте возможность их сохранения как отдельных объектов с внешним ключом. Кроме того, чтобы сократить количество операций ввода-вывода, важно ограничить специальный шаблон, чтобы он управлял только данными, которые извлекаются из главной, а не из вспомогательной таблицы.

Рекомендация 5. Уменьшите нагрузку на сеть и систему ввода-вывода

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

Например, если исключение возникает во время операции пользователя и специальная логика отправляет всю последовательность стека ошибок в COM или SOM для пользователя, то это приводит к перегруженности сети, так как через сеть проходят лишние данные. Эти данные, отображаемые пользователю, не нужны. Для отображения полезного сообщения об ошибке применяется специальная функция кода ошибки OOB.

Листинг 4. Неправильное кодирование
yfsUserExitException.setErrorDescription(e.getMessage());
yfsUserExitException.setStackTrace(e.getStackTrace());

Оператор System.out.println внутри специального кода Java™ потребляет дисковое пространство, выделенное экземпляру сервера приложений, что приводит к состязаниям за дисковое пространство. Он также вносит задержку записи в журнал событий, что приводит к замедлению реакции или уменьшению пропускной способности, так как журнал JVM синхронизирован. По умолчанию в журнале регистрируются сообщения INFO и ERROR из приложения Sterling Selling and Fulfilment Suite. Поэтому для протоколирования следует использовать метод Log4j, а не System.out.println. База данных будет перегружена операциями ввода-вывода из-за большого числа расширенных столбцов с данными типа CLOB или VARCHAR2 (размер > 2000) в таблицах.

Например, внутренне продукт выполняет запрос select в основном с признаком '*' в параметре YFS_ITEM.

Листинг 5. ЗАПРОС SELECT
SELECT  /*YANTRA*/ YFS_ITEM.* FROM YFS_ITEM YFS_ITEM WHERE (YFS_ITEM.ITEM_KEY = 'XYZ')

Запрос из листинга 6 извлекает одну запись из базы данных, так как Item_KEY представляет собой первичный ключ, который используется в операторе WHERE. Но операция ввода-вывода становится узким местом из-за большого числа столбцов, которые включают в себя расширенные столбцы типа CLOB или VARCHAR2 в составе объекта YFS_ITEM. Поэтому следует убедиться, что извлекаемые данные строго контролируются шаблоном.

Заключение

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


Ресурсы для скачивания


Похожие темы


Комментарии

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

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=40
Zone=Технология Java
ArticleID=1006844
ArticleTitle=Повышение производительности и масштабируемости системы IBM Sterling Order Management
publish-date=05262015