Карта сайта для поисковиков (Sitemap) в Zend Framework приложении

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

Задача

Создать карту сайта(sitemap.xml/sitemap.txt) для большого сайта на Zend Farmework.

Решение

Необходимо создать список публично доступных-страниц сайта, т.е. ссылок на них. Ссылки в нормальном ZF-приложении генерятся через Url Helper:

А значит у нас есть единая точка генерации ссылок. Это позволит нам составить список ссылок для карты сайта.

Нашей первой идеей было пробежаться по всем маршрутам (по которым url хелпер строит ссылки) и сгенерить ссылкы на основе маршрутов и данных из БД. Это оказалось плохой затеей, т.к. данных в базе было много, ссылок тоже и время генерации карты сайта выходило за все разумные пределы.

Второй идеей было перехватывать вызовы url-хелпера и журналировать их в БД, а потом уже на основе журнала генерировать sitemap. Т.е. сделать БД буфером между запросами хелпера и файлом sitemap. У этой идеи был свои недостатки. На каждую ссылку на странице делалось два запроса к БД: один на чтение из таблицы sitemap (а была ли уже такая ссылка) и второй на запись (создание новой записи или обновленеи времени доступа существующей). Если на странице 80 ссылок, то имеем + 160 запросов к БД. Не вариант.

Тогда на ум пришла третья идея. А что если буферизировать вызовы хелпера в приложении. Т.е. по ходу генерации страницы собираем в массив все ссылки, а потом… нет, не пишем в БД, ведь тогда надо опять же проверять существование ссылок… отправляем задачу на сервер очередей.

Солюшен

  1. Журналируем вызовы url-хелпера и складываем их в массив в локальной переменной.
  2. Перед отдачей результатов рендеринга страницы пользователю отправляем задание с этим массивом  в очередь.
  3. Отдаем страницу.
  4. Демон очереди получает задачу и в фоновом режиме (может даже на отдельном сервере) и осуществляет чтение/запись в БД.
  5. Где-нибудь ночью запускается cron-скрипт, который на основе подготовленных демоном данных в БД генерирует карту сайта.ъ
  6. PROFIT! 🙂

Преимущества

  • Нет оверхеда при генерации страницы, только быстрая отправка задания в очередь.
  • Актуальность карты сайта = период запуска крон скрипта.
  • Потенциально неограниченный размер карты сайта, за счёт разделения работы между подсистемами и фоновой генерацией карты.

Недостатки

  • Нужен сервер очередей 🙂
  • Все ссылки на сайте должны генерироваться через URL хелпер.

На самом деле в нормальном проекте всё так и есть. Если нет, это повод задуматься. Думаю эта заметка будет полезной для ZF разработчиков.

Токарчук Андрей