LINUX.ORG.RU
решено ФорумAdmin

Организация своего мини CDN


0

2

Доброго времени суток, ув. ЛОРовчане.

Есть веб-сервис, который в перспективе будет иметь свыше миллиона уникальных посетителей в день(по крайней мере так ставится задача). Если взглянуть на него админским взглядом, то это несколько тысяч виртуальных хостов и насколько миллионов файлов мелкой статики (jpg, png, css. js). Возникла необходимость организовать что-то типа своего мини CDN куда и вынести всю статику из веб-приложения, генерить ссылки на статику типа static.domain.com и резолвить айпишник этого сабдомена в зависимости от гео-позиционирования клиента. С этим, в принципе, все просто и ясно. Возникает вопрос лишь в том, как хранить сами файлы. Единственное что приходит на ум - хранить сами файлы в MongoDB (GridFS) и дергать их враппером отдавая nginx-ом. Даже есть идея написать простенький модуль для nginx, который бы это реализовывал. Сами базы реплецировать между серверами в мульти-мастер режиме. Для оказания высокой доступности серверов со статикой со стороны приложений планируется применять haproxy в режиме TCP балансирования. Добавлений файла будет не так много, так что латентность подключения веб-приложения к БД со статикой не сильно важна.
Есть еще вариант построить кластер на базе Ceph. Но я не думаю, что для такой узко-специализированной задачи это является оптимальным решением.
Цель всего этого:
- организовать максимальную скорость доступа к статическим файлам
- высокую доступность
- высокую надежность хранения
- оптимальное использование серверных ресурсов

Если кто-то сталкивался с подобного рода задачами либо просто имеет идеи относительно данного ТЗ, просьба поделиться своим мнением.

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

Заранее очень благодарен.

★★★★★

Возникает вопрос лишь в том, как хранить сами файлы. Единственное что приходит на ум - хранить сами файлы в MongoDB (GridFS) и дергать их враппером отдавая nginx-ом.

Зачем MongoDB? Почему недостаточно обычной FS и стандартного линуксового дискового кеша в памяти (память дешёвая, а статики как я понял не слишком много).
Просто есть такое дело: MongoDB и прочие NoSQL сейчас в моде и сильно пропиарены, из-за этого их часто используют тогда когда не следует. Так-что полагаю полезно лишний раз задать себе вопрос «а действительно-ли это хорошее решение моей задачи?».

MrClon ★★★★★ ()

Надо cdn — делай cdn, в чём проблема?

anonymous ()
Ответ на: комментарий от MrClon

Зачем MongoDB? Почему недостаточно обычной FS и стандартного линуксового дискового кеша в памяти (память дешёвая, а статики как я понял не слишком много).

Статики планируется много. Если хранить просто на винте, тогда как организовать отказоустойчивость и балансировку нагрузки? Городить файловый кластер не выход.

iron ★★★★★ ()
Ответ на: комментарий от iron

А как вы планируете организовать отказоустойчивость и балансировку нагрузки при использовании MongoDB? Точно так-же, DNS балансировкой и избыточностью копий данных (которую в любом случае подразумевает CDN).
Вообще какая разница между файловым кластером и БД-кластером? С точки зрения приложения разница только в том что на файловый кластер ему придётся раскладывать файлы самому, а в случае с БД-кластером файл отдаётся первой попавшейся мастер-ноде, а дальше она сома творит какую-то «магию». Как по мне ручная раскладка по нодам лучше, её гораздо проще контролировать.

Кстати про хранилища данных и CDNы есть интересная лекция от яндекса, рекомендую http://events.yandex.ru/events/kit/3/talks/524/

MrClon ★★★★★ ()

Рекомендую сделать связку на следующих технологиях:

  • lighttpd/nginx
  • OCFS - как распределенная фс. Либо rsync, если так проще.
  • haproxy - если не умеете готовить nginx для балансировки
