Отдача мелкой крафики

от автора

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

Понятно, что хранить в базе большие картинки смысла нет. Причин тому много, и все они уже давно всем известны, FileStream пока не рассматриваем. Однако часто возникает задача отдавать с одной страницы большое количество всякой мелочи – например аватарки в блогах или соцсетях, картинки-превью к новостям в лентах, и т.д., т.е. относительно лёгкую графику, но в товарных количествах. Беда в том, что отдача каждой такой картинки создаёт отдельный коннект к серверу, в итоге загрузка одной страницы порождает несколько десятков запросов на отдачу всякой мелюзги, общий объём которой на странице не превышет может быть сотни килобайт. Для нынешних каналов это ничто, а вот куча запросов к серверу при рендеринге страницы – это плохо. Особенно учитывая особенности блочной вёрстки, которая в отличие от табличной заставляет браузер интенсивнее «бомбить» сервер запросами на отдачу мелкой фигни, которую ещё и кешировать нельзя, т.к. она может меняться.

Довольно интересным представляется решение, при котором вся эта мелочь пузатая будет отдаваться в один поток. Таким образом мы на порядок снижаем количество запросов к серверу, а значит повышаем стойкость сайта к DDoS-атакам. В качестве приятного бонуса – перспектива прокачать юзабилити: все картинки будут возникать на странице сразу (без эффекта «подгрузки»), одновременно и без «дырок». Небольшая пауза перед их появлением не в счёт, субъективно такая загрузка выглядит «шустрее».

Видится примерно такая схема: в тексте HTML-файла ставятся плейсхолдеры с ID, соответстветствующими картикам в базе. Javascript «пробегает» по плейсхолдерам и формирует строку XMLHTTP-запроса, в ответ на который сервер возвращает массив base64-закодированных строк, которые опять же джаваскрипт рассовывает по src соответствующих плейсхолдеров.

В итоге вместо получения пары десятков отдельных картинок вестом по 2-5кБ мы получаем JSON-строку объёмом 50-100кБ за один асинхронный запрос. То есть а) уже ПОСЛЕ того, как прогрузится и отрендерится основной текстовый контент, и б) гораздо быстрее за счёт особенностей стриминга текстовых данных.

Рабочий пример (аватарки надёрганы из сети).

Код можно посмотреть в исходнике страницы. Сервлет на PHP (работает с SQLite) выглядит так:

<? ob_start(); $dbh = sqlite_open('data/img', 0666, $sqliteerror); $sth = sqlite_query($dbh, "SELECT *, ROWID AS id FROM img WHERE ROWID IN (".trim($_GET['q']).") LIMIT 20"); $res = sqlite_fetch_all($sth, SQLITE_ASSOC); echo json_encode($res); sqlite_close($dbh); ob_end_flush(); ?>

Что скажете, совсем дурацкая идея? Или я велосипед изобрёл?

ссылка на оригинал статьи http://habrahabr.ru/post/157661/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *