Библиотека сайта rus-linux.net
Фреймворк Zotonic
Глава 9 из книги "Производительность приложений с открытым исходным кодом".
Оригинал: Zotonic
Авторы: Arjan Scherpenisse и Marc Worrell
Перевод: Н.Ромоданов
Изменения в библиотеке Webmachine
Webmachine является библиотекой, в которой реализована абстракция протокола HTTP. Она реализована поверх библиотеки Mochiweb, в которой реализована низкоуровневая обработка протокола HTTP, например, процессы приема данных, анализ заголовка и т.д.
Контроллеры создаются с помощью модулей Erlang, реализующих функции обратного вызова,. Примерами функций обратного вызова являются функции resource_exists
, previously_existed
, authorized
, allowed_methods
, process_post
и т.д. В библиотеке Webmachine также определяются пути перенаправления запросов в соответствие со списком правил диспетчеризации, назначаются аргументы запросов и для обработки запроса HTTP выбирается правильный контроллер.
Благодаря библиотеке Webmachine обработка протокола HTTP становится простой. По этой причине мы с самого начала решили строить фреймворк Zotonic на основе библиотеки Webmachine.
При создании фреймворка Zotonic возникло несколько проблем, относящихся к библиотеке Webmachine.
- Когда мы начинали, то поддерживалась работа только с одним списком правил диспетчеризации, а не со списком правил для каждого хоста (т.е. сайта).
- Правила диспетчеризации устанавливались в среде приложения и в процессе диспетчеризации копировались в процесс, осуществляющий запрос.
- Некоторые функции обратного вызова (например,
last_modified
) во время оценки запроса вызывались несколько раз. - Когда в процессе оценки запроса происходит сбой работы Webmachine, то в журнал регистрации запроса не делалось никаких записей.
- Отсутствовала поддержка HTTP Upgrade, что усложняло поддержку сокетов WebSockets.
Первая проблема (отсутствие разбиения списка правил диспетчеризации на подсписки) — всего лишь неприятность. Она делает список правил диспетчеризации менее интуитивно понятным и более трудным для интерпретации.
Вторая проблема (копирование списка диспетчеризации для каждого запроса) выявила узкие места фреймворка Zotonic. Списки могут стать настолько большими, что их копирование может занять большую часть времени, необходимого для обработки запроса.
Третья проблема (несколько вызовов одной и той же функции) заставила программистов, которые писали контроллеры, реализовывать свои собственные механизмы кэширования, из-за чего возникали ошибки.
Четвертая проблема (отсутствие при аварии записей в журнале) усложнило обнаружение проблем в ходе эксплуатации фреймворка.
Пятая проблема (отсутствие HTTP Upgrade) мешало нам использовать замечательные абстракции, которые есть в библиотеке Webmachine, для сокетов WebSocket.
Указанные проблемы были настолько серьезными, что нам потребовалось модифицировать библиотеку Webmachine под наши собственные цели.
Сначала был добавлен новый инструмент: диспетчер. Диспетчер является модулем, реализующим функцию dispatch/3
, которая перенаправляет запросы согласно списку диспетчеризации. Диспетчер также выбирает правильный сайт (виртуальный хост), для этого он использует заголовок HTTP. Когда тестировался простой контроллер «hello world», то эти изменения дали трехкратное увеличение пропускной способности. Мы также видели, что в системах с множеством виртуальных хостов и правил диспетчеризации пропускная способность была гораздо выше.
В Webmachine поддерживается две структуры данных, одна - для данных запроса и одна - для хранения внутреннего состояния при обработке запроса. Эти структуры данных, имеющие ссылки друг на друга, практически почти всегда используются в паре, поэтому мы объединил их в единую структуру данных. В результате стало легче отказаться от использования словаря процесса и во все функции внутри библиотеке Webmachine добавить в виде аргумента одну новую структуру данных. Это привело к сокращению на 20% времени обработки каждого запроса.
Мы оптимизировали библиотеку Webmachine еще многими другими способами, которые здесь мы не будем описывать подробно, но самые важные моменты следующие:
- Мы кэшируем возвращаемые значения обратных вызовов некоторых контроллеров (
charsets_provided
,content_types_provided
,encodings_provided
,last_modified
иgenerate_etag
). - Мы отказались от использования словаря процесса more (глобальное состояние /less, более чистый код, проще тестирование).
- Для каждого запроса есть отдельный процесс журналирования; даже когда происходит аварийное завершение запроса, у нас вплоть до момента аварии есть записи в журнале.
- Для того, чтобы можно было поддерживать сокеты WebSockets, после проверки запрета доступа (forbidden) в качестве отдельного шага был добавлен обратный вызов HTTP Upgrade.
- Первоначально контроллер назывался «ресурсом». Мы изменили его на «контроллер» для того, чтобы иметь явное различие между ресурсами (данными) и кодом, обрабатывающим эти ресурсы.
- Для того, чтобы можно было измерять скорость выполнения запроса и его размер, были добавлены некоторые инструментальные средства.
Продолжение статьи: Модель данных: база данных документов на языке SQL.