Как сделать CDN для своего сайта и почему это полезно для высоконагруженных проектов

в 13:47, , рубрики: CDN, highload, sports.ru, Блог компании Sports.ru, метки: , ,

Главная задача отдела эксплуатации Sports.ru и Tribuna.com — масштабирование сетевой инфраструктуры в условиях постоянного роста трафика (за 1,5 года трафик и кол-во запросов в секунду выросло в два раза), регулярных пиковых нагрузок и аудитории, распределенной по разным странам. Для решения этой задачи мы используем разные технологии; одна из них — создание собственной CDN (сети доставки контента), которая позволяет сократить нагрузку, усилить защиту от DDoS-a и ускоряет загрузку сайта в удаленных регионах. Мы решили поделиться своим опытом в этой области и составили краткое практическое руководство для системных администраторов по разворачиванию и эксплуатации своей CDN.

I. Теория.

1. Терминология.

Сеть доставки (и дистрибуции) контента (англ. Content Delivery Network или Content Distribution Network, CDN) — географически распределённая сетевая инфраструктура, позволяющая оптимизировать доставку и дистрибуцию контента конечным пользователям в сети Интернет. Использование контент-провайдерами CDN способствует увеличению скорости загрузки интернет-пользователями аудио-, видео-, программного, игрового и других видов цифрового контента в точках присутствия сети CDN.

Так говорит нам всезнающая wikipedia. Но как же устроена эта CDN? Давайте сразу определимся со склонениями. CDN — это бла-бла-бла сеть. Сеть — женского рода, соответственно склоняем аббревиатуру в женском роде.

С точки зрения как это работает, можно написать следующую формулу:

CDN=anycast+proxy.

О anycast можно прочитать здесь ru.wikipedia.org/wiki/Anycast, если кому-то нужно вспомнить что такое Proxy-server, пробелы в знаниях можно восполнить тут: ru.wikipedia.org/wiki/%D0%9F%D1%80%D0%BE%D0%BA%D1%81%D0%B8-%D1%81%D0%B5%D1%80%D0%B2%D0%B5%D1%80

Фактически это технология сводится к анонсированию сетевого адреса, в который резолвится сайт, помещенный в CDN, из этих “географически распределённых мест” и проксированию запросов к условному одному серверу.

Какой профит из этого можно получить?
Размещая данные ближе к клиенту, вы получаете меньшую задержку в ответе для пользователя, сокращаете нагрузку на свой сервер, защита от DDoS… бла-бла-бла — читаем описание любой коммерческой CDN-сети.

Кажется сложным и непонятным? На самом деле это проще чем кажется, ниже всё будет описано более подробно.

2. Почему свой CDN, а не консалтинг.

Возникает вопрос, а для чего же делать свою CDN? Много прекрасных CDN-сетей, используй.
Во-первых, это не наш метод ;)
Во-вторых, эти сети уже построены, и не факт, что они подходят вам по распределенности на все сто. В случае своей CDN мы вольны где угодно размещать её узлы.
В-третьих, мы вкладываем деньги в свою инфрастурктуру, а не в чужую.
В-четвёртных, настроить свою CDN мы можем как угодно. Кешировать можно не только статические данные, но и динамические, например, данные для аннонимусов или общие данные. Такой гибкости нам ни одна коммерческая сеть в полном объёме не даст.

3. Профит от использования.

Итак, что же конкретно можно получить от своей CDN-сети:

Скорость загрузки/сокращение трафика.
Размещая данные ближе к пользователю можно рассчитывать на то, что эти данные он быстрее получит. Логично. Что с сокращением трафика? Кеширование данных на узлах, позволяет сократить число обращений к “главному серверу”. Плюс, мы можем всегда передавать сжатые данные от главного сервера к узлу CDN, в keepalive-соединениях. Можно настроить узел CDN так, чтобы конкурирующий запросы, которые мы кешируем, не выполнялись параллельно. Это тоже позволяет экономить трафик и процессорное время на “главном сервере”. В случае sports.ru это всё в сумме позволяет сократить число запросов и трафик в 3,5 раза к “главному серверу”.
Так же узел CDN является прекрасным местом для размещения DNS-slave сервера. Собственно, по тем же причинам.

II. Практика.

4. Необходимые условия.

Для того, чтобы сделать свой сервер CDN нам понадобится сам сервер, своя AS ru.wikipedia.org/wiki/%D0%90%D0%B2%D1%82%D0%BE%D0%BD%D0%BE%D0%BC%D0%BD%D0%B0%D1%8F_%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D0%B0_(%D0%B8%D0%BD%D1%82%D0%B5%D1%80%D0%BD%D0%B5%D1%82) и свободный ip-routenum, в котором мы и будем размещать свой CDN. Свободных IPv4 — сетей уже практически не осталось, но никто не мешает использовать эту статью для IPv6 истории :)

Нужно ещё будет как-то проксировать и сохранять ответы приходящих запросов.
Отказоустойчивость будем решать тем фактом, что Proxy и Anycast будем собирать на одном сервере. Если по каким-то причинам он отключится, это никак не повлияет на всю CDN в целом. Естественно, таких серверов должно быть как можно больше ;)