gh0stwizard ★★★★★ ()
Ответ на: комментарий от MrClon

А как вы планируете организовать отказоустойчивость и балансировку нагрузки при использовании MongoDB?

Я это уже описал. Несколько серверов с MongoDB мульти-мастер репликацией. Отказоустойчивость - haproxy в режиме TCP балансинга.

Точно так-же, DNS балансировкой и избыточностью копий данных

DNS балансировщик будет брать данные о живучести каждого сервера с haproxy.

Как по мне ручная раскладка по нодам лучше, её гораздо проще контролировать.

Так файло будет раскладываться приложением. И в случае сбоя, на одной из нод будут неактуальные данные. Как трекать свежесть файла? Как определить, что на первой ноде файло свежее чем на второй? Логи самому писать? Без какого-то транзакционного решения ИМХО тут не обойтись.

Спасибо за линк, посмотрю.

iron ★★★★★ ()
Ответ на: комментарий от gh0stwizard

OCFS - как распределенная фс. Либо rsync, если так проще.

Я больше склоняюсь к Ceph. Но опять же, не хотелось бы строить файловый кластер.

haproxy - если не умеете готовить nginx для балансировки

Дело тут не в умении готовить nginx, а в количестве фич самой балансировки и мониторинга этого процесса. По сему выбор пал на haproxy.

iron ★★★★★ ()
Ответ на: комментарий от iron

Но опять же, не хотелось бы строить файловый кластер.

Не смущает сколько жрет CPU монго? Вы хорошо ее тестировали? Просто подумайте, что в случае с монго у вас будет дополнительный внутренний трафик между нодами, равно такой же сколько будет клиентов. ИМХО, это лишний оверхед. В случае с дисковым хранилищем, кол-во серверов можно уменьшить в два раза. Или вы думаете, что ваш скрипт под nginx ничего не будет жрать? Для него тоже надо выделять ресурсы, в данном случае cpu+network. GridFS - это такая же bson-(де)сериализация, как и с обычными данными. Если все устраивает, то отговаривать вас я не стану.

gh0stwizard ★★★★★ ()
Последнее исправление: gh0stwizard (всего исправлений: 1)
Ответ на: комментарий от gh0stwizard

Просто подумайте, что в случае с монго у вас будет дополнительный внутренний трафик между нодами

Дополнительный трафик будешь лишь при запросах на добавление/обновление файлов, которых будет довольно мало.

Или вы думаете, что ваш скрипт под nginx ничего не будет жрать?

Сам скрипт будешь всего лишь вынимать данные из базы. По сему узким местом скорее всего будет БД, а не скрипт.

Если все устраивает, то отговаривать вас я не стану.

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

iron ★★★★★ ()
Ответ на: комментарий от iron

Дополнительный трафик будешь лишь при запросах на добавление/обновление файлов, которых будет довольно мало.

Т.е. nginx будет там же где реплика монги? Смысл тогда в ней? Чтобы воспользоваться плюшками репликации? Странные...

По сему узким местом скорее всего будет БД, а не скрипт.

У вас немного альтернатив для клиента, под nginx лишь драйвер на пхп и перле. Ни тот, ни другой не являются отличными драйверами в плане производительности. Да, они устраивают большинство, но вы не из их числа? Я к тому, что вы ищите легкий путь, готовое решение, якобы без проблем и полностью вас устраивающее. Но уже сказали, что это не та задача, где монго будет рулить и педалить. Запустите стенд с 7-11 серверами монги, да потестируйте ее. Пока еще есть время.

gh0stwizard ★★★★★ ()
Ответ на: комментарий от iron

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

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

*http://ru.wikipedia.org/wiki/Теорема_CAP

