Перенёс этот блог с Друпала на Хьюго

Небольшое лирическое вступление

Я уже не помню точно когда я сделал первую версию этого блога, но доменное имя romka.eu я зарегистрировал 10 августа 2006 года, 17 лет назад =8) Все эти 17 лет блог работал на CMS Drupal. Опять-таки, я уже не помню, на какой версии Друпала была сделана его первая версия, вполне вероятно, что это была версия 4.7. Версия упомянутая в этом блог-посте уже, скорее всего работала на пятёрке, а затем, позднее, по мере выхода новых релизов, я обновил блог до шестёрки и семёрки.

Примерно с 2007 по 2014 год я профессионально (в смысле, за деньги) занимался веб-разработкой и Друпал был моим основным рабочим инструментом. Не могу сказать, что работа с этой системой это ценный профессиональный опыт, но чего совершенно точно нельзя отрицать, так это того, что без участия в Друпал-сообществе не случилась бы та цепочка событий, которая сегодня привела меня туда где я есть. Семинары и конференции по Друпалу, новые знакомства, работа в forbes.ru (полученная в том числе благодаря моей самоуверенности в том, что друпальщика лучше меня ребятам просто не найти), а затем и в Яндексе, всё это скорее всего не произошло бы, если бы я тогда, году в 2006 не заинтересовался Друпалом. Я как-нибудь напишу эту историю подробнее, думаю, она может получиться интересной, но этот пост не об этом.

Обновление

Уже почти 10 лет как я не работаю с Друпалом и я давно хотел с него съехать. Используемый им стек технологий постоянно требовал внимания к себе: админка Друпала была красной от предупреждений о найденных уязвимостях для модулей, обновления к которым не выходили последние как минимум лет 5; спамеры находили всё новые и новые способы зафлудить БД бесполезными мусорными комментариями. Сайт работал на давно устаревшей Ubuntu 14.04, обновление которой потянуло бы за собой и обновление основных зависимостей Друпала: версии PHP и связанных с ним библиотек. В общем, сайт причинял головную боль, а разбираться со всем этим мне было уже совсем не интересно. Да и, кроме всего прочего, мне стали очевидны две вещи:

  1. мне не нужна такая сложная CMS для такого простого блога,
  2. я хочу, чтобы весь созданный мною контент представлял из себя простое дерево директорий, где каждый материал это одна директория, содержащая и текст, и связанные с ним фотографии и другие файлы. С таким подходом для просмотра содержимого не нужен ни веб-сервер, ни тем более БД и интерпретатор PHP.

Собственно, по этой причине я перенёс этот блог на статический генератор сайтов Hugo. Исходники блога лежат на Гитхабе (например, вот так выглядит этот пост), а из них Хьюго генерирует html-файлы, которые раскладываются на арендуемый мною сервер на Digital Ocean, а также на два CDN: netlify.com и render.com. Зеркала этого сайта на этих двух CDN доступны по адресам mirror1.romka.eu / romka-eu.onrender.com и mirror2.romka.eu / nimble-figolla-e0e98e.netlify.app. Для того объема контента, который у меня есть, использование этих CDN бесплатно, так что возможно, со временем, один из них может стать основным хостингом для этого блога.

Для сайта я сделал свою собственную тему оформления frühling, пока она распространяется только как часть этого блога, но позднее, когда я завершу её разработку, я планирую выложить её отдельным проектом.

Читать дальше ➠

Проблема с кодом вне функций в Drupal 6 и 7

Столкнулся с интересной проблемой, которую удалось повторить и в Drupal 6, и в Drupal 7. В модуле вне тела функции была объявлена константа:

define('TEST_CONST', drupal_get_path('module', 'test_module'));

(тут дело даже не в самой константе, а в использовании апишной функции drupal_get_path() вне тела функции).

Этот модуль долгое время корректно работал, до тех пор пока в нем не был объявлен hook_exit(). После этого события Друпал начал отдавать ошибку "PHP Fatal error: Call to undefined function drupal_get_path() in...", где вместо drupal_get_path() можно поставить почти любую функцию из Drupal API, которая была использована в коде, расположенном вне тела функций.

Поиск и исправление причин ошибки осложнился тем, что она стала проявляться не сразу после добавления hook_exit(), а спустя некоторое время.