5. How To.

Для реализации всего задуманного потребуется потребуется сервер с несколькими физическими ядрами для распределение нагрузки сетевой карты на каждое ядро. Достаточное количество оперативной памяти для помещения всего кеша в рамдиск. Мы же не хотим нагружать диски на сервере за тридевять земель? ;) Сетевая карта с поддержкой распределения нагрузки на разные ядра процессора, для того чтобы иметь большую пакетную производительность. И RAID1 на SATA дисках для пущей надёжности.

А ещё это дело надо правильно настроить, чтобы заставить работать в полною силу. Тюнингу под большие веб-нагрузки и выжиманию всех соков из железа хорошо подходит FreeBSD 9.x. Можно использовать и Linux, но в плане прозрачноcти и простоты настройки, единого типа конфигов в моём личном рейтинге выигрывает FreeBSD.
Чтобы не повторятся приведу примеры дельных рекомендаций по настройки FreeBSD под аналогичный тип нагрузки:

dadv.livejournal.com/139170.html
serverfault.com/questions/64356/freebsd-performance-tuning-sysctls-loader-conf-kernel

или погууглить на соотвествующую тему.

Анонсируемую сеть или часть этой сети я предлагаю разместить на интерфейсе локальной петли:

добавляем строчки в /etc/rc.conf:

ifconfig_lo0_alias0=«inet <ip-адрес CDN1>/32»
ifconfig_lo0_alias1=«inet <ip-адрес CDN2>/32»

и, конечно, не забыть включить маршрутизацию:

добавляем строчки в /etc/sysctl.conf:

net.inet.ip.forwarding=1

Включаем электронный диск для кеша данных, будем использовать для этого tmpfs:

добавляем строчки в /boot/loader.conf:

tmpfs_load=«YES»

и /etc/fstab:

tmpfs /mnt/tmpfs tmpfs rw,mode=777 0 0

Анонсировать сеть CDN будем через OpenBGP:
www.freshports.org/net/openbgpd/

Он обладает всем необходимым функционалом и просто настраивается. Скупая информация о нём в интернете нивелируется подробным Man-ом. Так же он может интегрироваться с пакетным фильтром PF, если нам захочется использовать его. Вот простой конфиг, который будет делать всё, что необходимо:

/usr/local/etc/bgpd.conf:

AS <номер нашей AS>
router-id <router-id>
network <анонсируемая сеть>
group «Uplink» {
neighbor <адрес провайдера> {
remote-as <AS провайдера>
descr «Uplink»
announce self
}
}
deny from any
deny to any
allow from <адрес провайдера>
allow to <адрес провайдера> prefix <анонсируемая сеть>

Перейдём к настройке Nginx. Фактически нам необходимо настроить на Nginx кешируюший статику proxy-сервер c агрегацией и сжатием остальных запросов и кеширумых данных.

Не забываем при сборке Nginx указать сборку с модулем gunzip, для разжимания данных для клиентов, не поддерживающих сжатие.

nginx.conf:

worker_processes auto;
http {
include mime.types;
proxy_temp_path /mnt/tmpfs/tmp;
proxy_cache_path /mnt/tmpfs/cache/site_cache levels=1:2 keys_zone=site:128m max_size=<размер кеша> inactive=<время, которое хранятся данные а кеше>;
gzip on;
gzip_disable «msie6»;
gzip_comp_level 4;
gzip_types text/plain text/html application/xml application/x-javascript text/javascript text/css application/json text/xml application/rss+xml;
gunzip on;
server {
listen 80 default;
server_name localhost;
location / {
proxy_cache_use_stale updating timeout http_500 http_502 http_504;
proxy_cache site;
proxy_cache_key $uri$is_args$args;
proxy_pass frontend;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host;
}
location ~* .(3gp|7z|avi|bmp|css|doc|docx|gif|gz|jpg|jpeg|js|mov|mp3|mp4|ogg|png|ppt|pptx|rar|tar|tiff|torrent|ttf|svg|swf|wma|xls|xlsx|xsl|xslt|zip)$ {
proxy_cache_use_stale timeout updating http_500 http_502 http_504;
proxy_cache site;
proxy_cache_key $uri$is_args$args;
proxy_cache_valid <время на которое кешируем статику>;
proxy_pass frontend;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host;
}
}
upstream frontend {
server <адрес фронтенда>;
}

Если по каким-то причинам не нужно кешировать динамические запросы на сайте, выключаем кеширование в секции location /. Раскешировать статические данные можно, изменив в них GET-парамметр, например, указывая номер ревизии.

Bind.
Тут всё просто, устанавливаем и добавляем строчки в named.conf:

zone «site.ru» {
type slave;
file "/etc/namedb/slave/site.ru";
masters {
<ip-адрес днс-мастер-сервера>;
};
};

Не забываем разрешить скачивание всей DNS-зоны c мастер-сервера.

That’s all! CDN-сервер настроен. Немного будет переделок, если захочется CDN-нить ещё несколько сайтов ;)

Автор: forwardfly

Источник

Поделиться

* - обязательные к заполнению поля