Можно узнать поподробнее про контент? Правильно-ли я понимаю что есть малая часть отвечающая за оформление сайта (js, css, всякие там иконочки) и большая часть заливаемая пользователями (или около того). Мне кажется разумным рассматривать их как отдельные сущности.
Файлы являющиеся частью оформления сайта будут, очевидно, регулярно обновляться. При-чём не абы как, а в процессе выкатывания новой версии сайта.
Файлы пользователей скорее всего будут изменяться редко. Можно ощутимо упростить себе жизнь если вообще не изменять их, а заливать новые с новым именем и отдавать клиентам уже новый URL. Старую версию можно либо просто оставить валяться где есть (как делает например вконтакт), либо забить нулями (для приватности), можно удалять и иметь проблемы с фрагментацией.

MrClon ★★★★★ ()

если только статика, то что мешает делать сеть кэширующих http серверов, например на основе Varnish со связью по ICP? Тем более, если будет географическое распределение. Мы так и сделали, результаты — не хуже Akamai при весьма нехилой нагрузке.

val-amart ★★★★★ ()
Ответ на: комментарий от gh0stwizard

Т.е. nginx будет там же где реплика монги? Смысл тогда в ней?

Да, там где монга. Чтоб максимально быстро отдавать сонтент из базы.

У вас немного альтернатив для клиента, под nginx лишь драйвер на пхп и перле. Ни тот, ни другой не являются отличными драйверами в плане производительности.

Да, есть такое. Но, как я писал в первом посте, какой прослойкой отдавать - вопрос пока открытый и далеко не самый важный.

Запустите стенд с 7-11 серверами монги, да потестируйте ее. Пока еще есть время.

Так и планирую сделать.

iron ★★★★★ ()
Ответ на: комментарий от MrClon

Тут странно говорить о баллансировке нагрузки, в любом случае запись нового файла должна быть произведена на все ноды, какая разница какую из них пнёт непосредственно приложение?

Разница заключается в том, что нужно писать в запущенный сервер. А если один из серваков отвалится то и приложение файл не запустится. Правда можно делать проверку доступности ноды перед записью. Но хочется сделать все максимально прозрачно для приложения.

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

Общая идея очень хороша, спасибо. Но здесь без переписывания приложения не обойтись. И в данный момент никто не будет переписывать его. Возможно со временем перепишут.

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

Да, все именно так и есть. Пока что стоит задача раздавать только статику. Позже планируется раздавать тяжелый контент (HD видео).

Файлы являющиеся частью оформления сайта будут, очевидно, регулярно обновляться. При-чём не абы как, а в процессе выкатывания новой версии сайта.

Статика - это по большему счету файлы которые будут заливать пользователи. У них есть возможность менять картинки и оформление в своей панели.

Файлы пользователей скорее всего будут изменяться редко. Можно ощутимо упростить себе жизнь если вообще не изменять их, а заливать новые с новым именем и отдавать клиентам уже новый URL. Старую версию можно либо просто оставить валяться где есть (как делает например вконтакт), либо забить нулями (для приватности), можно удалять и иметь проблемы с фрагментацией.

Если речь идет о мелких файлах, то можно их забросить на раздел с reiserfs. Но в этом случае будет фрагментация. Либо использовать xfs и по ночам дефрагментировать.

iron ★★★★★ ()
Ответ на: комментарий от val-amart

если только статика, то что мешает делать сеть кэширующих http серверов, например на основе Varnish со связью по ICP? Тем более, если будет географическое распределение. Мы так и сделали, результаты — не хуже Akamai при весьма нехилой нагрузке.

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

iron ★★★★★ ()
Ответ на: комментарий от iron

Разница заключается в том, что нужно писать в запущенный сервер. А если один из серваков отвалится то и приложение файл не запустится. Правда можно делать проверку доступности ноды перед записью. Но хочется сделать все максимально прозрачно для приложения.

