Наши партнеры

UnixForum





Библиотека сайта rus-linux.net

Twisted

Глава 21 из книги "Архитектура приложений с открытым исходным кодом", том 2.

Оригинал: Twisted
Автор: Jessica McKellar
Перевод: А. Панин

21.2. Архитектура Twisted

Twisted является управляемым событиями сетевым фреймворком. Парадигма управляемого событиями программирования является настолько неотъемлемой частью философии проектирования Twisted, что стоит уделить некоторое время обзору того, что на самом деле понимают под парадигмой управляемого событиями программирования.

Управляемое событиями программирование осуществляется в соответствии с парадигмой, определяющей то, что ход выполнения программы задается внешними событиями. Для него характерно использование цикла приема событий и использование функций обратного вызова с целью выполнения действий в моменты наступления событий. Другим двумя стандартными парадигмами программирования являются синхронное (однопоточное) и многопоточное программирование.

Давайте сравним и найдем отличия между однопоточной, многопоточной и управляемой событиями моделями программирования с помощью примера. На Рисунке 21.1 представлена выполняемая программой работа с течением времени в случае использования каждой из этих трех моделей. Программа должна выполнить три задачи, причем каждая из этих задач блокирует выполнение программы до момента завершения операции ввода/вывода. Время, потраченное при блокировании выполнения программы для завершения операций ввода/вывода, показано с помощью областей серого цвета.

Модели сетевого программирования
Рисунок 21.1: Модели сетевого программирования

В однопоточной синхронной версии программы задачи выполняются по очереди. В том случае, если одна задача блокируется для выполнения операций ввода-вывода, всем другим задачам приходится ожидать окончания выполнения операций и приступать к работе по очереди. Этот определенный порядок и последовательное выполнение задач упрощают понимание принципа работы программы, но при этом программа становится чрезмерно медленной в том случае, когда задачи не зависят друг от друга, но им все равно приходится ожидать друг друга.

В многопоточной версии программы три задачи с блокировками во время выполнения работы исполняются в отдельных программных потоках. Эти потоки управляются операционной системой и могут исполняться одновременно на множестве процессоров или поочередно на одном процессоре. Это позволяет выполнять работу некоторым потокам в тот момент, когда другие потоки блокируются для обработки ресурсов. Обычно эта программа более оптимальна с точки зрения времени, чем аналогичная синхронная программа, но приходится разрабатывать дополнительный код для защиты разделяемых потоками ресурсов, доступ к которым может осуществляться одновременно из нескольких потоков. Принцип работы многопоточных программ может оказаться более сложным для понимания, так как в случае реализации таких программ приходится заботиться о безопасной работе потоков с помощью механизмов сериализации процессов (блокировок), использования реентерантных функций, локальных хранилищ данных для потоков или других механизмов, которые в случае некорректного применения могут приводить к скрытым и опасным ошибкам.

Управляемая событиями версия программы поочередно выполняет три задачи, но в рамках одного потока. При выполнении операций ввода/вывода или других затрачивающих время операций, в цикле обработки событий регистрируется функция обратного вызова и выполнение задачи продолжается после завершения операции ввода/вывода. Функция обратного вызова устанавливает метод обработки события сразу же после завершения операции. Цикл обработки событий ожидает события и распределяет их в порядке поступления для обработки с помощью функций обратного вызова, которые их ожидают. Это обстоятельство позволяет программе выполнять работу всегда, когда это возможно без необходимости использования множества дополнительных потоков. Управляемые событиями программы могут быть более простыми для понимания, нежели многопоточные программы, так как разработчику не приходится заботиться о безопасности функционирования потоков.

Управляемая событиями модель обычно является хорошим выбором, если:
  1. имеется множество задач, которые...
  2. в значительной степени независимы (поэтому им не нужно взаимодействовать друг с другом или ожидать друг друга), а также...
  3. некоторые из этих задач блокируются во время ожидания событий.

Также эта модель является хорошим выбором в том случае, когда приложению требуется предоставлять задачам доступ к изменяемым данным, так как в этом случае не требуется синхронизации.

Приложения для работы с сетью обычно имеют именно эти свойства, что и определяет их хорошую совместимость с управляемой событиями моделью программирования.

Повторное использование существующих приложений

Многие популярные клиенты и серверы для различных сетевых протоколов существовали до того, как был создан фреймворк Twisted. Почему же glyph просто не использовал Apache, IRCd, BIND, OpenSSH или любое другое из ранее существующих приложений, клиенты и серверы из которых были с нуля реализованы в рамках Twisted?

Проблема состоит в том, что все эти реализации серверов обычно использовали разработанный с нуля с использованием языка программирования C код для взаимодействия с сетью, причем код приложения был напрямую связан с кодом сетевого уровня. Это обстоятельство в значительной степени затрудняло использование существующего кода в форме библиотек. Эти программные компоненты должны были совместно использоваться как черные ящики, не позволяя разработчику повторно использовать код в том случае, если он или она пожелали передать одни и те же данные с использованием множества протоколов. К тому же, реализации серверов и клиентов обычно являются отдельными приложениями, которые совместно не используют код. Расширение возможностей этих приложений и поддержка кроссплатформенной клиент-серверной совместимости оказываются более сложными задачами, чем должны.

В случае использования Twisted клиенты и серверы разрабатываются с использованием языка Python и постоянного интерфейса. Это обстоятельство упрощает разработку клиентов и серверов, совместное использование кода для реализации клиентов и серверов, использование одной и той же логики приложения для работы с различными протоколами, а также тестирование кода.


Продолжение статьи: Шаблон проектирования reactor