Twisted ПАиПП — Взгляд изнутри

Проблема

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

  1. Интенсивные вычисления, например вычисление простых чисел. Большой расход ресурсов компьютера и процессорного времени в частности. (Многие сталкивались с такими задачами только в школе)
  2. Ожидании данных необходимых для расчета конечных результатов программы. (Некоторые также сталкивались с такими задачами в школе. Ждали пока за них решат задачу другие.)

Ожидание данных

В рамках сетевого программирования мы часто сталкиваемся с ожиданием данных. Например мы должны отправить письмо:

waiting-schm

Все это кажется не трудоемким, пока у нас одно письмо, а если нам надо разослать спам пользователям Mail.ru =)? Тогда нам лучше распараллелить задачи.

Решить проблему можно воспользовавшись несколькими средствами:

  1. Обрабатывать запросы используя тяжелые процессы(process, fork(вилка)), в этом случае ОС будет запускать один процесс пока другой ждет ответа.
  2. Обрабатывать запросы в потоках(thread), в этом случае системы управления потоками(scheduler) будет запускать поток пока другой ждет ответа.
  3. Использовать не блокирующую систему вызовов - обработать все запросы в рамках одного потока(thread) без блокировки кода во время ожидания данных.

Не блокируемые вызовы

Такой метод использует Twisted. Его реализует Reactor - технология на базе шаблона для взаимоисключения и обработки синхронных событий. Чем то схож с шаблоном проектирования подписчик Observer. Для реализации такой техники в unix подобных системах используются вызовы ядра select и\или poll, epoll (смотрите man select). Такой подход используются в технологиях:

  1. ACE - платформа на базе C++
  2. Medusa - платформа на базе python
  3. MINA java.nio & java.nio.channels
  4. EventMachine - ruby
  5. POE - perl
  6. Twisted

Когда порождается много соединений в одном потоке, управление запросами(scheduling) - задача приложения, а не ОС. Система управления запросами реализована так, что она сама запустит функцию когда необходимое соединение готово для чтения или записи. Такой подход называется асинхронным или событийным программированием.

Примерная модель работы рассылки почты:

  1. Вызываем функцию для соединения с удаленным сервером.
  2. Ответ получаем сразу с пониманием того, что наш механизм сообщит функции отправки почты,когда соединение будет создано.
  3. Когда соединение создано, механизм ядра Twisted вызовет функцию отправки почты.

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

Callbacks

Асинхронная модель для оповещения функции о готовности данных для нее.

deferred-process

Приложение добавляет серию функций к отложенной задаче так, чтобы вызов происходил по мере получение асинхронного результата. Это называется цепочкой callback’ов.

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

Обобщение

  1. В синхронном программировании функция запрашивает данные и ждет их для дальнейшей обработки.
  2. В асинхронном программировании функция запрашивает данные и просит сообщить ей о их наличии реактор.

Deferred - Объект который позволяет создать цепочку callback’ов и служить сигналом о скором получении данных. Отложенная задача.


Add post to:   Yandex.ru Google Yahoo Bobrdobr.ru Newsland.ru Smi2.ru Rumarkz.ru Memori.ru Myscoop.ru 100zakladok.ru Rucity.com Moemesto.ru News2.ru Delicious Reddit Slashdot Digg Technorati
Make comment

Comments

antisvin 26.08.2008 14:26

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

Кроме того, есть несколько подходов позволяющие обьеденить потоки и события. Модель актеров (реализована в erlang, scala и менее известных языках) существующая аж с 1973 года, которая представляет вычисления как множество процессов без общей памяти асинхронно обменивающихся сообщениями. При этом, например, erlang может использовать потоки ОС для реализации собственных в виде m:n, т.е. тысячи (или миллионы, хотя это скорее из области бенчмарков а не реального применения) своих легковесных потоков распределять между несколькими потоками ОС чтобы загрузить все процессоры.

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

Ммм… Спасибо, ты как всегда прав, но сильно углубился в подробности. Понятно что путать потоки, процессы и не блокируемый ввод-вывод нелепо. Дело в том, что в оригинальной документации Twisted используется такое разделения для первоначального упрощения понимания прикладной области.

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

Твои комментарии жду с нетерпением, уже читаю доки. Открывается темная сторона “Hello world” от инфернального Антисвина =).

Пыс. Пыс. На бабье лето в Питер собираюсь, может пересечемся ;)


Required. 30 chars of fewer.

Required.

captcha image Please, enter symbols, which you see on the image