DCOM и Microsoft Transaction Server
Введение
Настоящая статья основывается на материалах докладов, сделанных автором на ежегодной конференции разработчиков DevCon. Учитывая повышенный интерес, проявленный аудиторией к данной тематике, а также возрастающую популярность Microsoft Transaction Server среди разработчиков многоуровневых систем несмотря на сравнительную "молодость" продукта, было бы целесообразно, на мой взгляд, немного более подробно остановиться на назначении и функциональных возможностях Microsoft Transaction Server, опуская, по мере возможности, специальные технические вопросы, затронутые в докладах, так как представляется гораздо более важным дать читателю общее видение продукта и его место в современной компонентной модели построения программного обеспечения, нежели дублировать документацию. Пользуясь случаем, я хотел бы поблагодарить многочисленных участников конференции DevCon'97, чьи вопросы во многом определили содержание данной статьи, и главного редактора издания "Технология клиент-сервер Клиент-сервер (англ.Client-server)— вычислительная или сетевая архитектура, в которой задания или сетевая нагрузка распределены между поставщиками услуг (сервисов), называемыми серверами, и заказчиками услуг, называемыми клиентами. Нередко клиенты и серверы взаимодействуют через компьютерную сеть и могут быть как различными физическими устройствами, так и программным обеспечением." В.Ю.Чистякова за ценное обсуждение ряда аспектов использования Microsoft Transaction Server и предоставленную возможность рассказа о них.
1. Стратегия распределенных вычислений. Краткий экскурс в историю.
Идея повторного использования кода не является чем-то принципиально новым в мире разработки программного обеспечения. Как известно, лень - двигатель Двигатель, мотор (от лат.motor приводящий в движение)— устройство, преобразующее какой-либо вид энергии в механическую. Этот термин используется с конца XIX века наряду со словом «мотор», которым с середины XX века чаще называют электродвигатели и двигатели внутреннего сгорания (ДВС). прогресса (J). Если смотреть на вещи с несколько философской точки зрения, то все развитие Развитие— необратимый закономерный процесс, направленный на изменение материальных и идеальных объектов. Изменение материи и сознания, их универсальное свойство, всеобщий принцип объяснения истории природы, общества и познания. человеческой цивилизации обусловлено возможностью основываться на результатах труда предшествующих поколений, расширяя и совершенствуя эту базу, в свою очередь, для наших потомков. Нет ничего удивительного поэтому, что попытки внедрения подобного подхода в области программных технологий предпринимались, наверное, еще на заре развития программирования. (Мы заведомо абстрагируемся от тех вырожденных случаев, когда условия оплаты заведомо подталкивали программистов к изобретению велосипеда и проч.) Сначала это, вероятно, был примитивный перенос кусков кода, который упростила директива #include, затем с появлением процедурных языков это стали библиотеки процедур, наконец, по мере того, как объектная парадигма Парадигма (от греч. , «пример, модель, образец»)— совокупность фундаментальных научных установок, представлений и терминов, принимаемая и разделяемая научным сообществом и объединяющая большинство его членов. Обеспечивает преемственность развития науки и научного творчества. овладела умами и чаяниями разработчиков средств разработки, их место в значительной степени заняли классы Класс (от лат.classis— группа) в классификации— группа предметов или явлений, обладающих общими признаками. и библиотеки классов. Собственно говоря, перенесение основных свойств объектов окружающего нас мира в ту его прекрасную часть, которая относится к разработке софта,- возьмем хотя бы наследование- уже было подчинено идее переиспользуемости. Однако ни процедуры, ни классы не позволяли в полной мере воспользоваться преимуществами наследования от уже разработанных независимых модулей при создании достаточно сложного проекта, в особенности, если его предполагалось растиражировать для большого числа заказчик Заказчик — лицо (физическое или юридическое), заинтересованное в выполнении исполнителем работ, оказании им услуг или приобретении у продавца какого-либо продукта (в широком смысле). Иногда при этом предполагается оформление заказа, но не обязательно.ов. Основным препятствием была практическая невозможность установить новую версию библиотеки без ущерба для приложений, написанным с учетом предыдущих версий API. В общем случае это влекло за собой повторную компоновку, а то и компиляцию проекта, что вынуждало поставщика программного решения передавать клиенту не только исполняемые или (в крайнем случае) объектные модули, но и исходные тексты программ. Во-первых, очевидно, что это отнюдь не способствовало охране интеллектуальной собственности авторов, а во-вторых, даже эти жертвы становились напрасны, если клиент вдруг решал использовать средства разработки иного производителя. Благим намерениям создателей С как некоего не зависящего от платформы стандарта языка программирования не суждено было сбыться, и со временем рынок ПО захлестнула волна компиляторов С/С++, для каждого из которых, как водится, немедленно возникли толпы поклонников, готовых истово отстаивать, что их любимый компилятор именно этой фирмы является самым компилятором в мире. На сегодня это число заметно уменьшилось, и страсти сами собой улеглись- речь не об этом. К несчастью, С++ не является единственным объектно-ориентированным языком, и если не столь долгое время назад заказчик желал, чтобы приобретенные у вас компоненты, написанные на том же С++, интегрировались в среду его "домашних" разработок, скажем, на Pascal'e, то это была далеко не тривиальная задача, где не спасали ни исходники, ни их косметическая правка. Таковы примерно были факторы, которые в конце концов привели к идее создания новой технологии и выработке стандартов, позволяющих избежать зависимости от конкретного средства разработки компонент и проводить эффективное обновление версий без негативных последствий для связанных с ними модулей. Реализация этой технологии, выполненная корпорацией Microsoft, получила название модели компонентных объектов (COM).
2. Модель компонентных объектов. Основные понятия.
Художник не рисует картину по пикселам. Сначала на холст ложатся грубые штрихи, и только потом наступает прорисовка деталей. Идея компонентного подхода в программировании возникла одновременно с программированием, поскольку она соответствует, если можно так выразиться, естественной модульности аналитического мышления, когда решение достаточно объемной задачи начинается с ее разбиения на несколько подзадач, те, в свою очередь, дробятся на еще более мелкие и иерархически более зависимые фрагменты и т.д. вплоть до тех деталей, решение которых элементарно. По той же причине компоненты упрощают отладку приложения- вспомните поиск корня методом половинного деления. Более того, сборка из независимых компонент существенно увеличивает масштабируемость Масштабируемость (англ.scalability) — в электронике и информатике означает способность системы, сети или процесса справляться с увеличением рабочей нагрузки (увеличивать свою производительность) при добавлении ресурсов (обычно аппаратных). Масштабируемость — важный аспект электронных систем, программных комплексов, систем баз данных, маршрутизаторов, сетей и т. п., если для них требуется возможность работать под большой нагрузкой. Система называется масштабируемой, если она способна увеличивать производительность пропорционально дополнительным ресурсам. Масштабируемость можно оценить через отношение прироста производительности системы к приросту используемых ресурсов. Чем ближе это отношение к единице, тем лучше. Также под масштабируемостью понимается возможность наращивания дополнительных ресурсов без структурных изменений центрального узла системы., так как в зависимости от требуемой функциональности мы можем добавить в него те или иные компоненты или, наоборот, изъять так, чтобы приложение не обрушивалось, а плавно и корректно деградировало. Мы можем физически "размазать" приложение по сети, установив разные компоненты на разные компьютеры, и снова повысить тем самым масштабируемость, но уже в плане производительности. Наконец, компоненты универсальны, как атомы или гены: компоненты, из которых состоит ваше приложение, в различных сочетаниях с другими компонентами могут использоваться при построении новых приложений, т.е. именно благодаря им суждено сбыться вековой мечте человечества о повторной используемости кода, с которой мы начали наш рассказ. Итак, компоненты- это круто. Теперь несколько слов о том, как это все работает.
Распределенная компонентная модель объектов (DCOM)- это (см.[1]) набор стандартов построения, размещения и взаимодействия компонент и реализующих их механизмов, которые позволяют объектам внутри компонент посылать вызовы другим компонентам, а также принимать и обрабатывать запросы от других компонент вне зависимости от их положения на компьютере или в сети, от способов реализации, от того, являются ли они прикладными или объектами операционной системы и т.д. Для этого объекты (D)COM "договариваются" о предоставлении друг другу сервисов через строго определенные интерфейсы, которые на идеологическом уровне можно рассматривать как своего рода обязательство Обязательство— относительное гражданское правоотношение, в силу которого одна сторона (должник) обязана совершить в пользу другой стороны (кредитора) определённые действия или воздержаться от определённых действий. Такими действиями являются: передача определённого имущества, выполнение работы, уплата денег, а также другие действия. Кредитор, в пользу которого должно быть совершено такое действие, имеет право требовать от должника исполнения его обязанности. объекта предоставить заявленную функциональность при условии вызова в соответствии с опубликованными им правилами, а на бытовом- как группы семантически связанных функций, объединенных в абстрактные виртуальные классы. Пусть, например, имеем некоторый набор функций, оформленный в виде
struct I1
{
virtual void f11()=0;
virtual int& f12()=0;
...
}
Любой класс, намеренный использовать эту функциональность, может быть оформлен, например, в виде наследования:
class AnyCls : public I1 ...
Однако, что предпринять, если нам потребовалось расширить набор функций? Переписать struct I1 означает вернуться к проблемам, описанным в п.1. Следовательно, логично будет свести дополнительные функции в новый интерфейс:
struct I2
{
virtual void f21()=0;
...
}
А как быть тогда с AnyCls? Интерфейсов может не один и не два, а множественное наследование выручает до известного предела, после которого возникают разного рода проблемы, начиная от слабой читаемости программы и заканчивая потерями в производительности. Решение состояло в использовании вложенных классов:
class AnyCls
{ protected: ...
public:
AnyCls {...;}
class C1 : public I1
{ public:
C1() {}
virtual void f11();
virtual int& f12();
...
} m1;
class C2 : public I2
{ public:
C2() {}
virtual void f21();
...
} m2;
...
}
void AnyCls::C1::f11(){ ... ;}
... , которые, с одной стороны, упакованы в родительском классе и не видны за его пределами, а с другой, имеют доступ к его элементам. Заметим, что с помощью функций CoCreateInstance или IUnknown::QueryInterface (см.ниже) клиент работает только с указателями на таблицы виртуальных функций интерфейсов, т.е. реально создав объект того же класса AnyCls, он тем не менее не имеет указателя на него. Таким образом он никогда не получает прямого доступа к внутренним данным объекта, даже если бы они не были protected. Моделированию на С++ основных механизм Механизм (греч. mechan— машина)— это совокупность совершающих требуемые движения тел (обычно— деталей машин), подвижно связанных и соприкасающихся между собой. Механизмы служат для передачи и преобразования движения.ов работы COM посвящена, например, [2], часть IV и желающие всегда могут обратиться к этой литературе, а также к [3], которая по справедливости считается основополагающей работой в области компонентного подхода, до сегодняшнего дня не утратившей своей актуальности.
Интерфейсы являются настолько основополагающим понятием COM, что для их описания используется специальный язык- IDL (язык определения интерфейсов), по своей структуре очень похожий на С++. В определении интерфейса описываются заголовки входящих в него функций с указанием их имен, возвращаемых типов, входных и выходных параметров, а также их типов. Это и есть та часть контракта, которая будет сообщать, что может и как надо вызывать объект, взявший на вооружение Вооружение— это комплекс технических средств или технологических процессов, предназначенных для поражения живой силы и объектов инфраструктуры противника. данный интерфейс. Каждый интерфейс получает свой 16-байтовый глобальный идентификатор, который присваивается ему программой генерации на основании времени создания, адреса сетевой платы и пр. После опубликования интерфейс фиксируется и дальнейшие изменения в нем не допускаются. IDL допускает наследование, так что возможны производные интерфейсы. Более того, все интерфейсы являются производными от одного базового интерфейса под названием IUnknown. В состав IUnknown входят 3 метода. QueryInterface используется для получения указателей на другие интерфейсы объекта, при условии, что указатель на начальный интерфейс был получен при помощи CoCreateInstance. Методы Метод (от др.-греч. — путь)— систематизированная совокупность шагов, действий, которые необходимо предпринять, чтобы решить определённую задачу или достичь определённой цели. В отличие от области знаний или исследований, является авторским, то есть созданным конкретной персоной или группой персон, научной или практической школой. В силу своей ограниченности рамками действия и результата, методы имеют тенденцию морально устаревать, преобразовываясь в другие методы, развиваясь в соответствии с временем, достижениями технической и научной мысли, потребностями общества. Совокупность однородных методов принято называть подходом. Развитие методов является естественным следствием развития научной мысли. AddRef и Release применяются для подсчета ссылок, т.е., грубо говоря, сколько клиентов в данный момент используют интерфейсы данного объекта. AddRef выполняется автоматически, как только со стороны клиента поступает запрос на указатель интерфейса. Однако если внутри клиентской программы происходит порождение новой ссылки на интерфейс, о которой серверный объект не догадывается, вызов AddRef возлагается на клиента. Клиент не имеет права разрушить серверный объект, но по окончании работы с ним он обязан вызвать метод Release, который уменьшит на единичку число пользователей объекта. Когда оно станет равным 0, объект сам себя уничтожит.
В том случае, если объект создан как in-process сервер (dll), т.е. выполняется внутри клиентского процесса, особых проблем не возникает. Если же объект реализован в виде out-of-process сервера, выполняющегося как отдельный процесс на том же или удаленном хосте, немедленно появляется вопрос о передаче указателя на интерфейсы и параметров вызовов методов между процессами. Вопрос нетривиальный тем более потому, что различные компьютеры могут использовать разные форматы представления данных. Ответ состоит в использовании proxy-объекта внутри клиентского процесса и заглушки внутри сервера. Proxy- это обычный COM-объект, который представляет те же интерфейсы, что и вызываемый клиентом, однако вместо непосредственного вызова методов он принимает переданные клиентом параметры и упаковывает их для передачи средствами межпроцессной или межмашинной (RPC- remote procedure call) коммуникации. Заглушка на стороне сервера принимает и распаковывает эти параметры, вызывает соответствующий метод серверного объекта и передает их ему. Возвращение результатов клиенту происходит по той же схеме в обратном направлении. Такой процесс называется маршалингом (демаршалингом). Обычно все развитые средства разработки COM-объектов предоставляют возможность Возможность — направление развития, присутствующее в каждом явлении жизни; выступает и в качестве предстоящего, и вполне объяснимо рациональным путем: в каждой возможности присутствует вероятная невозможность, «возможность невозможного». Возможность не определяется познанием того, что может быть. Познание вероятностей, возможностей не всегда влияет на нашу возможность. На изучении возможности основывается, главным образом, исследование бытия и события. автоматической генерации proxy и заглушки для интерфейса. Если разработчика по каким-то причинам это не устраивает, он может запрограммировать нестандартный маршалинг при помощи определенного в COM интерфейса IMarshal. Возникает интересный момент: если код маршалинга способ Метод (от греч. — «способ»)— систематизированная совокупность шагов, действий, которые необходимо предпринять, чтобы решить определенную задачу или достичь определенной цели. В отличие от области знаний или исследований, является авторским, то есть созданным конкретной персоной или группой персон, научной или практической школой. В силу своей ограниченности рамками действия и результата, методы имеют тенденцию морально устаревать, преобразовываясь в другие методы, развиваясь в соответствии с временем, достижениями технической и научной мысли, потребностями общества. Совокупность однородных методов принято называть подходом. Развитие методов является естественным следствием развития научной мысли.ен автоматически создаваться на стадии компиляции программы, то почему бы не использовать эту возможность для динамической генерации маршалеров во время выполнения программы? Такой подход (он известен как позднее связывание), несмотря на дополнительные затраты, существенно повышает гибкость программирования, ибо решение о вызовах тех или иных интерфейсов может приниматься по ходу дела в зависимости от прикладной логики. Однако для этого клиент должен "на лету" уметь получать доступ к информации об интерфейсах, необходимой для выполнения маршалинга. Этим требованиям отвечает библиотека Библиотека (греч. , от «книга» и «место хранения») — учреждение, собирающее и хранящее произведения печати и письменности для общественного пользования, а также осуществляющее справочно-библиографическую работу. В настоящее время всё более распространяются и входят в фонд библиотеки микрофиши, микрофильмы, диапозитивы, аудио- и видеокассеты, также всё более широкое распространение получают электронные носители (CD-ROM, DVD-ROM). типов, которая перечисляет все интерфейсы, поддерживаемые тем объектом, для которого она создается, и описывается в терминах уже упоминавшегося нами выше IDL. Как и для COM-объектов, при установке в registry записывается ID библиотеки и ее местоположение. При вызове средствами СОМ API библиотека типов предоставляет интерфейс ITypeLib, который, в свою очередь, позволяет получить указатели на интерфейс ITypeInfo для каждого интерфейса, перечисленного в библиотеке, с помощью которых добывается информация о параметрах методов и их типов, необходимая для динамического маршалинга.
Обычно основным потребителем этой информации оказывается интерфейс IDispatch (естественно, производный от IUnknown), который наверняка знаком программистам на Visual Basic. Методы этого интерфейса GetTypeInfo и GetTypeInfoCount позволяют динамически запрашивать запущенный объект относительно информации о всех его интерфейсах. Другой метод, IDispatch::Invoke фактически представляет собой оператор switch, который в зависимости от переданного значения идентификатор Идентификатор, ID (англ.data name, identifier — наименование данных) - это уникальный признак объекта, позволяюший различать объекты и/или объект по идентификатору.а (DISPID) вызывает тот или иной метод диспинтерфейса. Иногда в литературе можно встретить суждение, что Visual Basic не работает с указателями, поэтому для него потребовалось создать некий универсальный механизм, умеющий работать только с одним интерфейсом IDispatch. Это не совсем корректное замечание. Во-первых, в свете нашего разговора о маршалинг Маршалинг (от англ.marshal— упорядочивать), по смыслу похож на сериализацию, в информатике— процесс преобразования представления объекта в памяти в формат данных, пригодный для хранения или передачи. Обычно применяется, когда данные необходимо передавать между различными частями одной программы или от одной программы к другой.е очевидно, что единственная пара proxy-заглушка для IDispatch не в состоянии предусмотреть преобразование параметров для самых различных методов диспинтерфейса, поэтому часть преобразования неявно выполняет сам клиент, упаковывая параметры в variant. Во-вторых, только первая версия Visual Basic распознавала исключительно диспинтерфейсы. Во всех остальных случях QueryInterface совершенно аналогично возвращает указатель на виртуальную таблицу, содержащую реализацию запрашиваемого интерфейса. В терминах Visual Basic это известно как объектная ссылка (object reference). Т.е., если переменная объявлена как dim x As <Something>, где <Something>№ Object, то будет использоваться раннее связывание. В первую очередь компилятор (VB5) будет искать способы прямого вызова через виртуальную таблицу (vtable Таблица виртуальных методов (англ.virtual method table, VMT) — координирующая таблица или vtable — механизм, используемый в языках программирования для поддержки динамического соответствия (или метода позднего связывания). binding) и только в случае неудачи прибегнет к диспинтерфейсу. При этом по информации в библиотеке типов он постарается найти DISPID и кэшировать его, чтобы сэкономить на достаточно дорогом вызове GetIDsOfNames в период выполнения. При ссылках типа dim x As Object или Set x = y, где создание объекта y происходит во время работы программы, компилятор, естественно, лишен возможности сделать какие-либо предположения о природе объектов х и не сможет оптимизировать их вызовы. В этом случае, как нетрудно догадаться, будет иметь место позднее Позднее (укр. Пізнє) — село в Козелецком районе Черниговской области Украины. Население 25 человек. Занимает площадь 0,203 км. связывание. Позднее связывание преимущественно характерно для Visual FoxPro 5.0, в него также включена оптимизация для поддержки vtable binding- см. функцию sys(2333). Иногда интерфейсы описываются как двойственные, т.е. содержащие диспинтерфейсные представления для виртуальных таблиц своих методов.
Одним из ярких проявлений преимуществ компонентной модели служит OLE-автоматизация, или программируемость, тесно связанная с двойственными и диспинтерфейсами. OLE-автоматизация явилась одним из этапов развития COM, и практически каждый наверняка с ней сталкивался. Речь идет о том, что при всей полноте своей функциональности приложение будет представлять еще большую ценность Ценность — значимость (польза, полезность) некоторого множества объектов для множества живых существ. для разработчиков, если позволит использовать эту функциональность не только в интерактивном режиме, но и из пользовательских программ. Вместо того, чтобы снабжать приложение дополнительным API для этих целей, автор может просто оформить его как OLE Automation сервер, что приблизительно означает, что приложение сознательно "засвечивает" вовне некоторые из своих методов, использовавшихся для внутренней реализации заявленной функциональности. При этом, во-первых, достигается экономия Столовое имение (польск. dobra stoowe, белор. сталовы маёнтак)— в Речи Посполитой переданное в личную собственность монарха государственное имение, обеспечивающие доходом королевский престол. Позже были переименованы в «экономии». По-русски также применяется термин "королевские имения". программистского труда: автору не нужно сначала разрабатывать приложение, а потом писать API к нему. Во-вторых, пользователь мыслит в тех же категориях, что и автор, что значительно облегчает освоение программы. В третьих- и это плюс, характерный для всей технологии COM,- предоставленная функциональность остается на вооружении пользователя при разработке им каких-то своих программ, никак не связанных с данным OLE Automation сервером. Простой пример: если у нас на компьютере установлен Microsoft Office, то зачем нам изобретать велосипед и писать программу проверки орфографии, если мы можем создать объект Word.Application и вызвать для него метод SpellChecking:
dim x As New Word.Application
Debug.Print x.SpellChecking("Abra Cadabra")
...
То же самое относится, например, к использованию статистических функций Microsoft Excel и т.д. В качестве OLE Automation серверов могут рассматриваться не только офисные приложения, но и сами средства разработки- тот же Visual Basic или Visual FoxPro- и даже тяжелые серверные продукты семейства Microsoft BackOffice, например, Microsoft SQL Server, который с помощью SQL-DMO (distributed management objects) обеспечивает выполнение практически всех административных функций из клиентского приложения (разумеется, при наличии соответствующих прав доступа).
dim oSQLServer As New SQLOLE.SQLServer
oSQLServer.Connect "ntalexejs", "sa"
dim newdb As New SQLOLE.Database
newdb.Name = "sqlole"
newdb.ExtendOnDevices ("oledat=5")
newdb.TransactionLog.DedicateLogDevices ("olelog=2")
oSQLServer.Databases.Add newdb
3. Interface'ом об table, или компонентный подход в базах данных
Примерно в это же время, а может быть, несколько раньше, разработчики СУБД столкнулись с необходимостью поддержки неструктурированных типов данных: мультимедиа Мультимедиа — это взаимодействие визуальных и аудиоэффектов под управлением интерактивного программного обеспечения с использованием современных технических и программных средств, они объединяют текст, звук, графику, фото, видео в одном цифровом представлении., геопространственная информация, папки электронной почты и т.д. С идейной точки зрения, не принимая в расчет вопросов технической реализации, решение, казалось бы, лежит на поверхности: переписать заново или переработать ядро своего сервера баз данных, сделав его объектно-реляционным и включив туда поддержку новых типов наравне с традиционной информацией. Выигрыш очевиден: мы снова получаем единый API и полный контроль над данными и их изменениями. К сожалению, минусов при таком подходе оказывается больше, чем плюсов. Во-первых, требуется перекачка информации из исходных мест ее хранения в базу данных, где она будет обрабатываться, преобразовываться и возвращаться обратно. Естественно, это не лучшим образом сказывается на производительности и надежности. Во-вторых, выполнение запросов очень трудно поддается оптимизации, так как правила их обработки сильно зависят от типов данных. В-третьих, схема носит закрытый характер и оттого не является привлекательной в глазах разработчиков независимых приложений. Наконец, не вполне понятно, что делать, когда возникнет нужда в поддержке новых типов данных,- снова переписывать ядро? Поэтому следующим этапом стало проектирование универсальных серверов баз данных, где процедуры обработки неструктурированной информации обладали возможностью гибко встраиваться в технологию работы исполнительного механизма СУБД. В одном случае такие процедуры были оформлены как динамические библиотеки и работали в том же процессе, что и ядро универсального сервера, в другом- как самостоятельные процессы. При этом часть процедур отвечала за поддержку дополнительных типов данных, которые наряду с традиционными хранились в базе, а часть (во взаимодействии с сетевым сервером приложений) - за их обработку. В скором времени между приверженцами этих двух направлений разгорелась война не на шутку, которая вышла за пределы соревнования Соревнование — противоборство и конкурентная борьба между несколькими сторонами за достижение превосходства, (выигрыша, признания ит.п.) или в целях поддержки биологического инстинкта выживания. Термины соревнование, соревновательность широко используются в различных областях наук и направлениях человеческой деятельности, таких как биохимия, экология, экономика, бизнес, политика и спорт. технологий и переместилась на придорожные рекламные щиты и в отделы по найму персонала. Первый подход критиковался с точки зрения надежности, так как чисто теоретически можно допустить, что случайная ошибка в процедуре способна вывести из строя весь процесс, т.е. ядро СУБД, тем более, что право на написание встраиваемых модулей было также даровано независимым фирмам. Второй Второй — второй по счёту альбом песен Владимира Высоцкого в исполнении Григория Лепса, записанный и вышедший в 2007 году подход в силу изоляции процессов друг от друга выглядел более надежным, но по той же причине подвергался критике с точки зрения производительности. В последнее время достаточной популярность Популярность(от лат.populares, от populus — народ) — высокая степень востребованности чего-либо или кого-либо в определенной области жизни человека, например: популярность сетевых игр. На возникновение популярности в некоторых случаях влияет мода, и наоборот. Так же, как и мода, популярность привязана к определенному и, как правило, небольшому отрезку времени. Популярность зачастую смешивают с известностью, хотя это не одно и то же.ю пользуется идея компонентного подхода, когда данные не переносятся в базу, а используются по месту их непосредственного хранения. Для каждого типа данных существует компонент, который мы назовем, скажем, провайдером OLE DB и который по своему принципу работы напоминает хорошо известные ODBC-драйверы, с той лишь разницей, что он умеет обращаться к данным не обязательно реляционной природы. Каждый такой компонент "знает", как обеспечить доступ к своему типу и представляет для этого необходимые (стандартные) интерфейсы. В результате способы представления информации оказываются прозрачными для потребителя, и он сможет в одном операторе select SELECT ("селект") — оператор DML языка SQL, возвращающий набор данных (выборку) из базы данных, удовлетворяющих заданному условию. запрашивать, например, информацию из различных баз данных, электронных таблиц, документов, электронной почты, файловой системы Система (от др.-греч. — «сочетание»)— множество взаимосвязанных элементов, обособленное от среды и взаимодействующее с ней, как целое. и т.п.
Проникновение компонентных технологий в область баз данных было даже в какой-то степени обусловлено исторически. Перенесемся буквально на несколько лет назад, и мы попадем в эпоху расцвета персональных настольных СУБД a la xBase, где пользовательский интерфейс, средства программирования бизнес-логики, обеспечение целостности схемы хранения данных- все было заключено внутри одного продукта. За относительно недолгое время необходимость корпоративной работы над проектом, рост объемов хранимой и перерабатываемой информации и многое другое привели к внедрению клиент-серверных систем, где на сервер базы данных возлагалась ответственность за безопасность хранения и доступа к данным, поддержку их транзакционной целостности, обеспечение пользовательских соединений и многое другое. На клиенте, соответственно, остались пользовательский интерфейс и какая-то часть бизнес-логики. Вообще, бизнес-логика на сервере начинается с момента проектирования базы данных, и потому лично для меня вполне разумным представляется стремление Желание или вожделение— средняя степень воли, между простым органическим хотением, с одной стороны, и обдуманным решением или выбором— с другой. сосредоточить как можно большую ее часть в триггерах, хранимых процедурах и т.п. Клиент-серверные системы получили широкое признание «Признание»— кинофильм. Фильм основан на реальных событиях. Не рекомендуется просмотр детям и подросткам моложе 16 лет. и распространение вплоть до уровня масштабных корпоративных и общегосударственных проектов. Невероятно разрослась и усложнилась бизнес-логика, она перестала умещаться внутри сервера базы данных. Плюс к тому продолжали оказывать влияние те самые тенденции, которые обусловили переход от персональных баз к клиент-серверным система Система (от др.-греч. — «сочетание»)— множество взаимосвязанных элементов, обособленное от среды и взаимодействующее с ней, как целое.м: увеличение объемов данных, транзакционной нагрузки, числа одновременных пользовательских коннектов и т.д. В итоге на клиенте остался интерфейс, на сервере баз данных- его типичные функции типа поддержки целостности схемы, резервное копирование, тиражирование, а все, что относилось к бизнес-логике, выделилось в самостоятельное промежуточное звено (middlware). Не успели утихнуть восторги по поводу того, как классно стало жить теперь нам всем, как выяснилось, что новое- это хорошо забытое старое, за все приходится платить, и вместе с бизнес-логикой на хрупкие плечи разработчиков среднего звена ложится обязанность программирования безопасности доступа, управления потоками, обработки транзакций, обеспечения необходимого быстродействия и масштабируемости и много чего еще, с чем раньше благополучно справлялся сервер баз данных. Более того, столь тесное переплетение системного и прикладного программирования не только удлинило сроки разработки и подняло примерно вполовину стоимость такого проекта, но, что еще более печально, увеличило зависимость результатов от конкретного проекта и сделало практически невозможным повторное использование наработок в этой области. В этом месте оставалось бы вздохнуть, развести руками и поставить точку, но я с детства не люблю сказок с несчастливым концом, поэтому в нашем повествовании появляется новое действующее лицо- Microsoft Transaction Server.
4.Microsoft Transaction Server
18 мая в рамках проходившего в Нью-Йорке Дня Масштабируемости демонстрировалась работа гипотетической банковской системы, клиентами которой являлась примерно четверть населения земного шара. Общая база данных находилась под управлением 20-ти серверов Microsoft SQL Server 6.5 на платформе Compaq. Еще 20 компьютеров имитировали деятельность со стороны клиентов. Диспетчеризацию клиентской нагрузки и управление транзакциями выполняли 5 серверов Microsoft Transaction Server (MTS). За день система смогла обслужить миллиард(!) транзакций, из которых значительная доля пришлась на долю распределенных (т.е. проходящих через несколько серверов баз данных).
Microsoft Transaction Server 1.0 был выпущен в декабре прошлого года и в традиционном понимании является сервером поддержки работы приложений, составляющих ПО промежуточного слоя. Он осуществляет автоматическое управление процессами и потоками, имеет встроенные службы безопасности для контроля вызовов и использования объектов, обеспечивает поддержку распределенных транзакций по протоколу двухфазной фиксации OLE 2PC и интеграцию с MS DTC, предоставляет графический интерфейс для регистрации и управления компонентами (MTS Explorer), т.е. фактически предоставляет готовые средства решения задач системного программирования, которые, как мы отметили выше, неизбежно возникают при разработке middleware. С этой стороны положительный аспект применения MTS заключается в том, что при разработке компонент не нужно программировать вручную реакцию на разнообразные исходы в системе. Воспользуемся одним из примеров в составе MTS и рассмотрим класс Account компоненты Bank. Он имеет метод Post для дебитования или кредитования определенного банковского счета. Однако, как правило, банковская операция означает дебет одного счета и кредит другого. Вопрос: сколько дополнительного программирования потребуется, чтобы вызов двух методов в программе на VB, VC++ и т.д. выполнялся как одна транзакция? С использованием MTS решение становится тривиальным.
Bank.MoveMoney
dim ctxObject As ObjectContext
Set ctxObject = GetObjectContext()
...
On Error GoTo ErrorHandler
dim objAccount As Bank.Account
Set objAccount = ctxObject.CreateInstance("Bank.Account")
...
objAccount.Post(lngSecondAccount, lngAmount)
objAccount.Post(lngPrimeAccount, 0 - lngAmount)
...
ctxObject.SetComplete
...
ErrorHandler:
ctxObject.SetAbort
...
Мы значительно сократили и упростили текст примера, оставив в нем иллюстрацию самых базовых моментов. Первое, на что нужно обратить внимание- это объект ctxObject, который носит название "контекст объекта". Каждый объект, размещенный в MTS, автоматически получает в соответствие такой объект на все время своей жизни. Контекст объекта управляет участием объекта в транзакция Транзакция (англ.transaction)— в информатике, группа последовательных операций, которая представляет собой логическую единицу работы с данными. Транзакция может быть выполнена либо целиком и успешно, соблюдая целостность данных и независимо от параллельно идущих других транзакций, либо не выполнена вообще и тогда она не должна произвести никакого эффекта. Транзакции обрабатываются транзакционными системами, в процессе работы которых создаётся история транзакций.х под контролем MTS (см., например, методы SetComplete и SetAbort в примере) и предоставляет средства для программной проверки безопасности. Например, если поступает запрос на перевод Перевод— деятельность по интерпретации смысла текста на одном языке (исходном языке [ИЯ]) и созданию нового, эквивалентного текста на другом языке (переводящем языке [ПЯ]). крупной суммы, мы можем предусмотреть проверку на наличие у него соответствующих прав:
If (lngAmount > 500 Or lngAmount < -500) Then
If Not ctxObject.IsCallerInRole("Managers") Then
Err.Raise Number:=ERROR_NUMBER, ...
Description:= "Need 'Managers' role for amounts over $500"
End If
End If
Установка самих ролей происходит в MTS Explorer. Ccылку на контекст объекта можно получить с помощью функции MTS API GetObjectContext(). В данном примере мы создаем объект Account от контекста объекта MoveMoney, в результате чего он будет выполняться внутри той же транзакции, что и объект MoveMoney. В общем случае это зависит от транзакционного атрибута компоненты, под которым она установлена в MTS. Возможны 4 варианта: supported- при создании нового объекта его контекст наследует клиентскую транзакцию, если же клиент исполняется вне транзакции, то новый контекст тоже не будет транзакционным; required- то же, что и в предыдущем случае, но в случае отстутствия транзакции Транзакция (англ.transaction)— в информатике, группа последовательных операций, которая представляет собой логическую единицу работы с данными. Транзакция может быть выполнена либо целиком и успешно, соблюдая целостность данных и независимо от параллельно идущих других транзакций, либо не выполнена вообще и тогда она не должна произвести никакого эффекта. Транзакции обрабатываются транзакционными системами, в процессе работы которых создаётся история транзакций. у клиента MTS откроет новую транзакцию для объекта; requires new- объект не наследует транзакцию клиента, для него всегда открывается новая транзакция; not supported- транзакция никогда не будет открыта объекту вне зависимости от наличия транзакции на клиенте.
Одной из отличительных черт MTS является чрезвычайно рачительное, я бы даже сказал, трепетное отношение к системным ресурсам. Его девизом является активизация по мере необходимости и как можно более быстрая деактивизация объектов. Когда MTS деактивизирует объект, тот не разрушается, а становится доступен для повторного использования другими объектами. По секрету скажу, что MTS зачастую наглеет настолько, что может деактивизировать созданный вами объект при живых клиентских ссылках. То есть если вы создали объект, а потом отошли кофейку попить, не удивляйтесь, что этот сквалыга уже спер ваш объект, деактивизировал его и загнал кому-нибудь на сторону. Сердиться на него за это не стоит, потому что когда вы вернетесь и скажете "эй, парень, гони взад мой объект", лучше подождать лишних пол-секунды, пока MTS создаст или утянет (что существенно быстрее) с очередного ленивого соединения такой же объект, чем получить сообщение типа "извини, брат, не могу- память Память— одна из психических функций и видов умственной деятельности, предназначенная сохранять, накапливать и воспроизводить информацию. Способность длительно хранить информацию о событиях внешнего мира и реакциях организма и многократно использовать её в сфере сознания для организации последующей деятельности. кончилась". MTS деактивизирует объект при вызовах методов окончания транзакции SetComplete или SetAbort. В следующий раз при повторном обращении к этому объекту MTS по обыкновению вмешается в COMовский вызов, подсунет вам тот самый ваш (а может и не ваш) объект и вызовет у него затребованный вами метод. То же происходит при работе с базами данных. Так как одной из самых дорогих операций является установка соединения, то MTS склонен держать у себя пул ODBC-соединений, и если нужное вам соединение уже туда попало и является свободным, как вы думаете, что сделает MTS, когда вы его попросите соединиться с базой? Кинется бегом открывать новое соединение? Щас прям. В подавляющем большинстве случаев вы получите его из пула. Смех смехом, однако бережное расходование системных ресурсов является одним из необходимых условий высокой масштабируемости, и не обладай MTS такими возможностями, он едва ли сумел бы на обычной в общем-то конфигурации Конфигурация — характерное взаимное положение Солнца, планет, других небесных тел Солнечной системы на небесной сфере. без особых наворотов, обработать миллиард транзакций в сутки.
Иногда возникают ситуации, когда объект вынужден вернуть управление клиенту не будучи готовым завершить транзакцию. Пусть у нас есть объект, отвечающий за ввод одной бухгалтерской проводки. Нам нужно ввести серию проводок, скажем, за день и сверить сумму с итогом. Если они совпадают, то только тогда всю группу проводок можно фиксировать как единую транзакцию. Для этих целей контекст объекта имеет метод DisableCommit, который запрещает деактивизацию и сброс внутреннего состояния объекта. В нашем случае его должен вызвать объект ввода проводки. После выверки итогов объектом вызывается метод EnableCommit с последующей фиксацией или откатом транзакции.
Итак все объекты, работающие в среде управления MTS, могут вызывать друг друга. В отличие от них базовым клиентом называется истинный клиент в рассмотренной нами в п.3 трехуровневой схеме, т.е. это приложение, работающее, очевидно, не под управлением MTS, основная цель которого обеспечивать пользовательский интерфейс и отображать запросы пользователя в вызовы компонент. Для управления работой объектов MTS базовый клиент использует объект TransactionContext. Несмотря на то, что схема его применения очень похожа на контекст объекта (методы CreateInstance, Complete и Abort), базовый клиент может только управлять транзакцией MTS, но не участвовать в ней. Например, он не может напрямую открыть соединение с базой данных и вставить операции над ней внутрь этой транзакции. Наверное, это правильно, потому что коль скоро бизнес-логика Бизнес-логика — в разработке информационных систем — совокупность правил, принципов, зависимостей поведения объектов предметной области (области человеческой деятельности, которую система поддерживает). Иначе можно сказать, что бизнес-логика — это реализация правил и ограничений автоматизируемых операций. Является синонимом термина «логика предметной области» (англ.domain logic). ушла из клиентской части, то участие в транзакциях middleware недопустимо для базового клиента.
VB4 умел создавать только однопоточные компоненты. MTS обеспечивает их поддержку, хотя это самый медленный способ, чреватый взаимными блокировками. Предположим, объекты А и В последовательно исполняются на одном потоке управления. А блокирует запись Х и заканчивает работу, забыв сделать SetComplete. Управление получает объект В, которому тоже нужна запись Х, поэтому он простаивает в ожидании, пока А ее разблокирует. Но для этого А должен получить поток управления, который наглухо занял В. Имеем картину под названием "Приплыли". В VB5 можно создавать apartment-threaded компоненты, которые также поддерживает MTS, что уже легче. Каждому объекту внутри компоненты назначается отдельный поток на все время его жизни. Границы Граница— реальная или воображаемая линия, определяющая пределы какого-либо субъекта или объекта и разделяющая этот субъект или объект от других. апартаментов определяются деятельностью (activity), которая, насколько я понимаю, означает "гирлянду" объектов, связанных последовательными вызовами. Таким образом, если два объекта принадлежат разным деятельностям, они могут выполняться параллельно независимо от того, принадлежат они одной или разным компонентам. Мне кажется, что логично было бы ввести в последующих версиях MTS модель Модель (фр.modle, от лат.modulus— «мера, аналог, образец»)— некоторый материальный или мысленно представляемый объект или явление, являющийся упрощённой версией моделируемого объекта или явления (прототипа) и в достаточной степени повторяющий свойства, существенные для целей конкретного моделирования(опуская несущественные свойства, в которых он может отличаться от прототипа). рабочих потоков, так чтобы объекты не привязывались жестко к какому-то потоку, а могли свободно между ними перераспределяться и при этом не требовался бы кросс-поточный маршалинг.
Административными единицами при размещении компонент в MTS служат пакеты. Считается, что компоненты внутри пакета полностью доверяют друг другу, поэтому взаимные права компонент в пакете не проверяются, кроме того они запускаются в одном процессе. Очевидно, что базовые вызовы имеют identity клиента, поэтому при доступе к компонентам внутри пакета Пакета (порт. Paquet) — муниципалитет в Бразилии, входит в штат Пиауи. Составная часть мезорегиона Юго-восток штата Пиауи. Входит в экономико-статистический микрорегион Пикус. Население составляет 4430 человек на 2006 год. Занимает площадь 448,457км. Плотность населения - 9,9 чел./км. проверяется user-id. Вызовы, идущие из пакета, уже имеют identity данного пакета, поэтому если пользователи обращаются к компонентам, а компоненты, в свою очередь,- к базе данных, то имеет смысл сгруппировать компоненты по пакетам в соответствии с правами пользователей на доступ к базе, в противном случае авторизацию придется прописывать ручками внутри компонент. Это своего рода издержки переходного периода к многоуровневым системам. Перестройте свое мышление в соответствии с новым подходом: вы уже выросли из системы "клиент-сервер", давайте права на базу, имея в виду не конечных пользователей, а компоненты. В конце концов, пользователь вообще теперь не работает с базой- это забота Забота — комплекс действий, основанных на позитивных чувствах (часто — любовь, уважение) к объекту (человеку, животному, или предмету), и нацеленных на бескорыстное удовлетворение потребностей того объекта. компонент. Администрирование пользовательского доступа к компонентам осуществляется из MTS Explorer.
MTS допускает введение внутри пакетов глобальных переменных, доступ к которым разрешен для каждой компоненты. Глобальные переменные Переменная— атрибут физической или абстрактной системы, который может изменять своё значение. Значение может меняться в зависимости от контекста, в котором рассматривается система, или в случае уточнения, о какой конкретно системе идёт речь. Концепция переменной широко используется в таких областях как математика, естественные науки, техника и программирование. Примерами переменных могут служить температура воздуха, параметр функции и многое другое. В широком смысле, переменная характеризуется лишь множеством значений, которые она может принимать. (свойства) организованы в группы, получить или создать которые можно с помощью SharedPropertyGroupManager. Аналогично внутри каждой группы можно получить или создать разделяемое свойство при помощи SharedPropertyGroup. Вернемся к нашему банковскому примеру в начале пункта. Предположим, что мы еще хотим протоколировать каждую проводку в журнале и присваивать ей согласованный уникальный номер. Вот как для этого могут использоваться разделяемые свойства Свойство (в философии, математике и логике)— атрибут предмета (объекта). Например, о красном предмете говорится, что он обладает свойством красноты. Свойство можно рассматривать как форму предмета самого по себе, притом, что он может обладать и другими свойствами. Свойства, следовательно, подпадают под действие парадокса Рассела и парадокса Греллинга-Нельсона.:
dim spmMgr As SharedPropertyGroupManager
Set spmMgr = CreateObject("MTxSpm.SharedPropertyGroupManager.1")
dim spmGroup As SharedPropertyGroup
dim bResult As Boolean
Set spmGroup = spmMgr.CreatePropertyGroup("Receipt", LockSetGet, _
Process, bResult)
dim spmPropNextReceipt As SharedProperty
Set spmPropNextReceipt = spmGroup.CreateProperty("Next", bResult)
dim spmPropMaxNum As SharedProperty
Set spmPropMaxNum = spmGroup.CreateProperty("MaxNum", bResult)
dim objReceiptUpdate As Bank.UpdateReceipt
If spmPropNextReceipt.Value >= spmPropMaxNum.Value Then
Set objReceiptUpdate = ctxObject.CreateInstance("Bank.UpdateReceipt")
spmPropNextReceipt.Value = objReceiptUpdate.Update(strResult)
spmPropMaxNum.Value = spmPropNextReceipt.Value + 100
End If
' Get the next receipt number and update property
spmPropNextReceipt.Value = spmPropNextReceipt.Value + 1
Заключение
Microsoft Transaction Server сочетает в себе функции монитора транзакций и брокера объектных запросов. Как монитор транзакций MTS управляет транзакциями, проходящими через несколько менеджеров ресурсов, распределителями ресурсов (ODBC-соединения) и общими свойствами, процессами и потоками. Как брокер объектных запросов MTS управляет распределением компонент по компьютерам, использованием (в том числе повторным) экземпляров объектов, а также правами и безопасностью объектных вызовов. Приложения пишутся как однопользовательские, оформляются как ActiveX dll'и, регистрируются в среде управления MTS и начинают работать в многопользовательском режиме. Программирование для MTS не требует интенсивного знания COM или Win32 API. Компоненты для MTS могут быть разработаны с использованием широкого перечня средств разработки как от Microsoft, так и от других фирм. MTS поддерживает толстых (Win32 через DCOM) и тонких (броузер через HTTP и ASP) базовых клиентов. Несмотря на сравнительно недавний срок выхода MTS успел зарекомендовать себя как мощное и надежное средство построения и диспетчеризации ПО промежуточного слоя, отвечающее самым современным требованиям концепции распределенных вычислений.
Алексей Шуленин
Microsoft
Список литературы
- Д.Чэппел. Технологии ActiveX и OLE. ISBN 5-7502-0029-9
- Д.Круглински. Основы Visual C++. ISBN 5-7502-0025-6
- K.Brockschmidt. Inside OLE2. ISBN 1-55615-618-9
- Х.Кастер. Основы Windows NT и NTFS. ISBN 5-7502-0023-X
|