Глава 30
Использование MTS
Введение
Эта глава посвящена одной из самых перспективных и важных программных технологий — Microsoft Transaction Server (MTS). С одной стороны, MTS — это современный и прогрессивный инструмент для создания многозвенных приложений, который позволяет не только отслеживать транзакции, но и обеспечивает хороший механизм безопасности и стабильность при большой нагрузке. С другой стороны, в полной мере его использовать достаточно сложно: одно дело — теория, другое — практика. Зачастую разработчику сложно определиться в необходимости использования MTS. В каких-то случаях разработчики обходятся без него, а в каких-то предпочитают довериться фирме Microsoft, которая убеждает в огромных преимуществах данного программного продукта. Попробуем разобраться, что на самом деле происходит внутри MTS, что действительно является преимуществом, а что лишними хлопотами, и самое главное — как правильно использовать этот инструмент для реализации полноценных многозвенных приложений.
Для полной ясности сначала определимся с теорией, а затем на практике проверим, что, для чего и как на самом деле можно использовать. Разделим наш рассказ на две логические части. Кто впервые услышал об MTS, тому будет полезно почитать обе части. Тот, кто уже знаком с MTS, может сразу приступить к подробностям, касающимся непосредственно программирования в среде Delphi.
Что такое MTS?
MTS — это среда, которая обеспечивает управление транзакциями, безопасность и пулинг ресурсов и объектов для распределенньк СОМ приложений. Это целый комплекс услуг, которые реализуются через следующие элементы:
MTS Explorer
MTS Explorer — это средство для удобного выставления значений различных параметров, просмотра статистики, пакетов и реальной работы в текущий момент. Умелое его использование может намного облегчить вашу жизнь. Конечно, большинство параметров можно напрямую исправлять в реестре, но неизвестно, что предпочтительнее: копаться непосредственно в реестре, и тогда надо точно знать в какой именно секции какое значение и какому параметру прописать, или в красивом графическом интерфейсе отмечать нужные галочки. Итак, MTS Explorer позволяет:
Координатор распределенных транзакций
Координатор распределенных транзакций (MS DTC) — это служба, которая управляет транзакциями. Впервые она была реализована как часть Microsoft SQL Server 6.5 и затем была включена в MTS, обеспечивая работу с транзакциями на низком уровне, без вмешательства разработчиков. MS DTC использует двухфазное подтверждение для проверки того, что транзакция прошла успешно.
Утилиты MTS
MTS обеспечивает работу в командной строке и через batch-файл. Приведем список утилит, которые поставляются вместе с MTS, с описанием их значения.
Таблица 30.1. Описание утилит MTS
Утилита |
Описание |
MTXSTOP.exe |
Закрывает все процессы MTS. У этой команды есть аналог для выполнения в MTS Explorer |
MTXTEST.exe |
Тестирование маршалинга |
MTXTSTOP.exe |
Останавливает mtxtest . ехе. Этот инструмент не устанавливается по умолчанию и требует дополнительного указания при установке |
SAMPDTCC.exe |
Тестирует MS DTC с простым клиентом |
SAMPDTCS.exe |
Тестирует MS DTC с простым сервером Тестирует конфигурацию настройки параметров Oracle |
MTXREREG.exe |
Обновляет все компоненты, зарегистрированные на компьютере. У этой команды есть аналог для выполнения в MTS Explorer |
MTXREPL.exe |
Дублирует MTS-сервер |
TestOracleXAConfig. exe |
TestOracleXAConfig. exe |
Надо напомнить, что кроме всех выше перечисленных элементов для организации работы с MTS, существуют еще и стандартные средства Windows NT: Event Viewer, Performance Monitor, Server Manager, User Manager for Domains, Windows NT Diagnostics и т. д. И не забудьте, что для их использования вы должны иметь права администратора.
Установка MTS
MTS устанавливается с пакетом Windows NT Option Pack, который распространяется бесплатно фирмой Microsoft. Он поставляется как отдельно, так и в комплекте, например, дистрибутива Visual Studio 98 Enterprise Edition.
MTS поддерживает различные операционные системы: Windows 95/98, Windows NT Workstation и Windows NT Server, а также Windows 2000. MTS является в этом смысле очень гибким, но, если вы создаете серьезное приложение MTS с реализацией всех его преимуществ и достижений, то лучше использовать Windows NT Server. Что касается Windows NT Workstation, то она может заменить Windows NT Server в процессе разработки, но и только; в такой конфигурации MTS поддерживает ограниченное количество клиентов.
В Windows 95/98 вообще невозможно в полной мере создавать MTS-приложения, поскольку в такой конфигурации MTS полностью отсутствует поддержка безопасности.
MTS и Delphi
Уже начиная с четвертой версии Delphi, фирма Inprise ввела в мастерах создания шаблонов элементы, связанные с MTS. Это MTS Object и MTS Data-Module. В этом есть свои минусы и плюсы. Мастера шаблонов, с одной стороны, хороши, так как не надо забивать себе голову понятными и ненужными вещами, а с другой стороны, программирование при этом становится настолько высокоуровневым, что программисту без полной ясности производимых действий сложно работать. Для начала мы остановимся на работе мастеров, в дальнейшем никогда не поздно заняться изучением работы с этими объектами.
Поскольку в мастерах изначально существует два элемента, то сразу возникает вопрос, кому отдать предпочтение. По опыту можно сказать, что уже этот выбор является предметом для дискуссий. Несмотря на необходимость однозначно работать с базами данных, нельзя сразу отказываться от работы с объектом MTS. Потому что может возникнуть необходимость, сначала использовать объект MTS (MTS Object), а потом уже модуль данных MTS (MTS DataModule) или, к примеру, просто удаленный модуль данных (Remote DataModule) или простой модуль данных (DataModule).
Существует некоторая путаница в терминах, когда говорится об объектах и о компонентах в Delphi и в MTS. Термин компонент употребляются как в общем, абстрактном смысле, так при ссылке на объект или класс, происходящий от TComponent. Аналогично термин объект употребляется для обозначения абстрактного понятия основного элемента и конкретного объекта TMTSAutoObject, который наследован от TAutoObject.
Stateful и stateless объекты
Исходя из общих принципов работы MTS, создаваемый объект может быть двух типов: stateful и stateless. Это зависит от конкретной задачи и назначения объекта. Довольно сильно распространено ошибочное мнение о том, что объект обязательно должен быть stateless.
Подобно любому объекту СОМ, объекты MTS могут сохранять внутреннее состояние через многократные запросы клиента. Такой объект имеет тип stateful. Объекты MTS могут быть и типа stateless. Это значит, что объект не хранит никакого промежуточного состояния, пока ждет следующего вызова клиента.
Когда транзакция успешно завершена или прервана, все объекты, вовлеченные в транзакцию, деактивизируются и тем самым теряют информацию о своем состоянии, приобретенную во время транзакции. Это помогает убедиться в изоляции транзакции и согласованности базы данных, а также освобождает ресурсы сервера для использования другими транзакциями. Завершение транзакции позволяет MTS деактивизировать объект и обновить ресурсы.
Сохранение состояния объекта требует от объекта, чтобы тот оставался активным и сохранял такой ценный ресурс как, например, соединение с базой данных. А на практике это значит не что иное, как работу с глобальными переменными, потому что именно в них хранится промежуточное состояние объекта.
Объекты типа stateless наиболее эффективны, а потому и рекомендуемы;но это не значит, что нельзя работать с объектами типа stateful.
Транзакции
Возможность компонента "жить" внутри своей собственной транзакции или быть частью большой группы компонентов, которые принадлежат одной транзакции, является огромным преимуществом MTS. Это позволяет варьировать использование компонента, не перестраивая логику приложения.
Транзакции MTS гарантируют, что:
Клиенты могут использовать прямой контроль над транзакциями с помощью контекста объекта (используя интерфейс ITransactionContext). Однако MTS может и сам для простоты работы клиента управлять транзакциями автоматически.
Пользуясь транзакциями MTS, вы можете использовать бизнес-логику приложения в серверных объектах. Серверные объекты могут осуществлять эти правила таким образом, что клиенту не надо будет ничего знать об этих правилах.
Атрибуты транзакций можно выставлять тремя способами:
Распределитель ресурсов может использовать контекст объекта MTS для обеспечения служб на основе транзакций. Например, объект выполняется внутри транзакции, которая зарезервировала соединение с базой данных, используя распределитель ресурсов DDE. Это соединение автоматически организует транзакцию. Все изменения в базе данных, использующие это соединение, становятся частью транзакции и затем либо принимаются, либо откатываются.
Для возможности объекта MTS участвовать в определении, когда транзакция уже завершена, используются методы интерфейса IObjectContext (табл. 30.2):
Таблица 30.2. Методы интерфейса idbjectContext
Метод |
Описание |
SetComplete |
Указывает на то, что объект успешно завершил свою работу во время транзакции. Объект деактивизируется при завершении работы метода. MTS повторно активизирует объект при следующем вызове, инициированном объектом |
SetAbort |
Указывает на то, что работа объекта никогда не может быть принята. Объект деактивизируется при завершении работы метода. MTS повторно активизирует объект при следующем вызове, инициированном объектом |
EnableCommit |
Указывает на то, что работа объекта не обязательно сделана, но что его изменения могут быть сохранены в текущем виде. Метод позволяет транзакции, в которой участвует вызвавший его объект, быть сохраненной. Он поддерживает внутреннее состояние объекта через многократные вызовы клиентов, пока не буДут вызваны методы SetComplete или SetAbort или пока транзакция на завершится. EnableCommit используется по умолчанию, когда объект активизирован. Именно поэтому объект должен всегда вызывать методы SetComplete или SetAbort перед возвращением из EnableCommit, если вы хотите, чтобы объект поддерживал свое внутреннее состояние до следующего вызова клиента |
DisableCornrtlit |
Указывает на то, что работа объекта неприемлема, и что он не может завершить его работу, пока не получит распоряжения от клиента о дальнейших действиях. Этот метод надо вызывать перед возвращением управления клиенту для поддержания состояния объекта через многократные вызовы клиента. Это предотвращает среду MTS от деактивизации объекта, и обновляет его ресурсы по завершению работы метода. Если вызван метод DisableCommit, и клиент пытается сохранить результаты транзакции до вызова объектом EnableCommit или SetComplete, транзакция будет прервана. Это можно использовать, например, чтобы изменить состояние по умолчанию, когда объект активизирован |
Завершение транзакций по умолчанию происходит через время, указанное в параметре Transaction Timeout, который выставляется для каждого объекта отдельно через MTS Explorer. По умолчанию это время равно 60 секундам. По истечении этого времени, если транзакция не успела завершиться, то она автоматически прерывается MTS.
Безопасность
Одним из удобных сервисов, предоставляемых MTS, является реализация возможности обеспечить доступ к компонентам (и даже к отдельным интерфейсам) в зависимости от прав, которыми обладает клиент. Безопасность MTS состоит из двух частей.
Для приложений, которые требуют более строгой безопасности, контекст объекта использует интерфейс iSecurityProperty, чьи методы позволяют возвращать идентификатор Windows Security iDentifier (SID) для прямого вызова и создания объекта.
Ресурсы
Управление ресурсами
Для управления ресурсами MTS использует три способа:
Активизация Just-in-time
Способность объекта быть деактивизированным и повторно активизированным, пока клиент сохраняет ссылку на него, называется активизацией just-in-time. С точки зрения клиента, только единственный экземпляр объекта существует с момента создания и до полного уничтожения. Действительно, вполне реальна ситуация, когда объект несколько раз активизируется и деактивизируется. Пока объект не используется, клиент может держать ссылку на объект еще некоторое время, не затрагивая ресурсов системы. Когда объект становится неактивным, MTS уничтожает все ресурсы объекта и в том числе, например, соединение с базой данных.
Когда создается объект СОМ как часть среды MTS, также создается соответствующий контекст объекта. Этот контекст объекта существует в течение всего времени жизни соответствующего объекта MTS. MTS использует контекст объекта для сохранения информации о нем при деактивизации. Этот контекст объекта с помощью интерфейса IObjectContext координирует транзакции. Объект СОМ создается в неактивном состоянии и становится активным только после запроса клиента.
Объект MTS становится неактивным при возникновении следующих событий.
Пулинг ресурсов
После освобождения ресурсов при деактивизации, они становятся доступными для других серверных объектов. Таким образом, соединение с базой данных, больше не используемое одним серверным объектом, может быть использовано другим. Этот процесс называется пудингом ресурсов.
Открытие и закрытие соединения с базой данных занимает много времени. MTS использует распределитель ресурсов для обеспечения повторного использования уже существующего соединения с базой данных, вместо того, чтобы создавать его заново.
В среде Delphi распределителем ресурсов является Borland Database Engine (BDE).
Освобождение ресурсов
Обычно освобождение ресурсов объекта делается при помощи вызова методов SetComplete и setAbort после обслуживания запроса клиента. Эти методы освобождают ресурсы, зарезервированные распределителем ресурсов MTS.
Также необходимо освобождать ссылки на другие ресурсы, включая ссылки на другие объекты (и объекты MTS, и контексты объектов) и память, занятую экземплярами компонентов. Этого делать не следует только лишь в случае, если необходимо сохранить информацию о состоянии между вызовами клиентов.
Пулинг объектов
MTS реализует не только пулинг ресурсов, но и пулинг объектов. После деактивизации MTS присваивает значение true свойству CanBepooled, которое указывает на то, что объект может быть заново использован. При таком значении этого свойства объект помещается в пул. Объекты внутри пула доступны для немедленного использования любыми другими запросами клиентов. Только если пул объектов пуст, MTS автоматически создает новый экземпляр объекта. К сожалению, на самом деле пулинг объектов в данной версии MTS (2.0) пока не работает. Но это свойство используется для дальнейшей совместимости.
Распределители ресурсов
Delphi предоставляет для работы два распределителя ресурсов.
Группы разделенных свойств (функция CreateSharedPropertyGroup), которые устанавливают уникальное пространство имен для свойств, которые они содержат. Вы можете записать и считать все свойства этот группы. В дополнение, информация о состоянии может быть разделена среди всех объектов MTS, которые инсталлированы в том же пакете.
Следующий пример показывает, как добавить код для поддержки менеджера разделенных свойств в объекте MTS.
Листинг 30.1 Пример использования менеджера разделенных свойств
unit Uniti;
interface uses
MtsObj, Mtx, ComObj, Project2_TLB;
type
Tfoobar = class(TMtsAutoObject, Ifoobar) private
Group: ISharedPropertyGroup;
protected
procedure OnActivate; override;
procedure OnDeactivate; override;
procedure IncCounter;
end;
implementation uses ComServ;
{ Tfoobar } procedure Tfoobar.OnActivate;
var Exists: WordBool;
Counter: ISharedProperty;
begin
Group := CreateSharedPropertyGroup('MyGroup');
Counter := Group.CreatePropertyf'Counter', Exists);
end;
procedure Tfoobar.IncCounter;
var Counter: ISharedProperty;
begin
Counter := Group.PropertyByName['Counter'] ;
Counter.Value := Counter.Value + 1;
end;
procedure Tfoobar.OnDeactivate;
begin
Group := nil;
end;
initialization
TAutoObjectFactory.Create(ComServer,
Tfoobar,Class_foobar, ciMultiInstance, tniApartment) ;
end.
В этом примере создана группа свойств, которая названа MyGroup и содержит разделенные среди объектов и экземпляров свойства. В этом примере есть разделенное свойство Counter. Оно использует функцию CreateSharedpropertyGroup для создания менеджера группы свойств и самой группы свойств, и затем использует метод createproperty объекта группы для создания самого свойства counter.
Для получения значения свойства надо использовать метод PropertyByName объекта группы.
Все объекты с разделенным состоянием должны быть запущены в одном и том же серверном процессе. Компоненты с разделенными свойствами должны иметь одинаковые атрибуты активизации. Например, если один компонент сконфигурирован на запуск в процессе клиента, а другой в процессе сервера, то эти объекты будут запущены в разных процессах, даже если они инсталлированы в одном пакете.
Компоненты Microsoft Transaction Server (MTS)
Компоненты MTS представляют собой серверы СОМ, активизируемые внутри процесса (in-process servers) и содержащиеся в динамической библиотеке (DLL). Они отличаются от других СОМ-объектов тем, что выполняются в адресном пространстве среды MTS.
Объект MTS
Обычно объекты MTS по своим размерам очень маленькие и используются для раздельных бизнес-функций. Например, MTS-компоненты могут использовать бизнес-правила приложений, обеспечивая наблюдение за состоянием приложения.
Объект MTS можно просмотреть, как и любой другой СОМ-объект. В дополнение к поддержке любого числа СОМ-интерфейсов, он также поддерживает и интерфейс MTS. Как широко известный IUnknown является общим интерфейсом для всех СОМ-объектов, так IObjectControi является общим для всех объектов MTS.
Чтобы создать объект MTS, необходимо запустить мастер создания. Для этого надо выбрать пункт New меню File и затем значок MTS object со страницы Multitier. Первое, что предлагает сделать мастер, это выбрать имя для кокласса, затем тип потоковой модели, тип модели транзакций и флажок генерации кода для управления событиями (рис. 30.1).
Рис. 30.1. Первый этап создания объекта MTS с помощью мастера
Кокласс описывает СОМ-объект, который использует один или несколько интерфейсов и определяет, какой из используемых интерфейсов будет использован по умолчанию (обычно это Dispinterface).
Типы потоковой модели
Мастер создания объекта MTS требует указать тип потоковой модели:
Таблица 30.2. Типы потоков при создании объектов MTS
Тип |
Описание |
Применение |
Single |
Нет поддержки потоков. Все объекты в таком компоненте выполняются в основном потоке. Этот тип такой же, как и у СОМ-объектов по умолчанию |
Очень ограниченная масштабируемость. Компоненты, имеющие плюс к этому еще и тип stateful, могут служить причиной тупиков и блокировок. Можно устранить эту проблему, описав объект типа stateless и вызвав метод SetComplete перед возвращением из него |
Apartment (or Singlethreaded apartment) |
Каждый объект ассоциируется с отдельным потоком, который сохраняется, пока живет объект |
Два объекта могут выполняться параллельно, пока они находятся в различных действиях (activities). Эти объекты могут быть в одном компоненте или в разных компонентах |
Эти типы потоков подобны тем, что определены для СОМ-объектов. Однако из-за того, что среда MTS обеспечивает более сильную поддержку потоков, значение каждого типа немного отличается. Более того, тип Free не применим к объектам, запускаемым в среде MTS, в силу поддержки в MTS так называемых действии (activities). Более подробную информацию про действия MTS см. в разделе "Оптимизация работы с MTS".
Типы транзакций
Мастер создания объекта MTS-требует указать и тип модели транзакции. Всего описаны четыре типа.
Генерация кода событий
При необходимости получить управление событиями MTS-объекта надо выбрать опцию Generate Event support code (рис. 30.1). Мастер автоматически создаст отдельный интерфейс IConnectionPointContainer.
Если изначально неправильно указан тип проекта, то возникает сообщение об ошибке (рис. 30.2), однако при выборе ОК эта библиотека будет автоматически создана.
Рис. 30.2. Сообщение об ошибке в случае, если создаваемый проект не является библиотекой ActiveX
После этого мастер создания сгенерирует файлы (при условии, что сам проект мы назовем projectTest.dpr и основной модуль как unttest.pas):
Мастер создает шаблон исходного текста. Как показывает опыт, следует обратить внимание на следующие принципиальные и важные моменты.
Листинг 30.2 Описание класса в модуле Unttest.pas
TTest = class(TMtsAutoObject, IConnectionPointContainer, ITest) private
{ Private declarations }
FConnectionPoints: TConnectionPoints;
FConnectionPoint: TConnectionPoint;
FSinkList: TList;
FEvents: ITestEvents;
public
procedure Initialize; overrider-protected
{ Protected declarations }
property ConnectionPoints: TConnectionPoints read FConnectionPoints implements IConnectionPointContainer;
procedure EventSinkChangedtconst EventSink: IDnknown); override;
end;
Прежде всего, мастер Delphi по умолчанию использует дуальный интерфейс. Это означает, что объект автоматизации поддерживает позднее связывание во время исполнения через интерфейс IDispatch, а также раннее связывание во время компиляции, которое выполняется через прямой вызов одной из функций в виртуальной'таблице (vrable), являющейся ссылкой на конкретный интерфейс. В дополнение к этому, если вам необходим код событий, то появится наследование еще и от третьего интерфейса.
Далее обратим внимание на значение параметров guid в секции const библиотеки типов
LIBID_ProjectTest: TGUID = '{F56C5B60-C3C1-11D3-BFB6-444553540000}';
IID_ITest: TGUID = '{F56C5B61-C3C1-11D3-BFB6-444553540000)';
DIID_ITestEvents: TGUID = (F56C5B63-C3C1-11D3-BFB6-444553540000)';
CLASS_Test: TGUID = '(F56C5B65-C3C1-11D3-BFB6-444553540000}';
Количество guid может даже в первое время смутить. Но, во-первых, обратите внимание, что все они разные, а во-вторых, для внешней связи с библиотекой необходимо использовать именно GUID от кокласса.
Все дальнейшие изменения необходимо проделывать через редактор библиотеки типов, а затем делать обновление секции implementation.
Модуль данных MTS
Чтобы создать модуль данных MTS, надо запустить мастер создания. Для этого надо выбрать пункт New меню File и затем значок MTS DataModule со страницы Multitier. Первое, что предлагает сделать мастер, это выбрать имя для кокласса, затем тип потоковой модели и тип модели транзакций — то есть все то же самое, что и при создании объекта MTS за исключением генерации кода событий (рис. 30.3).
Рис. 30.3. Первый этап создания модуля данных MTS
Принципиальным отличием модуля данных от простого объекта MTS является то, что модуль данных сразу предоставляет возможность работы с невизуальными компонентами TDatabase, TTabie, TQuery (рис. 30.4), потому как является наследником объекта TRemoteDataModuie, в то время как объект MTS — объекта TAutoObject.
Далее с модулем данных MTS работа ведется точно так же, как и с простым модулем данных, в частности, с использованием дизайнера модуля данных (рис. 30.5).
Рис. 30.4. Внешний вид модуля данных MTS
Рис. 30.5. Дизайнер модуля данных
Тестирование и установка MTS-компонентов
Для правильного тестирования объектов MTS необходимо отключить параметр Transaction TimeOut (поставить значение, равное нулю). Это ничто иное, как измеряемое в секундах время, которое обозначает, как долго данный объект будет оставаться активным. По умолчанию это время равно 60 секундам.
В стадии разработки MTS компонента нельзя его перекомпилировать, пока он находится в памяти. В этом случае появится сообщение об ошибке Cannot write to DLL while executable is loaded. Для избежания этого необходимо с использованием MTS Explorer установить в свойствах пакета параметр Shut down after being idle for 3 minutes, изменив соответственно время . Для этого надо:
Для запуска компонента MTS в отладчике необходимо настроить параметры запуска (рис. 30.6). Для этого надо:
Рис. 30.6. Настройка параметров утилиты для запуска под отладчиком
После этого, расставив в нужных местах точки останова, можно запустить серверный объект и, посылая запросы от клиента, заниматься отладкой приложения.
Группа компонентов, которая запускается в одном процессе, называется пакетом. Каждый пакет запускается в единственном экземпляре исполняемого файла mtx.exe. Это можно увидеть при запуске нескольких пакетов из диспетчера задач на странице Processes.
Для установки MTS-объекта в пакет из Delphi необходимо:
В один пакет можно инсталлировать компоненты из разных библиотек. И компоненты из одной библиотеки могут быть инсталлированы в разные пакеты. Однако один компонент не может быть установлен в несколько пакетов.
Простой пример
После изучения основных принципов и понятий MTS, напишем простой пример, в котором клиент будет запрашивать у сервера информацию о проектах данного работника. Будем использовать стандартный псевдоним IBLocal для примеров, поставляемых с Delphi.
Создание серверной части
С помощью мастера создадим модуль данных MTS, который назовем DMTest (см. рис. 30.5).
В библиотеке типов для интерфейса IDMTest создадим метод Getproject для обработки запроса клиента. Этот метод будет определять, какое число проектов есть у данного работника.
Листинг 30.3 Описание метода GetProject в секции implementation
procedure TDMTest.GetProject(emp_no, number: Integer);
begin
try
quNumberPro.Close ;
quNumberPro.PararnByName('num').Aslnteger:=emp_no;
quNuroberPro.Open;
number: =quNuniberPro. RecordCount;
SetComplete;
Except SetAbort;
End;
end;
Затем скомпилируем этот компонент и установим в пакет Testpack.
Создание клиентской части
В качестве клиента создадим новое приложение в Delphi и назовем его client. Визуально форму организуем следующим образом (рис. 30.7):
Рис. 30.7. Форма клиентского приложения
Связь между сервером и клиентом можно организовывать через различные
Компоненты: TDCOMConnection, TWebConnection, TSocketConnection. Используем в примере компонент связи, работающий с DCOM. Его надо настроить следующим образом (рис. 30.8):
Рис. 30.8. Настройка параметров для компонента TDCOMConnection в клиентском приложении
Обработаем событие нажатия кнопки Считать:
procedure TForml.btnCountClick(Sender: TObject);
begin
СОМ.Connected:=True;
LblNumber.Caption:=IntToStr
(DCOM.AppServer.GetProject(txtEmp_no.Text));
DCOM.Connected:=False;
end;
Итак, когда мы нажимаем на кнопку Считать, компонент связи устанавливает связь с сервером приложения (здесь использован IP-адрес петли, чтобы обращаться к одному и тому же компьютеру в качестве клиента и сервера). После чего клиент получает отклик на вызов метода Getproject. Записав в метку ibiNumber нужную информацию, уничтожаем экземпляр объекта.
Пример создания клиента и сервера в случае распределенной транзакции
При распределенной транзакции в процессе участвуют уже не два компьютера, а более. Создадим пример, в котором добавим помимо возможности определения количества проектов по работнику еще и некоторую дополнительную информацию. Предположим, что эта информация находится в другой базе данных и на другой машине (для удобства будем использовать тот же псевдоним IBLocal).
Для реализации распределенной транзакции необходимо создать еще два серверных объекта. Первый будет отвечать за определение дополнительной информации по проекту (название, описание и тип продукта), а второй — создавать два серверных объекта внутри своих транзакций.
Сначала напишем первый объект. Он создается аналогично объекту из предыдущего примера, только вместо метода Getproject вызовем метод GetDesc, a зля передачи информации о проекте компоненты TClientDataSet и TDataSetProvider (рис. 30.9). В компоненте quGetDesc добавим следующий текст SQL-запроса: select * from project where proj_ id=:proj_ id.
Рис. 30.9. Модуль данных второго объекта
А так выглядит код метода GetDesc:
procedure TDesc.GetDesc(const Proj_id: WideString; Proj_desc: OleVariant) ;
begin try
Database.Open;
quGetDesc.ParamByNaitie(
'proj_id').AsStrmg:=Proj_id;
quGetDesc.Open;
Proj_desc:=DSProvider.Data;
Database.Close;
SetComplete;
except
SetAbort;
end;
Скомпилируем данный объект и установим в тот же пакет TestPack.
Теперь напишем второй объект для управления распределенными транзакциями. Основной объект MTS для организации распределенной транзакции имеет такое описание:
type
TMainObject = class(TMtsAutoObject, IMainObject) private
FDesc:IDesc;
FDMTest:IDMTest;
protected
procedure MainDo(Emp_n,o, number: Integer; const Proj_id: WideString;
Proj_desc: OleVariant); safecall;
{ Protected declarations }
end;
Добавим в проект библиотеки типов двух предыдущих объектов. Для этого следует выбрать в меню Project пункт Import type library (рис. 30.10), далее нажать кнопку Add и выбрать соответствующий файл с расширением *. tlb.
Создадим метод MainDo, который будет реализовывать распределенную транзакцию, вызывая методы двух порожденных серверных объектов:
procedure TMainObject.MainDo(Emp_no, number: Integer;
const Proj_id: WideString; Proj_desc: OleVariant);
var Tr:ITransactionContextEx;
begin Tr:=CreateTransactionContextEx;
01eCheck(Tr.CreateInstance
(CLASS_DMTest,IDMTest,FDMTest)) ;
01eCheck(Tr.CreateInstance
(CIASS_Desc,IDesc,FDesc)) ;
try
FDMTest.GetProject(emp_no,number);
FDesc.GetDesc(proj_id,Proj_desc) ;
Tr.Commit;
except
Tr.Abort;
raise;
end;
end;
Рис. 30.10. Диалоговое окно для добавления в проект библиотеки типов
В начале метода мы создаем контекст транзакции — интерфейс ItransactionContextEx. Этот интерфейс и выполняет всю основную работу. Теперь скомпилируем его и установим в тот же пакет TestPack.
Клиентская часть создается аналогично предыдущему примеру, поэтому воспользуемся готовой.
При тестировании надо вводить два параметра: код работника и код проекта, поэтому к уже существующей форме добавим вторую строку для ввода данных (рис. 30.11) И TDBGrid, TDataSource, TClientDataSet — для отображения данных.
Рис. 30.11. Визуальная форма клиента для тестирования распределенной транзакции
Оптимизация работы с MTS
Написать приложение, использующее MTS, формально просто. Более сложным является грамотное создание приложения, когда оно не только работает, но и приносит максимальный эффект от своей работы, представляя собой воплощение всех достижений MTS. Для этого надо хорошо представлять весь механизм работы с СОМ-объектами и принципы работы транзакций, потому как MTS является комбинацией этих технологий.
Одним из основных принципов работы транзакций является их взаимная изоляция. Для достижения этого многие системы используют различные механизмы блокировок влияния транзакций друг на друга. MTS использует очень сильную систему изоляции транзакций. Пока данные в одной транзакции не будут обработаны, они не будут видны в другой транзакции. Это сильно снижает производительность системы, поэтому необходимо свести время работы каждой транзакции к минимуму и не забывать про такие методы как SetComplete И SetAbort.
Наиболее важным и фундаментальным аспектом программирования для MTS является такое понятие, как действие (activity). Очень часто ему придают слишком маленькое значение, хотя именно из-за неправильной работы с ним возникают некоторые проблемы и трудности. Действие MTS — это множество объектов, которые действуют сообща в интересах единственного клиента. Действие может содержать объекты из разных пакетов. Каждый объект MTS существует только в одном действии, а действие может содержать несколько объектов. Каждая транзакция MTS также существует только в одном действии, хотя действие может содержать несколько транзакций, благодаря такому значению параметра транзакции, как requires new.
Программирование для MTS подразумевает, что объекты MTS не должны разделяться между действиями. Параллельность внутри действия очень опасна, поскольку возможна ситуация, что объект, работающий в интересах одного потока, может попытаться принять транзакцию, пока объект, работающий в интересах второго потока, находится в процессе выполнения работы внутри той же транзакции. Если такая транзакция была бы действительно принята, то это привело бы к принятию частично выполненной транзакции.
В целом можно сделать вывод, что для создания эффективного и хорошо работающего MTS-приложения необходимо очень хорошо представлять весь механизм работы не только СОМ-объектов, но и транзакций, потоков и даже операционной системы.
Резюме
Приложения MTS можно воплотить в жизнь, используя при создании различные комбинации объектов MTS и модулей данных MTS. Все зависит от поставленной задачи и требований к приложению: вариантов очень много. И такое многообразие помогает принять правильное решение при выборе того или иного способа создания MTS приложения.
С помощью MTS реализовано много проектов, которые отличаются простотой реализации, благодаря использованию встроенных механизмов поддержки транзакции, обеспечения безопасности и экономному и эффективному использованию ресурсов. Но эта технология не стоит на месте, а очень бурно развивается. Не успели разработчики еще в полной мере использовать ее в таком варианте, как уже вышла более новая версия. Теперь MTS является встроенным механизмом в Windows 2000 и обладает пудингом объектов, автоматическим распределением нагрузки между серверами и встроенным механизмом организации данных в памяти.