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

UnixForum





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

Фреймворк Zotonic

Глава 9 из книги "Производительность приложений с открытым исходным кодом".

Оригинал: Zotonic
Авторы: Arjan Scherpenisse и Marc Worrell
Дата публикации: 2013 г.
Перевод: Н.Ромоданов
Дата перевода: февраль 2014 г.

Введение в фреймворк Zotonic

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

Хотя в нем доступны многие функциональные возможности, которые есть во фреймворках, предназначенных для веб-разработки, например, в Django, Drupal, Ruby on Rails и в Wordpress, его главным конкурентным преимуществом является язык, из которого он черпает всю свою силу: язык Erlang. Этот язык, изначально разработанный для создания телефонных коммутаторов, обеспечивает отказоустойчивость и отличную производительность фремворка Zotonic.

Как уже сказано, в этой главе будет рассказываться о производительности фреймворка Zotonic. Мы рассмотрим причины, благодаря которым язык Erlang был выбран в качестве платформы программирования, затем проинспектируем стек запросов HTTP, а затем погрузимся в стратегии кэширования, которые используются в фреймворке Zotonic. Наконец, мы расскажем о вариантах оптимизации, которые мы использовали в субмодулях и базе данных фреймворка Zotonic.

Почему Zotonic? Почему Erlang?

Первые работы по Zotonic были начаты в 2008 году, и, как и многие проекты, он появился из желания «сделать все с нуля». Марк Уоррелл (Marc Worrell), основной архитектор фреймворка Zotonic, в течение семи лет работал в фирме Mediamatic Lab, в Амстердаме, в системе управления контентом, похожей на Drupal и написанной на PHP/MySQL, которая называлась Anymeta. Основной парадигмой системы Anymeta было то, что в ней был реализован «прагматичный подход к семантическому вебу», моделирующей все в системе в виде обобщенных «сущностей». Хотя подход был успешным, его реализация страдала от проблем с масштабируемостью.

После того, как Марк покинул фирму Mediamatic, он потратил несколько месяцев на проектирование с нуля более правильной системы управления контентом, похожей на Anymeta. Основной задачей разработки Zotonic было сделать этот проект простым для его использования разработчиками внешнего интерфейса; он должен был поддерживать легкую разработку веб-интерфейсов реального времени, допускающих одновременное существование долговременных подключений и многих короткоживущих запросов; и он должен быть иметь хорошую производительность. Что еще более важно, он должен был решать наиболее распространенные проблемы, из-за которых в более ранних подходах к веб-разработке возникали ограничения по производительности, например, он должен был выдержать эффект Shashdot (внезапный всплеск числа посетителей).

Проблемы с классическим подходом PHP+Apache

Классическая настройка с использованием PHP представляет собой модуль внутри контейнера веб-сервера, например, сервера Apache. При каждом запросе, сервер Apache решает, как обработать запрос. Когда это запрос для PHP, то сервер разворачивает модуль mod_php5, а затем интерпретатор PHP начинается интерпретацию скрипта. Это приводит к задержке запуска: как правило, на такое разворачивание требуется 5 мс, а затем еще нужно время для того, чтобы проработал код на PHP. Эта проблема может быть частично устранена с помощью акселераторов PHP, которые минуя интерпретатор предварительно компилируют скрипт PHP. Накладные расходы на запуск PHP можно также устранить с помощью менеджера процессов, например, PHP-FPM.

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

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

Требования к современному Веб фреймворку

Современные веб фреймворки обычно имеют дело с тремя классами запросов HTTP. Во-первых, есть динамически генерируемые страницы: динамически обрабатываемые и обычно генерируемые процессором по шаблону. Во-вторых, есть статический контент: малые и большие файлы, которые не изменяются (например, JavaScript, CSS и медиа данные). В-третьих, существуют долгоживущие подключения: веб-сокеты и запросы к долгоживущим пулам, используемые для обеспечения интерактивности и двусторонней связи со страницами.

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

  • Распараллеливание: нужно поддерживать множество одновременных соединений, которые не ограничены числом процессов UNIX или потоков OS.
  • Совместное использование ресурсов: нужно иметь механизм для недорогого разделения ресурсов (например, кэширования, подключения к БД) различными запросами.
  • Горячее обновление кода: для облегчения разработки и для возможности горячего обновления систем в процессе промышленной эксплуатации (сведения простоя к минимуму), было бы неплохо, если бы изменения в коде могли бы разворачиваться в работающей системе без необходимости ее перезагрузки.
  • Поддержка многоядерных процессоров: современная система должна масштабироваться на несколько ядер, т.к. существующие процессоры, как правило, развиваются в направлении увеличения количества ядер, а не увеличения тактовой частоты.
  • Отказоустойчивость: необходимо, чтобы система могла обрабатывать исключительные ситуации, «плохо ведущий себя» код, различные аномалии или исчерпание ресурсов. В идеале в системе это должно происходить с помощью некоторого механизма контроля, который перезапускает неправильно работающие части.
  • Развертывание: для того, чтобы обеспечить более высокую производительность и защиту от аппаратных сбоев, система, в идеале, должна быть встраиваемой и легко настраиваемой с поддержкой ее развертывания на нескольких узлах.

На помощь приходит язык Erlang

Насколько нам известно, Erlang был единственным языком, удовлетворяющих этим требованиям сразу «из коробки». Виртуальная машина Erlang в сочетании с платформой Open Telecom Platform (OTP) представляла собой систему, которая дала и продолжает давать нам все необходимые возможности.

Язык Erlang является (по большей части) функциональным языком программирования и системой реального времени. Приложения Erlang/OTP первоначально разрабатывались для телефонных коммутаторов и известны своей отказоустойчивостью и возможностью распараллеливания. В языке Erlang используется распараллеливания, базирующаяся на понятии «актора» (actor): каждый актор представляет собой легковесный «процесс» (зеленый поток), и единственным способом совместного использования состояния процесса является обмен сообщениями. Платформа Open Telecom Platform представляет собой набор стандартных библиотек языка Erlang, с помощью которых, кроме всего прочего, реализуется отказоустойчивость и мониторинг процессов.

Отказоустойчивость является основой парадигмы программирования: основная философия системы — let it crash (пусть процесс будет разрушен). Поскольку у процессов нет какого-нибудь общего синхронизированного состояния (чтобы использовать одно и то же состояние, они должны посылать друг другу сообщения), их состояние изолировано от других процессов. Таким образом, разрушение одного процесса никогда не будет причиной прекращения работы системы. Когда процесс будет разрушен, процесс, осуществляющий наблюдение за ним, может принять решение о его перезапуске.

Философия let it crash удобна при программировании. Использование сопоставления с образцом и охранных функций позволяют применять средства поддержки нормального состояния, требующие меньшего количество кода обработки ошибок, что обычно приводит к чистому, краткому и читаемому коду.


Продолжение статьи: Архитектура фреймворка Zotonic.