Вы-же понимаете что «сделать прозрачно для приложения» означает «скрыть от приложения»? Вообще странный получается термин.
Это увеличивает риск что когда (не «если», а «когда») в хранилище что-то пойдёт не так приложение об этом просто не узнает.
Вообще процесс записи на описанный мной кластер я вижу следующим образом: приложение синхронно или асинхронно отправляет файл на все ноды, дожидается подтверждения от как минимум большинства нод (в подтверждении может содержаться хэш файла, что-бы быть уверенным что файл получен без повреждений). Те ноды которые не ответили после n попыток либо выбратываются из кластера (их IP не отдаются клиентам) либо просто заливка этого файла на них откладывается на больший срок. Если не удалось залить файл на большинство нод значит заливка не удалась, ошибка.
Впрочем это всё нужно додумывать.

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

MrClon ★★★★★ ()
Ответ на: комментарий от iron

Расскажите пожалуйста подробнее как вы видите алгоритм работы такого решения (мне нужно будет сформулировать ее программерам).

Программерам практически не нужно ничего знать или делать. Они ведь программеры, все равно не осилят ;)

Нужно настроить ферму прозрачных кеширующих проксисерверов, возможно в иерархии (если есть такая необходимость). Кроме Varnish, рекомендую обратить внимание на Apache Traffic Server, он поддерживает WCCP. хз что у них обоих с HTCP, мне ICP достаточно. Для очистки кеша нужно просто послать http запрос типа purge. Если не сработает (а у нас когда использовали Bluecoat такое бывало) — просто вынимаете проблемный сервер из фермы, останавливаете, чистите полностью кеш, рестартуете, проверяете, пулите назад в ферму. Все это конечно легко скриптуется, прикручиваете апи, приложение просто дергает апи если надо инвалидировать обьект. а вообще по правильному надо делать не так — если обьект меняется, надо создавать новый обьект, по новому URI, и уже на него ссылаться. потому что не все кеши вы контролируете и соответственно клиент может все равно видеть устаревший контент. Если статики много, и обьем «горячего» кеша не влазит в ОЗУ, потребуется кеш партиционировать (в доках все отлично описано). Вы тут упамянули стриминг видео, это тоже отлично кешируется, точно такими же методами (но есть конечно специфика... долго и много писать лень, извините, может как-нибуть в блог). При любом расскладе, рекомендую статику всю загнать на одино отдельное dns имя, и раздавать оттуда с правильными заголовками кеширования (чтобы на кеширующих серверах кеширование не приходилось форсировать, и они знали, сколько время жизни обьектов).

val-amart ★★★★★ ()

http://reverbrain.com/blog/

Под элиптик репы сделали. Но вы уточните сначала, нужно ли вам распределенное kv или хватит проксей.

Vit ★★★★★ ()
Ответ на: комментарий от MrClon

Вы-же понимаете что «сделать прозрачно для приложения» означает «скрыть от приложения»? Вообще странный получается термин.

Это увеличивает риск что когда (не «если», а «когда») в хранилище что-то пойдёт не так приложение об этом просто не узнает.
Все верно. Самое главное то, что запись будет выполнена. Все остальное - забота самого «файл-кластера».

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

Очень хороший алгоритм, спасибо.

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

Если через кеш будет ходить только не модифицируемый пользовательский контент то выбрасывать ненужно можно будет тупо по таймауту.
Так оно примерно и будет в будущем. Я постараюсь четко разделить шаблонную статику и юзер-генерейтед контент.

iron ★★★★★ ()

Решил остановится на решении с кешированием. Пока что еще не определился со всеми техническими деталями решения (будет ли это Varnish или кто-то другое). Сначала устрою дебаты с командой программеров и тогда уже приму окончательное решение.

Ребята, всем большое спасибо за участие в обсуждении. Высказав свое мнение вы позволили мне шире и глубже взглянуть как на ТЗ, так и на возможные варианты решения.

iron ★★★★★ ()

Посмотри в сторону PeerCDN.

devl547 ★★★★★ ()
Ответ на: комментарий от devl547

Посмотри в сторону PeerCDN.

Очень интересная штука, спасибо. Для тяжелого контента в самый раз.

iron ★★★★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.