Суть ошибки оказалась в следующем:

  • Друпал в таблице system, модулям которые реализуют hook_exit(), проставляет значение 1 в колонке bootstrap, по умолчанию этот параметр равен нулю.
  • В свою очередь модули отмеченные таким образом начинают загружаться Друпалом раньше остальных (на этапе DRUPAL_BOOTSTRAP_LATE_PAGE_CACHE в случае Drupal 6) когда API, в частности файл common.inc, содержащий функцию drupal_get_path(), еще не загружен полностью.
  • Загрузка модуля подразумевает include файла модуля и, что логично, исполнение кода, находящегося вне тела функций.

Таким образом, после добавления hook_exit() модуль стал загружаться до полной загрузки API и функция drupal_get_path() на этом этапе действительно еще не была определена. Решилась проблема переносом проблемного кода в hook_init().

Возникла ошибка не сразу от того, что обновление поля bootstrap в таблице system делается не сразу, а при обновлении кеша списка модулей (вызов функции module_rebuild_cache() в Drupal 6). Этот кеш очищается, например, при нажатии кнопки “Сохранить” на странице списка модулей или при срабатывании модуля Update status.

Похвастаюсь статистикой в день сообщения о разводе Путина

Средняя нагрузка на сайт днем в рабочий день 1000 запросов в минуту (масимум 30-40 в секунду), около 200 тысяч уников в день и около 800 тысяч просмотров. Трафик отдается на скорости до 10 мегабайт в секунду.

В пиках нагрузка раньше доходила до 4 тысяч запросов в минуту (до 120 в секунду), около 350 тысяч уников в день и 2,5 млн. просмотрв. В пиках трафик отдавался на скорости до 50 мегабайт в секунду.

Пятница, 7 июня. В пике сайт отдавал больше 12 тысяч страниц в минуту (250 в секунуду) на скорости около 110 мегабайт в секунду.

visitors Traffic by minutes First frontend Second frontend

Drupal + Varnish отработали на отлично. С учетом нашего канала и железа сайт может держать вдвое большую нагрузку подобного плана.

Интеграция системы статистики Piwik с Drupal 6

При работе над Drupal-проектом у меня возникла необходимость сбора детальной статистики о просмотрах материалов и вывода этой статистики в виде блоков, отображающих самые просматриваемые материалы за последние день, неделю и месяц. Стандартный друпальский модуль Statistics (и в шестом, и в седьмом Друпале) для решения такой задачи абсолютно неприменим:

  • во-первых он осуществляет сбор статистики на hook_exit() и не будет работать корректно со сколько-нибудь серьезными системами кеширования, например при использовании Varnish или модуля Boost.
  • во-вторых модуль Statistics собирает статистику за всё время существования материала, сделать выборку вида: “сколько раз был просмотрен материал за последний день” с этим модулем невозможно. По этому при использовании этого модуля исходную задачу пришлось бы модифицировать к виду: вывести список самых просматриваемых материалов созданных за последние день, неделю или месяц, но этот подход неприемлем, так как на сайте существуют материалы старше месяца, способные попасть в топ по просмотрам.

Таким образом, возникла необходимость внедрить полноценную систему статистики и интегрировать ее с Друпалом. Под полноценными системами я понимаю сервисы типа Google Analytics или Яндекс.Метрика, используя API которых можно запросить статистику просмотров материалов за любой диапазон дат. Достоинством этих сервисов является то, что они у себя хранят всю статистику, а она на посещаемом ресурсе может занимать немало места, их недостаток — все таки это внешние сервисы и неизвестно, что с ними случится завтра: сломаются, станут платными, не захотят внедрять нужную пользователю фичу и т.д.

В итоге я решил установить на собственном сервере open source систему статистики Piwik и интегрировать ее с Друпалом. Да, Пивик пока местами уступает GA и Я.М в гибкости отчетов (хотя есть в нем и отчеты, которых нет ни в ГА, ни в Я.М), но, во-первых, нужную мне задачу он решает, во-вторых он постоянно развивается своими разработчиками и может быть расширен с помощью самописных плагинов.

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

Заполнение полей данными осуществляется через Drupal Queue API по крону, но при желании стандартный механизм обработки очереди может быть заменен чем угодно, например Rabbit MQ.

Плюсом хранения статистики в полях является то, что статистика становится прозрачно интегрированной со всем модулями Друпала, например с Views, с помощью которого, в том числе, можно строить блоки с контексто-зависимой статистикой. То есть, например, на главной странице сайта выводить список самых популярных статей со всего сайта, а на странице статьи или раздела — выводить самые популярные статьи текущего раздела.

Основная проблема для меня состояла в том, что модуль Piwik stats работает только под седьмым Друпалом и его разработчик не планировал делать бэкпорт под шестерку, а проект, в котором мне понадобился этот функционал, работает как раз на древней шестой версии Друпала. По этому я сам сделал бэкпорт этого модуля под шестерку. Забрать мою версию модуля можно из sandbox-проекта Piwik_stats, обсуждение этого бэкпорта с автором основного модуля тут: http://drupal.org/node/1736398.

Пока мейнтейнер модуля не хочет делать мою версию модуля официальной, из-за того, что требуется сделать детальный code review. Тем не менее, мой модуль без нареканий больше месяца работает в бою на двух Друпал 6 проектах.

Typo — Drupal-модуль для борьбы с опечатками на сайте

Разработал новый модуль для Drupal 7, который позволяет пользователю выделить мышью найденную в тексте опечатку и нажатием Ctrl + Enter отправить сообщение о ней администратору сайта. Модуль не зависит от внешних сервисов типа Орфуса и тесно интегрирован с популярными модулями Друпала такими как Rules, Token, Views и Views bulk operations.

Интеграция с модулями Rules и Token, позволяет, например, настроить отправку сообщений о найденных ошибках по е-мейлу, в системный журнал или вызвать любое другое действие, доступное в модуле Rules. С помощью токенов [typo:url], [typo:text] и [typo:comment] в текст сообщения можно включить информацию об опечатке.

Интеграция с Views позволяет сделать вывод списка ошибок на странице, в комплекте с модулем уже идет настроенное представление, а интеграция с Views bulk operations позволяет удалять из этого представления обработанные сообщения.

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

Popup-окно с формой отправки опечатки выводится модулем Ctools и его вид может быть изменён как правкой CSS-файла, так и правкой соответствующего tpl-файла. Ctools — это единственная зависимость модуля, остальные модули (Rules, Views, etc) нужны только если вы хотите использовать соответствующий функционал.

Скачать модуль можно на странице проекта: http://drupal.org/project/typo.

Испытать этот модуль вы можете прямо на этом сайте, список отправленных отчетов об опечатках доступен всем посетителям здесь: http://romka.eu/typo-reports (на реальном сайте к этому представлению анонимам лучше не давать).

upd Модуль упомянули в обзоре в блоге Cocomore, жду наплыва установок на агнлоязычных сайтах :)

Пример конфигурационного файла Varnish

Как обещал в докладе выкладываю пример и описание рабочего конфига для Варниша. Чтобы узнать подробнее о том, что такое Варниш и для чего он нужен ознакомьтесь с разделом Pressflow + Varnish.

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

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

Читать дальше ➠

Обновил этот сайт с шестой версии Друпала на седьмую

Обновление прошло без проблем: ноды, таксономия, комментарии, пользователи переместились без проблем (пользователям, создавшим учетные записи во время переезда, нужно будет запросить новые пароли).

За основу темы оформления взял адаптивную тему Corolla, которую немного допилил под себя в отдельной подтеме. Вообще, Друпал 7 в целом и, в частности, адаптивные темы оформления, созданные под него, сильно впечатляют — это очень мощные инструменты, которые позволяют только настройками и правкой css создавать сайты сложные как по структуре, так и по верстке.

Пока выключены мои кастомные модули, созданные для Drupal 6: блок курсов валют и vk_openapi. В ближайшее время планирую портировать их под семерку.

Старая версия сайта доступна по адресу http://d6.romka.eu.

Кеширование на Drupal-сайте. Сравнение встроенного в Drupal кеша, статического файлового кеша (модуль Boost) и Varnish

Публикую текст своего доклада для Друпалконфа, который прошел 4 июня 2012 года в Москве. Хочу акцентировать внимание на том, что этот текст не адаптирован под блогпост и публикуется в том виде, в котором я рассказывал его на конференции.

Введение

В текущем Drupal 6 проекте, над которым я работаю последние 2 года, в пике мы отдаем до 2 млн просмотров страниц в день и забиваем полностью наш 200-мегабитный интернет-канал. Судя по отчетам нашей системы мониторинга с текущей архитектурой и железом (6 серверов: 2 фронтэнда с nginx, 2 бэкенда с Varnish + Apache + Drupal и 2 MySQL-сервера с master-slave репликацией) мы можем выдерживать втрое большую нагрузку, если решим вопрос с каналом.

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

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

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

