Библиотека сайта rus-linux.net
Применение принципов оптимизации к средствам компонентного развертывания и конфигурирования систем
Глава 6 из книги "Производительность приложений с открытым исходным кодом".
Оригинал: Applying Optimization Principle Patterns to Component Deployment and Configuration Tools,
Авторы: Doug C. Schmidt, William R. Otte, and Aniruddha Gokhal
Перевод: Н.Ромоданов
Принципы оптимизации, используемые для сокращения фазы последовательного анализа
Все тоже самое относится и к проблеме анализа, которая была описана ранее; излишнее следование последовательному порядку обработки снижает производительность. Однако в данном случае вместо того, чтобы вновь анализировать алгоритмический подход к процессу развертывания, мы пересмотрим всю архитектуру системы. Чтобы в данном случае разобраться с проблемами производительности, мы к DanCE применили следующие принципы оптимизации:
- Не следует допускать, чтобы спецификации чрезмерно ограничивали вашу систему. Когда система или фреймворк реализуются согласно некоторой спецификации, эта спецификация вместе с ее ограничениями и неявными допущениями часто естественным образом становится моделью архитектуры вашей системы. Часто можно спроектировать вашу реализацию таким образом, чтобы в нее можно было добавить другие элементы архитектуры или новое поведение системы и, при этом, оставаться в пределах допущений, заданных в спецификации. Это пример как принципа Specification vs. Implementation (Спецификация или реализация), так и принципа Degrees of Freedom (Степени свободы).
- Нужно поддерживать строгое разделение решаемых задач. Обеспечьте, чтобы ваша система функционировала в виде слоев или модулей, которые взаимодействуют друг с другом через четко определенные интерфейсы. Это поможет обеспечить, чтобы состояние каждого слоя или модуля было хорошо формулируемым и это упростит взаимодействие между логически различными частями ваших приложений, а также упростит применение принципа Design for Parallelization (Разработка с учетом распараллеливания). Кроме того, если обеспечить, чтобы формулирование состояния каждого слоя было самодостаточным, то это также поможет применить принцип Avoid Synchronization (Отказ от синхронизации).
Кроме того, модульность архитектуры вашего программного обеспечения часто сможет подсказать, как можно будет применить другие принципы оптимизации. Таким образом, мы предлагаем еще один принцип Separate Concerns (Разделение решаемых задач), позволяющий распределить различные понятия по различным модулям в рамках модульной архитектуры (с помощью которой они обобщены). Хотя традиционно добавочный уровень косвенности может быть встречен с неодобрением из-за того, что он может привести к потери производительности, иногда он позволяет выявить новые возможности или помочь применить другие принципы оптимизации.
- Нужно обеспечить, чтобы эти слои или модули могли взаимодействовать друг с другом асинхронно. Если модули или слои в архитектуре вашей системы имеют интерфейсы, в рамках которых предполагается синхронная работа, то усложняется распараллеливание операций с целью повышения производительности. Даже если интерфейс сам является синхронным, часто можно воспользоваться другими методами, например, использовать абстракции, которые позволят вам взаимодействовать с синхронным интерфейсом в асинхронном режиме. Отказ от синхронных промежуточных взаимодействий является еще одним важным применением принципа Design for Parallelization (Разработка с учетом распараллеливания).
Когда эти принципы применяются на глобальном уровне (например, менеджер ExecutionManager
, описываемый в разделе «Архитектура D&C времени выполнения»), разделение решаемых задач поддерживается в силу того, что этот уровень и ресурсы уровня узлов находятся в отдельных процессах, и, вероятно, на различных физических узлах. В этом контексте также легко достижима асинхронность, поскольку мы смогли воспользоваться асинхронным вызовом методов CORBA (CORBA Asynchronous Method Invocation - AMI), который позволяет клиенту (в данном случае, глобальной инфраструктуре) взаимодействовать асинхронно с синхронным интерфейсом сервера (в данном случае, инфраструктурой уровня узла) и распараллеливать отправку нескольких запросов на различные узлы. Это пример принципа Degrees of Freedom (Степени свободы), состоящий в том, что спецификация не запрещает асинхронное взаимодействие между этими сущностями.
Но применение этих принципов в инфраструктуре уровня узла оказалось более сложным. Как описано выше, в нашей первоначальной реализации были плохо разделены решаемые задачи, что исключительно затруднило применение нескольких исполняемых потоков для распараллеливания на уровне узла действий, связанных с развертыванием компонентов. Для поддержки этого, мы на уровне узла создали новую абстракцию, которую мы назвали локальным менеджером Locality Manager, представляющим собой результат применения вышеуказанных принципов оптимизации.
Обзор локального менеджера LE-DAnCE. Архитектура LE-DAnCE уровня узла (например, NodeManager, NodeApplicationManager и NodeApplication) теперь функционирует точно также, как версия глобальной части архитектуры OMG D&C, действие которой ограничено узлом. Вместо того, чтобы иметь приложение NodeApplication, непосредственно запускающее установку экземпляров конкретных компонентов, эта обязанность теперь делегируется экземплярам менеджера LocalityManager. Инфраструктура уровня узла выполняет второе «расщепление» плана, который она получает с глобального уровня с помощью объединения отдельных экземпляров компонентов в один или большее количество процессов приложения. Затем приложение NodeApplication порождает ряд процессов LocalityManager и параллельно делегирует эти «ограниченных процессом» (т.е. содержащие только те компоненты и соединения, которые требуются одному процессу) планы в каждый процесс приложения.
Локальный менеджер Locality Manager является примером принципа оптимизации Specification vs. Implementation (Спецификация или реализация). Согласно спецификации следовало бы предположить, что NodeApplication является финальной сущностью, которая взаимодействует со средним слоем компонента; признав, что в нашей реализации можно ввести еще один уровень абстракции, мы смогли применить ряд других принципов оптимизации.
В отличие от предыдущей реализации NodeApplication в DAnCE, локальный менеджер LocalityManager в LE-DAnCE функционирует как общий процесс приложения, в котором решаемые задачи строго разделены между общей логикой развертывания, необходимой при анализе плана, и конкретной логикой развертывания, необходимой для установки и управления жизненным циклом экземпляров среднего слоя конкретного компонента. Такое разделение достигается с помощью сущностей, называемых Instance Installation Handlers (обработчики установки экземпляров компонентов), с помощью которых реализован строго определенный интерфейс управления жизненным циклом экземпляра компонента, в том числе управление установкой, удалением, подключением, отключением и активацией. Эти обработчики также используются в контексте NodeApplication для управления жизненным циклом процессов LocalityManager.
Создание этих обработчиков является примером проявления принципа Degrees of Freedom (Степени свободы); согласно требованию явного взаимодействия со средним слоем компонента, этот принцип позволил нам легко создать наш собственный вариант взаимодействия. Сделав это, мы применили принцип Separate Concerns (Распределение решаемых задач).
Использование локального менеджера Locality Manager для сокращению последовательного выполнения действий на фазах развертывания. Новый менеджер LocalityManager и обработчики установки экземпляров, используемые в LE-DAnCE, делают распараллеливание в LE-DAnCE более простым, чем в DAnCE. Распараллеливание как в LocalityManager, так и в NodeApplication достигается с помощью сущности, которая назвается Deployment Scheduler (Планировщик развертывания) и показана на рис.6.5.
Рис.6.5: Планировщик развертывания в DAnCE
В планировщике развертывания Deployment Scheduler объединены принцип Command (Команда) [36] и принцип Active Object (Активный объект) [37]. Внутри объекта действия заключены отдельные действия по развертыванию (например, установка экземпляра, подключение экземпляра и т.д.) вместе со всеми требуемыми метаданными. Каждое отдельное действие развертывания является вызовом метода обработчика установок Installation Handler, поэтому в каждом потенциальном случае развертывания эти действия переписывать не требуется. Внутрь отдельных действий также полностью включена обработка ошибок и логика протоколирования, что еще больше упрощает использование локального менеджера LocalityManager.
Планирование исполнения отдельных действий (например, установки компонента или создания соединения) осуществляется при помощи конфигурируемого пула потоков. Этот пул, в зависимости от требований приложения, может работать в режиме, выбираемом пользователем, в однопоточном режиме или в многопоточном режиме. Этот пул потоков можно также использоваться для планирования более сложного поведения, например, алгоритма планирования на основе приоритетов, который динамически изменяет порядок установки экземпляров компонентов в зависимости от того, какие метаданные присутствуют в плане развертывания.
Локальный менеджер LocalityManager определяет, какие действия следует выполнить на каждой конкретной фазе развертывания, и для каждой инструкции создает один объект действий Action. Затем эти действия перенаправляются для выполнения в планировщик развертывания, а основной поток управления ждет от планировщика развертывания сигнала о завершении. После завершения установки локальный менеджер LocalityManager получает от выполненных действий либо возвращаемые значения, либо коды ошибок и завершает фазу развертывания.
Чтобы обеспечить распараллеливание отдельных экземпляров LocalityManager на одном и том же узле, в реализации NodeApplication кроме обработчика установок, используемого для процессов LocalityManager, также используется планировщик развертывания LE-DAnCE. Использование планировщика развертывания на этом уровне помогает справиться со значительными задержками, возникающими при развертывании на уровне узлов. На создание экземпляров LocalityManager может потребоваться время, значительно большее в сравнении с временем, необходимым для развертывания экземпляров компонентов, поэтому в случае, когда для развертывания приложений на каждом узле используется большое количество процессов LocalityManager, распараллеливание этого процесса может существенно сократить время ожидания.
Если все объединить вместе, то для платформы SEAMONSTER динамическое переупорядочивание событий развертывания и параллельная установка экземпляров LocalityManager станет перспективным подходом к снижению задержек развертывания. Если критическим событиям развертывания, например, активированию или изменению настроек датчиков, используемых при наблюдении за природными явлениями, назначать высокие приоритеты, то движок DAnCE может обеспечить, чтобы критические действия выполнялись своевременно. Кроме того, распараллеливание, которое можно использовать в этом случае, может уменьшить время ожидания за счет того, того, что когда один экземпляр менеджера LocalityManager будет заблокирован из-за ожидания ввода/вывода, другие экземпляры будут продолжать выполняться, либо за счет того, что будут использованы возможности новых многоядерных встроенных процессоров.
Продолжение статьи: Заключение.