46
Глава 1
Если все операторы выполняются быстро, архитектура MTS работает отлично. Можно
эффективно обслуживать небольшим количеством процессов большое сообщество
пользователей. Если же имеются сеансы, монополизирующие разделяемый сервер на-
долго, то кажется, что СУБД "зависает". Пусть сконфигурировано десять разделяемых
серверов для поддержки 100 пользователей. Если в некоторый момент времени десять
пользователей одновременно введут оператор, выполняющийся более 45 секунд, то всем
остальным транзакциям (и новым подключениям) придется ждать. Если некоторым из
ожидающих в очереди сеансов необходимо выполнять оператор такой же продолжитель-
ности, возникает большая проблема — "зависание" будет продолжаться не 45 секунд, а
намного дольше. Даже если желающих выполнить подобный оператор одновременно
будет не десять, а лишь несколько, все равно будет наблюдаться существенное падение
производительности сервера. Мы отберем на длительное время совместно используемый
ресурс, и это плохо. Вместо десяти серверных процессов, выполняющих быстрые зап-
росы в очереди, остается пять или шесть (или еще меньше). Со временем система ста-
нет работать с производительностью, заметно меньше предполагаемой, исключительно
из-за нехватки этого ресурса.
Простое решение "в лоб" состоит в запуске большего количества разделяемых серве-
ров, но в конечном итоге придется запускать разделяемый сервер для каждого пользо-
вателя, а это неприемлемо для системы с тысячами пользователей (как та, что создава-
лась в рассматриваемом проекте). Это не только создает узкие места в самой системе
(чем большим количеством процессов приходится управлять, тем больше процессорно-
го времени на это уходит), но и просто не соответствует целям создания режима MTS.
Реальное решение этой проблемы оказалось простым: не выполнять продолжитель-
ные транзакции на сервере, работающем в режиме MTS. А вот реализация этого реше-
ния оказалась сложнее. Это можно было сделать несколькими способами, но все они
требовали существенных изменений архитектуры. Самым подходящим способом, тре-
бующим минимальных изменений, оказалось использование средств расширенной под-
держки очередей (Advanced Queues — AQ).
AQ — это промежуточное программное обеспечение для обмена сообщениями, реализо-
ванное на базе СУБД Oracle и позволяющее клиентскому сеансу добавлять сообщения
в таблицу очереди базы данных. Это сообщение в дальнейшем (обычно сразу после фик-
сации транзакции) выбирается из очереди другим сеансом, проверяющим содержимое
сообщения. Сообщение содержит информацию для обработки другим сеансом. Оно
может использоваться для эмуляции мгновенного выполнения за счет вынесения про-
должительного процесса за пределы интерактивного клиента.
Итак, вместо выполнения 45-секундного процесса, компонент должен помешать зап-
рос со всеми необходимыми входными данными в очередь и выполнять его асинхрон-
но, а не синхронно. В этом случае пользователю не придется ждать ответа 45 секунд, то
есть система становится более динамичной.
Хотя, судя по описанию, этот подход прост (подключение механизма AQ полностью
решает проблему), потребовалось сделать намного больше. Этот 45-секундный процесс
генерировал идентификатор транзакции, необходимый на следующем шаге в интерфейсе
для соединения таблиц — по проекту интерфейс без этого не работал. Используя меха-
Разработка успешных приложений для Oracle
низм AQ, мы не ждем генерации идентификатора транзакции, — мы обращаемся к си-
стеме с просьбой сделать это когда-нибудь. Поэтому приложение опять оказалось в ту-
пике. С одной стороны, мы не можем ждать завершения процесса 45 секунд, но, с дру-
гой стороны, для перехода к следующему экрану необходим сгенерированный
идентификатор, а получить его можно только спустя 45 секунд. Для того чтобы решить
эту проблему, пришлось синтезировать собственный поддельный идентификатор тран-
закции, изменить продолжительный процесс так, чтобы он принимал этот сгенериро-
ванный поддельный идентификатор и обновлял таблицу, записывая его по завершении
работы, благодаря чему реальный идентификатор транзакции связывался с поддельным.
То есть, вместо получения реального идентификатора в результате длительного процес-
са, этот идентификатор становится для процесса входными данными. Во всех "подчи-
ненных" таблицах использовался этот поддельный идентификатор транзакции, а не ре-
альный (поскольку генерации реального надо ждать определенное время). Нам также
пришлось пересмотреть использование этого идентификатора транзакции, чтобы понять,
как это изменение повлияет на другие модули, и так далее.
Еще одна проблема состояла в том, что при синхронной работе, если 45-секундный
процесс завершался неудачно, пользователь узнавал об этом сразу. Он мог устранить при-
чину ошибки (обычно путем изменения входных данных) и повторно выполнить зап-
рос. Теперь, когда транзакции выполняются асинхронно с помощью механизма AQ,
сделать это невозможно. Для поддержки отсроченного уведомления об ошибке пришлось
добавить новые средства. В частности, понадобилось реализовать механизм потоков
заданий для отправки информации о неудавшихся транзакциях соответствующему лицу.
В результате пришлось существенно пересмотреть структуру базы данных. Пришлось
добавить новое программное обеспечение (AQ). Пришлось также создать новые процессы
(управление потоками заданий и другие служебные процессы). К положительным по-
следствиям этих изменений можно отнести не только решение проблемы с архитекту-
рой MTS, но и удобство для пользователя (создавалась видимость более быстрой реак-
ции системы). С другой стороны, все эти изменения существенно задержали завершение
проекта, поскольку проблемы были выявлены лишь непосредственно перед внедрени-
ем, на этапе тестирования масштабируемости. Очень жаль, что приложение сразу не был
правильно спроектировано. Если бы разработчики знали, как физически реализован ме-
ханизм MTS, было бы ясно, что исходный проект не обеспечивает требуемой масшта-
бируемости.
Do'stlaringiz bilan baham: