Разные, на мой взгляд, интересные замечания, связанные с компьютерами в частности и техникой вообще.

суббота, 26 февраля 2011 г.

Ошибка Drupal и ImageCache при использовании nginx в качестве проксирующего web-сервера

Есть у меня под присмотром один сервер. Сервер это находится чёрт знает где, а компания, которая предоставляет его довольно жадная. На сервере около 20-ти разнообразных сайтов и на всё про всё 192 метра оперативки. Вот, недавно нагрузка окончательно стала добивать его, поэтому было решено воткнуть nginx как фронтенд как установленному там апачу(изначально не сделал так, потому как там не полноценный сервер, где что хочу, то и творю, а выделенный в chroot на FreeBSD). Собрал, поставил, настроил. Всё хорошо, нагрузка упала, но через некоторое время на части сайтов(те, что с Drupal, как раз) не отображались уменьшенные изображения залитых после перехода на связку nginx+apache картинок.


Долго пытался понять, в чём дело, перепроверил все, связанные с файлами настройки nginx, но так и не мог понять, в чём проблема. В итоге, взялся смотреть, что вообще происходит на сервере при загрузке любого изображения на проблемных сайтах. И выяснилось, что всё нормально работает, картинки загружаются и даже вполне себе доступны по прямому пути, а не отображаются только превьюшки. Тут и выяснилось, что проблема не в самом nginx, а в php'шном модуле ImageCache и Drupal'е. Я не знаю, кто этот костыль придумывал и откуда у него руки, но работает эта штука по такой вот схеме:
1. Картинка загружается, в базе создаётся соответствующая запись, но превьюшки ещё нет.
2. Пользователь заходит на страницу, где должна быть превьюшка, движок видит, что её нету по ссылке, перехватывает на себя 404-ую ошибку и с помощью ImageCache генерит превьюшку, которая тут же замечательно отображается.
3. Превьюшка сохраняется на диске, поэтому в дальнейшем заново ничего генерить не надо.
Это же только вдуматься надо. Создавать обычный контент, провоцируя критическую для такого случая ошибку!
Почему нельзя было сгенерить превьюшку сразу, я не знаю. Видимо, это показалось разработчикам слишком уж обычно, что ли. Не знаю, как по-другому сказать. И, честно говоря, не знаю, кто придумал такое решение разработчики drupal'а или imagecache. Разбираться было лень - не люблю ни друпал, ни всё, что связано с php.
Разумеется, при использовании nginx как проксирующего сервера и настройке грамотной отдачи статики без привлечения апача, он пытался отдавать превьюшки сам. Но ведь их нет. Апач-то с php никакого запроса не получали. И drupal с imagecache ничего не сгенерировали. И потому вместо превьюшек nginx честно отдавал 404.
В общем, решилось дело добавлением вот такого вот костыля в описание каждого виртхоста с drupal'ом и imagecache:
location @d_ic_hook {
  proxy_pass              http://sitename:8080;
  proxy_set_header        Host   $host;
  proxy_set_header        X-Real-IP  $remote_addr;
  proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
}
location ~* $images {
  root /path/to/site/root;
  error_page 404 = @d_ic_hook;
  proxy_cache_valid 404 1m;
}
Т.е. я вместо того, чтобы выдать свою обычную nginx'овскую 404-ую ошибку, принудительно перенаправляю любую 404-ую ошибку на апач, а тот уже отрабатывает её так, как ему нужно.
Превьюшки появились, пользователи довольны, а я ещё раз для себя на всякий случай отметил как делать не надо, если надумаю писать какую-нибудь программу или скрипт.

UPD: Грамотные люди подсказывают, что виноват именно ImageCache. 

2 комментария:

  1. Большое спасибо!! Ваш пост помог понять проблему, правда пришлось повозиться чтобы понять что такое @d_ic_hook и применить у себя на сайте. Но без вашего поста ничего бы не получилось. Спасибо!

    ОтветитьУдалить
  2. Пожалуйста.
    Приятно, что информация оказалась полезной.

    ОтветитьУдалить