Читать дальше ➠

Авторизация на Drupal-сайте с помощью аккаунта ВКонтакте

Разработчики ВКонтакте.ру не так давно открыли доступ к OpenAPI — интерфейсу, позволяющему обычным пользователям авторизоваться на сторонних сайтах с использованием своих учетных записей ВКонтакте.ру.

Я выкладываю первую версию модуля vk_openapi, который интегрирует Drupal 6 с Open API. Демонстрацию работы модуля вы можете увидеть на этом сайте. Кнопка для авторизации с помощью учетной записи вКонтакте находится в форме авторизации (в правой колонке внизу) и на странице с формой входа.

Особенности модуля

  • из учетной записи ВКонтакте выбираются все доступные поля и сохраняются в объекте $user;
  • каждому созданному модулем пользователю автоматически может быть назначена роль;
  • в качестве аватара нового пользователя может быть использован автар из профиля пользователя ВКонтакте;
  • созданный модулем пользователь может быть связан с существующим на сайте аккаунтом.

В ближайших планах: обновление статуса пользователя на основе данных из профиля ВКонтакте.

Скачать модуль можно на drupal.org. В продолжении более подробное описание модуля и инструкция по его установке.

Читать дальше ➠

Несколько статей о Друпале

В течение последнего года я написал три статьи о CMS Drupal, которые были опубликованы в бумажной и электронной версии журнала PC Magazine/RE. Сейчас я публикую “авторские” 1 версии этих статей. Каждая статья разбита на несколько разделов и ниже я привожу ссылки и описания каждого из них.

Первая статья “Разработка сайта на Drupal

  • Часть 1. Введение”. В этой части рассказывается о возможностях Друпала “из коробки”, а также об основных дополнительных модулях. Таксономия, ревизии, мультисайтинг — это совсем не страшно.
  • Часть 2. Архитектура Друпала”. Здесь сказаны общие слова о модульной системе Друпала, механизмах работы с формами, базой данных и кешем. Подробнее эти вопросы будут рассмотрены в следующих разделах и статьях.

После прочтения первых двух частей этой статьи новичок, задающийся вопросом “подойдет ли Друпал для моего нового суперстартапа”, должен на 100% определиться с ответом на этот вопрос. Вообще, в 95% случаев на этот вопрос можно ответить утвердительно, с оговоркой, что работать над проектом будет профессионал хорошо знакомый с Друпалом.

  • Часть 3. Модули Drupal”. CCK, Views, Imagecache, Panels, Ubercart — модули Друпала покрывающие 90% возникающих задач. В этой части статьи даны краткие описания каждого из перечисленных модулей.
  • Часть 4. Интранет-сайт на Друпале. Первый практический пример, в нем разрабатывается интранет-сайт для большой компании. Цель этого раздела — показать возможности, которыми обладает Друпал без доработки напильником. При разработке используются только существующие модули и не написано ни единой строчки программного кода. Аналогичное, только значительно более “кастомное” решение я успешно внедрил в одной из компаний со штатом в несколько сотен человек.
  • Часть 5. Социальная сеть на Друпале”. Точнее не социальная сеть, а коллективный блог с элементами социальной сети. Описание более новой версии примера описанного в этом раздедле можно найти на Швабрешвабр.
  • Часть 6. Оптимизация Друпал”. Этот раздел написал Александр Графов, он же axel. Друпал часто критикуют за низкую производительность. В этом разделе рассказано о приемах, позволяющих “разогнать” движок.

Вторая статья “Пример разработки модуля для Drupal

Третья статья “Темизация Друпал

  • Часть 1. Введение”. Во введении рассказано о шаблонных движках, которые могут быть использованы в Друпале, даны определения основных терминов, использованных в тексте (тема оформления, регион, блок), а также приведено несколько полезных ссылок.
  • Часть 2. Анатомия темы оформления”. Здесь дано подробное описание каждого из файлов-шаблонов, использующихся в темах оформления, а также рассказано о том, как определить отдельный шаблон для каждой страницы или группы страниц.
  • Часть 3. Forms API и темизация”. В этом разделе приводится пример разработки новой и изменения существующей формы с помощью Forms API Друпала, а также о изменении внешнего вида любого элемента формы в отдельности или формы целиком.
  • Часть 4. Темизация Views”. Небольшой раздел, рассказывающий о том, как изменить внещний вид данных, возвращаемых модулем Views.