|<<
<
>
>>|
/
Простая CDN своими руками Сергей Хоменков ---- CDN = Content Delivery Network = Сеть доставки (и дистрибуции) контента {{http://ru.wikipedia.org/wiki/CDN}} ---- Задача: Ваш сайт у пользователя должен открываться и работать быстрее ---- Все рекомендации серии «{{Разгони свой сайт|http://webo.in/}}» вы уже выполнили ---- {{img src="img/webday_yslow.png" width="698" height="429"}} Отчёт {{YSlow|http://developer.yahoo.com/yslow/}} о {{webday.info||http://webday.info}} ---- Осталась быстрая доставка данных пользователю ---- Решаем проблемы: - Не справляется один сервер - Пользователи далеко от данных ---- Не справляется один сервер? Ставим два! Но как? ---- Первым делом вам нужен отдельный (под)домен для отдачи статических файлов ---- Для начала пусть это будет {{i.site.ru}} ---- И используем DNS-балансировку ---- В доменной зоне site.ru создаём две записи: i.site.ru IN A 10.0.0.1 # сервер №1 IN A 10.0.0.2 # сервер №2 ---- Пример: > nslookup i.r0.ru Name: i.r0.ru Addresses: 81.19.66.95, 81.19.66.94 ---- Теперь запросы на {{http://i.site.ru/xxx.jpg}} будут распределяться по обоим серверам ---- Но все данные остались на сервере №1 Новый контент заливают туда же ---- Варианты: ---- 1. Синхронизировать содержимое Новые данные заливать на оба сервера ---- Это трудоёмко и требует модификации кода (иногда стороннего) ---- 2. Автоматически копировать новые данные с сервера №1 => №2 Например через {{#v|rsync}} каждые N минут ---- - Тратятся ресурсы на синхронизацию даже если данные не изменились - Получаем задержку появления данных на сервере №2 в N минут ---- 3. Обновлять данные на сервере №2 по запросу от клиента ---- Например на сервер №2 поставить кеширующий прокси сервер общего назначения ({{#v|squid}}) или специализированный ({{#v|nginx}}) ---- - Имеем минимальные затраты на поддержку актуальности данных. - Для сервера №1 создаётся дополнительный трафик, как от ещё одного клиента. ---- Все способы имеют право на существование и используются в живой природе ---- Вариант с проксированием (№3) прост в настройке и легко тиражируется на несколько серверов ---- Сервер №2 nginx.conf: {{#v|http}} { {{#v|proxy_cache_path}} {{#i|/var/nginx/cache}} levels=1:2 keys_zone={{#i|CACHE}}:10m inactive=1h; {{#v|upstream}} {{#i|site_ru}} { server 10.0.0.1; } {{#v|server}} { {{#v|server_name}} {{#i|i.site.ru}}; {{#v|location}} / { {{#v|proxy_pass}} http://{{#i|site_ru}}; {{#v|proxy_set_header}} Host $host; {{#v|proxy_cache}} {{#i|CACHE}}; {{#v|proxy_cache_valid}} 200 1h; } } } } ---- Этот интуитивно понятный конфиг ☺ проксирует запросы на IP 10.0.0.1 и кеширует ответы на 1 час ---- {{img src="img/ngenix_hp_web.png" width="570" height="385"}} {{ngenix.net|http://ngenix.net}} ---- Для справки: Свет может облететь Землю 7.5 раз за 1 секунду ---- Москва — Лос-Анджелес ~9800 км 32 мс туда и 32 мс назад ---- {{img src="img/moscow-la-map.png" width="599" height="398"}} Путь по поверхности Земли на {{WhoYOUgle|http://whoyougle.ru/place/distance/?from_which=524901&to_which=5368361}} ---- Плюс задержки на приём-передачу на каждом роутере по пути ---- Лишние задержки и (относительно) более узкие каналы ⇨ меньшая скорость загрузки ---- Усложняем задачу: Выносим второй сервер к другому провайдеру, в другой город, страну, континент ---- Задача: Как заставить браузер клиента обращаться к серверу, который к нему ближе? ---- Разделим клиентов по IP-адресам ---- Адресам присвоим метки ip2geo.conf: 89.249.48.0/21 comptek; 62.122.184.0/21 ssi; 84.42.48.0/21 ctcs; … ---- Или возьмём базу российских городов на {{ipgeobase.ru|http://ipgeobase.ru}} (Ru-Center), или стран на {{wipmania.com|http://wipmania.com}}, или международную базу на {{maxmind.com|http://maxmind.com}} ---- Для формата данных {{#v|MaxMind}} есть специальные модули под {{#v|nginx}}/{{#v|apache}}/{{#v|php}}/{{#v|perl}} Но в общем случае можно работать с любыми данными ---- Сервер №1 nginx.conf: {{#v|geo}} {{#i|$ip2geo}} { {{#v|include}} ip2geo.conf; } … {{#v|proxy_set_header}} X-Geoip {{#i|$ip2geo}}; ---- Perl: print $ENV{'HTTP_X_GEOIP'}; PHP: <?= $_SERVER['HTTP_X_GEOIP'] ?> Результат: ru ---- Выбираем нужный сервер: {{#v|$static_host}} = $_SERVER['{{#v|HTTP_X_GEOIP}}'] == 'ru' ? '{{#v|i-ru.site.ru}}' : '{{#v|i-world.site.ru}}'; Загружаем с него документы: <img src='<?= {{#v|$static_host}} ?>/xxx.jpg'> ---- В CSS можно использовать относительные адреса {{http://i.site.ru/style/basic.css}}: body { background: url(\"/i/yellow.png\") } Будет загружен {{http://i.site.ru/i/yellow.png}} ---- Мы только что сделали гео-балансировку запросов ---- {{img src="img/NCDN_-_CDN.png" width="662" height="284"}} ---- По России такую услугу оказывает {{ngenix.net|http://ngenix.net}} 7 точек присутствия в РФ От 9т.р./мес ---- {{img src="img/ngenix_network.png" width="593" height="350"}} Площадки {{ngenix|http://ngenix.net/network.html}} ---- Для всего мира есть много провайдеров Cм. {{статью|http://en.wikipedia.org/wiki/Content_delivery_network#Content_delivery_service_providers}} о CDN на википедии ---- Например: {{CacheFly.com|http://cachefly.com}} 18 точек присутствия в мире От $99/мес. ---- {{img src="img/cachefly_network.png" width="996" height="495"}} Площадки {{CacheFly|http://cachefly.cachefly.net/networkmap/}} ---- Самый старый провайдер {{Akamai.com|http://akamai.com}} Обслуживает MicroSoft и другие очень крупные проекты ---- Есть бесплатная (с лимитами) академическая {{coralcdn.org|http://coralcdn.org}} $static_host = $_SERVER['HTTP_X_GEOIP'] == 'ru' ? '{{#v|i.site.ru}}' : '{{#v|i.site.ru.nyud.net}}'; ---- Большинство работают в режиме кеширующего прокси Платные поддерживают загрузку файлов через API ---- Загрузка файлов xxx.jpg является довольно простой задачей И современные CDN сейчас оказывают более сложные услуги: - раздача потокового видео - размещение приложений на облачном хостинге и пр. ---- Следующая задача: Один и тот же контент у нас сейчас размещается по разным URL ---- Это плохо сказывается на кешировании и не очень хорошо на индексации картинок поисковиками ---- Следующий шаг — возврат к единому {{http://i.site.ru/}} ---- Нужно обучить DNS сервер для российских IP выдавать IP сервера №1, а для остальных — сервера №2 ---- Это задача GeoDNS И в Google можно найти несколько рецептов для её решения ☺ Например сервис {{GeoDirector.com|http://geodirector.com}} ---- {{img src="img/geodirector_scr.png" width="614" height="266"}} Настройка {{GeoDirector|http://geodirector.com/geodns-free-configurator.html}} ---- Кстати! DNS запросы от клиента к вам приходят с IP адреса DNS сервера его провайдера. ---- Проблема: \"Я использую {{Google Public DNS|http://code.google.com/intl/ru/speed/public-dns/}}. Куда мне идти?\" ---- Если вы добрались до этих вопросов, я рекомендую ознакомиться с опытом других компаний Посмотреть доклады конференции Highload от российских видео-порталов и проекта Ngenix А также изучить предложения на рынке от CDN провайдеров и облачных хостингов ---- Здесь можно посмотреть список и результаты тестирования различных провайдеров: {{paessler.com/...|http://www.paessler.com/blog/2010/05/17/networking-basics/real-world-performance-comparison-of-cdn-content-delivery-network-providers}} ---- Выводы ---- CDN — это просто! ☺ ---- Сразу планируйте отдельный домен для статических файлов. ---- Для загрузки файлов используйте общий модуль. ---- Сможете поменять стратегию: 1. Выкладываем в локальную файловую систему 2. + заливаем на сервера № 2-N 3. Выкладываем на CDN {{Amazon S3|http://aws.amazon.com/s3/}}, {{Google App Engine|http://code.google.com/intl/ru/appengine/}}, … ---- Спасибо! Вопросы? Презентация: {{http://hsw.pp.ru/talks/cdn/cdn.html}} © Сергей Хоменков для {{Bryansk WebDay|http://webday.info/}} 2010 hsw@rambler.ru, {{hsw.moikrug.ru|http://hsw.moikrug.ru}} {{WhoYOUgle.ru|http://whoyougle.ru}}