C# для профессионалов. Том II
Шрифт:
В старые времена разработчики должны были создавать свои собственные схемы обеспечения транзакций, чтобы получить разновидность функциональности, упомянутой выше. Эти схемы включали обычно много логических переменных и детально разработанные стратегии обработки ошибок, и были подвержены ошибкам. Уже недавно объект
Принципы транзакций
Рассмотрим внутренний механизм работы транзакций
Координатор распределенных транзакция (DTC), компонент операционной системы Windows, отвечает за управление транзакциями. Компоненты, которые могут вовлекаться и участвовать в транзакциях, должны быть согласованы с интерфейсом, понимающим DTC, и должны предоставлять менеджера ресурсов, который может отменить или зафиксировать единицы работы, когда DTC прикажет ему это сделать. Этот высокий уровень абстракции позволяет таким различным компонентам, как процессоры баз данных и процессоры кредитных карт, работать совместно.
DTC реализует транзакции с помощью процесса, называемого двухфазной фиксацией. При выполнении транзакции DTC запрашивает сначала у каждого менеджера ресурсов, участвующего в транзакции, сможет ли он завершить свою работу — это является первой фазой. И только если DTC получает положительное подтверждение от каждого участника, он приказывает каждому участнику продолжить и зафиксировать изменения — это будет вторая фаза. Если один из участников испытывает трудности в первой фазе, то DTC прикажет каждому участнику отменить свою работу.
"Контекст" является абстракцией, важной для обработки транзакций. Каждая операция транзакции — такая как списание средств с кредитной карты и последующая вставка записи о заказе — имеет контекст, с которым она ассоциирована. Если операция происходит в контексте транзакции, это равносильно тому, что операция является частью транзакции и может предложить DTC, чтобы транзакция была зафиксирована или отменена. Такая операция по сути обладает правом "вето" на выполнение всех операций в своем контексте.
Хотя и немного детальное, это объяснение внутренней работы транзакций будет полезно позже, при кодировании поддержки транзакций в сборке .NET.
Транзакции в N-звенной архитектуре
Архитектурно типичные клиент-серверные приложения, использующие транзакции COM+, состоят из слоя объектов доступа к данным, которые выполняют работу по добавлению, удалению, извлечению и обновлению записей в базе данных. Этот слой завернут в слой бизнес-объектов, которые реализуют бизнес-правила через интерфейс пользователя на основе формы Windows или на основе браузера.
Обычно один метод бизнес-объекта вызывает несколько методов на различных объектах доступа к данным. Если один из методов доступа к данным не может выполниться правильно, метод бизнес-объекта использует механизм транзакций COM+, чтобы запросить DTC об отмене операции.
Службы COM+ и время жизни объекта
Название Сервер транзакций Microsoft было несколько неправильным, так как MTS предоставлял больше, чем просто поддержку транзакций. В этом разделе мы рассмотрим две службы COM+, которые были упомянуты первыми в MTS, — активацию JIT и создание пулов объектов. Обе эти службы являются технологиями эффективного
использования серверными машинами своих ресурсов при манипуляциях серверными объектами.Чтобы понять, как работают активация JIT и создание пулов объектов, необходимо знать, что существуют два различных типа приложений COM+.
□ Библиотечное приложение является совокупностью классов компонентов, объекты которых создаются в процессе вызывающего клиента.
□ Серверное приложение является совокупностью классов компонентов, объекты которых создаются в выделенном замещающем процессе, отдельном от процессов всех вызывающих клиентов.
Большинство приложений на основе ASP используют компоненты, хранимые в серверных приложениях. Так как компоненты находятся в выделенном замещающем процессе, отказ серверного компонента не приводит к аварийному отказу сервера Web. Для стандартных (не определенных в .NET) приложений COM задается свойство Activation Type на вкладке Activation окна приложения Properties:
Как мы увидим позже, существует другая процедура для определения типа активации сборки .NET. Будет показано, как делать это программным путем с помощью атрибутов.
Только приложения COM+ с типом активации Serverapplication могут воспользоваться пулом объектов, включающих службу COM+, которая будет рассмотрена далее.
Создание пулов объектов
В терминах циклов процессора и байтов является достаточно дорогим создание экземпляра и инициализация объекта. Эти расходы объединяются для сервера Web, который должен обслуживать одновременно десятки тысяч пользователей. Чтобы пользователи не ощущали задержки, пока сервер Web пытается создать объекты компонентов, службы COM+ предоставляют пулы объектов.
Как можно предположить, эта служба COM+ позволяет поддерживать пул объектов, которые создаются и ожидают использования даже до того, как они понадобятся. Когда серверному сеансу понадобиться объект определенного компонента он просто запрашивает объект из пула доступных объектов, получая его немедленно, если объект готов, или ожидая в очереди, пока не станет доступен новый объект. Когда объект освобождается клиентом, службы COM+ не разрушают его, а позволяют существовать в пуле, готовым на случай, если он понадобится другому клиенту. Так как можно определить минимальное и максимальное число объектов в пуле, то можно дискретно контролировать, сколько серверных ресурсов выделено для класса компонента.
По своей природе пул объектов может позволить использовать один и тот же экземпляр объекта нескольким различным клиентским процессам. Это означает, что если один из этих процессов изменит состояние общего объекта перед тем, как откажется от него, новое состояние будет видно следующему процессу, который получит объект, даже если это состояние будет не тем, которое ожидает наследующий процесс. Существует пара способов обойти эту проблему.
Первый: можно спроектировать классы компонентов не имеющих состояния. Это означает, что для них не определяются свойства, которые должны быть заданы перед вызовом методов. Вместо этого значения этих свойств хранятся вне объектов, в самом интерфейсе пользователя, и передаются в качестве входящих в объекты аргументов, когда вызываются их методы. Так как объекты больше не связаны с какими-либо устойчивыми данными, эта схема эффективно сокращает классы до библиотек функций.