2 июня

Что такое CDN, и как это вообще работает

Блог компании RUVDS.comIT-инфраструктураСетевые технологии

Сайт Texas Internet Consulting. Жив с 1987 года, страница — 7 Килобайт.

Помните время, когда главная больше 90 Килобайт считалась расточительством? С тех пор Интернет стал жирным. И понадобились инструменты, чтобы правильно раздавать трафик сразу с нескольких узлов. Например, во время очередного обновления Fortnite CDN от Akamai сумел переварить трафик мощностью в 106 Терабит в секунду. Давайте пробежимся по основным принципам этой технологии и потенциальным проблемам.

И о том, почему Minecraft в Казани тормозит, если не развернуть сервер в черте города.

image
Вот современный сайт, который соблюдает разумные рамки: 1,7 Мегабайта.

image
Пример относительно тяжёлого сайта с видеоконтентом и анимацией: 39,5 Мегабайта радости и шевеления.

Сейчас, когда 100 Мегабит домашнего Интернета воспринимаются вполне привычно, всё меньше дизайнеров заморачивается с кропотливым сжатием каждого изображения и экономии на мелочах. Ситуации, когда кто-то умный положил на главную картинку в PNG весом в 30 Мегабайт, бывают чаще, чем хотелось бы.

image
Исторические данные взяты здесь.

А если посмотреть на статистику, то тенденция к росту объёмов становится ещё более очевидной. Например, за 10 лет размеры средней страницы, рассчитанной на мобильные устройства, выросли в семь раз (с 233 до 1 864 Килобайт).

Проблема ширины канала


У вас есть много иллюстраций и видео, которые надо доставить клиенту. Передать однократно несколько Мегабайт не очень трудно: современные каналы связи позволяют делать это за секунды. Всё становится гораздо хуже, когда к вам на сайт одновременно заходят вначале несколько десятков, а потом — тысяч посетителей.

Давайте считать. Допустим, у вас один-единственный сервер и у вас типичная страница весом в 1,8 Мегабайта. Клиенты приходят к вам впервые и с «холодным» кэшем, то есть в браузере нет ранее загруженных материалов с вашего ресурса.

Чтобы отдать за приемлемые три секунды страницу, нам потребуется ширина канала в 4,8 Мегабита на одного посетителя. Если их придет 100, то это уже 480 Мегабит. А если вдруг потребуется отдать тем же людям небольшой видеофайл размером 10 Мегабайт, то нам потребуется канал в 2,7 Гигабита.

Таким образом, у вас появляется два основных типа контента: динамический и статический.
Статический контент, как следует из названия, не изменяется или меняется крайне редко. Например, это логотип веб-сайта. Или залитые образы с дистрибутивами ПО.

Динамический контент отличается тем, что он генерируется сервером «на лету». Обычно это происходит в момент самого запроса. Например, при клике на кнопку формируется плей-лист, уникальный для конкретного пользователя.

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

Почему не взлетел чистый multicast?


image
Схема работы multicast.

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

Одна проблема — поддержка оборудованием. Для того чтобы гарантировать, что multicast-пакет доедет до каждого клиента, нам нужно убедиться, что каждый промежуточный узел правильно сконфигурирован и готов доставить его дальше. В противном случае пакет «угаснет» где-то по дороге на тупом маршрутизаторе, а клиент не дождётся своей вечерней трансляции на YouTube. Именно поэтому вместо более продвинутого мультикаста взлетела географически распределённая сеть CDN, которая работает на более простом unicast.

Вторая проблема — 4K и грядущий 8K. Провайдеры уже нервно вздрагивают от объёмов трафика, а будет только хуже. В варианте чистого мультикаста вы не можете регулировать качество вещания. В случае того же Google Global Cache в качестве CDN вы можете отдавать локальным клиентам картинку в адаптивном битрейте. GGC закэшировал некоторый кусок видео и кормит своих клиентов в 4K. В этот момент у одного из клиентов возникают проблемы из-за перегрузки локальной сети. GGC автоматически снизит битрейт с учётом изменившейся ширины канала клиента и продолжит раздавать ролик.

Тем не менее технология очень привлекательна для IPTV, поэтому некоторые компании предлагают такие интересные решения, как nanoCDN Multicast ABR. Концепция строится на добавлении в сеть провайдера дополнительного узла-транскастера, который преобразует unicast от источника видео за пределами сети в multicast до конечного потребителя.

Мир без CDN


Итак, мы определились с тем, что нам потребуется очень много ресурсов для того, чтобы обслуживать всех посетителей из единой точки. Давайте попробуем представить, как выглядел бы современный веб без CDN. Каждая компания строит себе один огромный дата-центр и собирает все ресурсы в одной-единственной точке мира.

image
Централизованная раздача контента и распределённая схема через CDN.

Небольшие веб-ресурсы


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

Видеохостинг


Забудьте. Никакого YouTube, Vimeo и других ресурсов без CDN не будет (важно: торрент-сеть, по сути, тоже можно считать подвидом CDN в такой ситуации, но работающей по совершенно иным принципам).

Без CDN можете смело возвращаться в начало нулевых, когда видео было доступно по прямым ссылкам и его нужно было качать. Никакого стриминга, FlashGet и прочих хардкорных менеджеров загрузки. Причём речи о скачивании в реальном времени даже и близко не было бы. Уже сейчас, если верить статистике, один только YouTube генерирует 37 % всего мобильного трафика в мире. Это миллиард часов видео в сутки. Без географического распределения нагрузки подобные сервисы просто не родились бы.

image

Именно поэтому тот же Google предлагает установку в дата-центры крупных провайдеров своего оборудования, которое обеспечивает так называемый GGC — Google Global Cache. Когда вы тычете в популярный ролик на YouTube, то данные тащатся не из дата-центра в Калифорнии, а из ближайшего крупного узла связи вашего провайдера. Если ролик малопопулярен, то трафик уже прилетит из-за пределов внутренней сети провайдера, но будет закэширован.

Раньше провайдеры существенно экономили на трафике тем, что делали кэши и локальные файлшары. Тогда первый скачавший новую песню «Металлики» пользователь давал возможность провайдеру не платить за магистральный трафик для ещё 50 возжелавших, но выставить счёт пользователям как за обычный трафик. Можно сказать, что это был ещё один подвид CDN. Отсюда же растут уши идеи с retracker.local. В 2010 году nag.ru предложил оригинальную идею организации локальных ретрекеров под этим адресом у всех провайдеров для облегчения поиска локальных пиров и снижения внешнего трафика. Идею поддержал rutracker.org, начав добавлять этот адрес в дополнение к своим ретрекерам.

Мессенджеры


Выживут, но без всяких модных стикеров, трансляции геопозиции и прочих радостей. А ещё вы, скорее всего, можете забыть про пуши со стороны Google Services. То есть в Сети вы будете только тогда, когда запущено приложение, что означает непрерывное потребление батарейки. Можете вспоминать про ностальгические времена ICQ и Jabber. Он со своей федеративной системой был не так плох, кстати. Кое-где его до сих пор используют.

Магазины


Остались бы исключительно в формате странички локального мясного магазина с картой проезда и телефоном. А ещё придётся вспомнить старые добрые бумажные распечатки прайсов в магазинах компьютерных комплектующих. Amazon и Aliexpress просто не смогли бы существовать. У них и сейчас со всеми современными технологиями запредельные пиковые нагрузки в моменты распродаж, которые требуют сложнейшей балансировки и непростой облачной архитектуры. Тем не менее в парадигме «один дата-центр на магазин» можно было бы устраивать распродажи. Просто они шли бы медленнее. В случае отказоустойчивости в виде двух площадок часть проблем резервирования решилась бы, но каждый запрос пользователя ходил бы через всю страну именно до них без локального кэша. А если уж делать локальный кэш, то почему сразу же не сделать там же на узле и серверные приложения?

Отдалённые регионы


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

Проблема долгого пинга


Вторая проблема, которую решает CDN, — это ускорение запросов. Около вас есть локальный сервер, который кэширует статический контент и иногда сам умеет выдавать динамический. Если вам знакомы тормоза 1С при забегах из Владивостока в Москву или особенности работы с SAP через какой-нибудь корпоративный VPN в Европе из Новосибирска, то вы понимаете всю глубину боли. Сотни запросов незаметны при обычных сетевых задержках внутри города, но, когда расстояния увеличиваются, неиллюзорно тормозить начинает всё. Россия в этом плане выделяется тем, что у нас страна такого размера, где от случайного города до столицы может оказаться дальше, чем от этого же города до столицы другой страны. Это рождает интересные особенности туннелирования трафика серверных приложений той же MS.

Так что внутри современной CDN?


CDN — это общее название множества различных технологий, призванных доставлять статический контент как можно ближе и быстрее по отношению к клиенту. Например, torrent-раздача новой версии Ubuntu — это тоже CDN. А вы становитесь одним из узлов раздачи, помогая другим пользователям быстрее получить новую версию дистрибутива и не положить основной сайт под нагрузкой.

В случае классического понимания речь идёт о специально созданных и предназначенных только для решения подобных задач сетях. Часто проприетарных. Если вам нужен CDN общего назначения, то вы обращаетесь к кому-то из крупных вендоров, имеющих серверы по всему миру и достаточные каналы связи. Крупнейшие из них, такие, как Amazon и Google, тянут свои собственные кабели связи для обеспечения нужной пропускной способности и снижения задержек.

1. Выбираем ближайший узел


Для начала пользователю при DNS-запросе отдаётся адрес ближайшего к нему узла. Это нужно для того, чтобы ваш браузер не полез качать фотографию откуда-то из Ванкувера, когда ближайшая к вам копия файла есть в кэше на сервере в вашем городе. Обычно это делается с помощью GeoDNS, но иногда используется специально сконфигурированный Anycast. Например, всем известный 8.8.8.8 от Google будет вести на ближайший узел, который чаще всего расположен во внутренней сети вашего провайдера. Это возможно благодаря правильному анонсированию сетей, по которому роутеры провайдера выбирают наиболее короткий маршрут.

2. Кэшируем


Это ключевой момент в работе CDN. Кэширование очень важно для снижения трансграничного трафика, каналы для которого совсем не резиновые. Более того, очень важно, чтобы кэширование происходило строго в соответствии с географией пользователей. Например, локальный Google Global Cache не должен хранить YouTube-видео с рекламой российского сотового провайдера на серверах в Нью-Йорке. Маловероятно, что она будет кому-то там нужна. Аналогично нет смысла кэшировать рецепты приготовления лягушачьих лапок на французском языке где-то в Перми. Поэтому основной принцип довольно прост. Первый пользователь, который запросил контент, ждёт дольше всех, пока он не подтянется откуда-то из франкфуртского дата-центра. Зато все последующие обращения будут происходить с минимальными задержками и нагрузками на сеть провайдера.

Причём у крупных вендоров схема очень похожа на работу классического DNS. Мы вначале спрашиваем ближайший к нам узел, нет ли у него нужной картинки. Потом он идёт не к корневому узлу, а к географически ближайшим. И если он и там не сможет найти нужное, то только тогда пойдёт к первоисточнику на другом континенте. Таким образом, мы получаем максимально эффективное хранение тяжёлых файлов как можно ближе к локальным клиентам с учётом их потребностей.

3. Доставляем динамику


Динамический контент генерируется на стороне вашего origin-сервера. Например, создаётся страница с новостями, отсортированными под конкретного клиента. Кэшировать всё это очень сложно, так как контент, по сути, уникальный. В большинстве случаев динамическое содержимое вроде текста «В Лондоне +23 градуса» доставляется от origin-сервера, а статическое вроде картинки с Биг-Беном прилетает от CDN.

Чтобы ещё больше повысить скорость загрузки страницы, некоторые компании предлагают кэширование динамического контента за счёт переноса выполнения скриптов на сторону их инфраструктуры. Например, такой вариант предлагает сервис Cloudflare Workers. При этом код кэшируется и выполняется быстро и в географически нужных локациях. При этом тот же Cloudflare использует свою проприетарную технологию маршрутизации трафика Argo Smart Routing, что позволяет оптимизировать доставку запросов пользователей по наиболее быстрым маршрутам внутри своих сетей.

4. Реализуем OPES-протокол


OPES (Open Pluggable Edge Services) — это протокол, предназначенный для адаптации одного и того же контента под нужды конкретного клиента. Работает это примерно так.

В Сети есть куча клиентов, origin-сервер с исходным контентом, кэширующий сервер CDN и специальный callout-сервер, отвечающий за адаптацию контента:

  1. Клиент с PC запрашивает контент у CDN.
  2. CDN забирает его у origin-сервера, кэширует и отдаёт клиенту.
  3. Клиент с мобильного телефона запрашивает тот же ресурс у CDN.
  4. CDN не беспокоит origin-сервер, отправляет на переработку свой кэш в сторону callout-сервера.
  5. Callout-сервер адаптирует контент под мобильного клиента и отдаёт его CDN.
  6. CDN кэширует новый вариант ресурса и отдаёт его мобильному клиенту.

5. Правильно отдаём картинки, Image CDN


CDN — это намного больше, чем просто тупой кэш для файлов. Хороший пример — правильная работа с изображениями. Обычный CDN общего назначения не обращает внимания на особенности клиента, который к нему обратился. Попросили отдать картинку — он её отдаст, неважно, запросил её Samsung Galaxy, iPad или PC с 8К-дисплеем. Правильный Image CDN отдаст картинку в нужном формате, сжав её под размеры дисплея клиента. Тем самым экономится большое количество трафика и ускоряется загрузка страниц на тех устройствах, которым не нужна графика в огромном разрешении.

6. Делаем ещё кучу нужных вещей


Помимо доставки контента, узлы CDN могут обеспечивать терминирование HTTPS-трафика, WAF (Web Application Firewall), защиту от DDoS и кучу других задач.

Что нужно для подключения к CDN?


Каждый проект уникален. Но в целом в минималистичном варианте задача сводится к нескольким этапам:

  1. Отделите статический контент и перенесите его на отдельный домен, например, на static.mydomain.com.
  2. Создайте отдельный домен для раздачи контента с CDN, например, cdn.mydomain.com.
  3. Заключите договор с CDN-провайдером и сообщите ему, откуда он будет забирать origin-контент (static.mydomain.com) и откуда отдавать клиентам (cdn.mydomain.com).
  4. Настройте в своём DNS cdn.mydomain.com на IP-адреса вашего провайдера.

Теперь, когда на странице будут попадаться ресурсы с cdn.mydomain.com, они будут раздаваться с географически ближайшего сервера вашего CDN-провайдера.

Управление кэшированием


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

Проблема любого кэша в том, что мало отрегулировать скорость его протухания. Нужно убедиться, что ни промежуточные узлы, ни браузер не додумаются закэшировать особо чувствительные данные. Например, реквизиты банковской карты. Замечали, что их каждый раз приходится вводить заново? Вот это оно и работает.

Для этого необходимо использовать специальные валидаторы в заголовках веб-страниц.

cache-control: private


Заголовок говорит о том, что контент может быть закэширован только конечным клиентом, но не промежуточным узлом, таким, как прокси или CDN.

cache-control: public


Контент может быть кэширован кем угодно.

cache-control: no-store


Контент не должен быть кэширован никем и никогда. Чаще всего используется для страниц с особо чувствительной информацией, например, форме ввода реквизитов банковской карты.

cache-control: no-cache


Контент не должен использоваться до тех пор, пока клиент не убедится, что он просматривает последнюю версию. Это реализуется за счёт хедера ETag, который представляет собой идентификатор, уникальный для конкретного ресурса. По сути, это хэш.

Клиент при запросе посмотрит, что у него лежит в кэше, и отдаст ETag в заголовке If-None-Match. Если ETag от клиента соответствует актуальной версии у сервера, то он ответит клиенту, что можно пользоваться кэшем. Иначе пришлёт новую версию.

cache-control: max-age


В этом заголовке указывается срок жизни ресурса в секундах с момента первого получения.
Помимо управления кэшированием через заголовки, владелец ресурса всегда может внести дополнительные изменения через панель управления или сбросить кэш, ткнув CDN через API.

Кому выгоден CDN


Практически всем. Клиент получает самые низкие пинги при обращении к ресурсу и отсутствие ожидания при массовой нагрузке на сервис, например, при выходе очередного дистрибутива ОС или игры.

Источник контента получает конкурентное преимущество. Современный веб приучил людей, что страница, которая не грузится больше нескольких секунд, скорее всего, сломана и можно просто перейти к следующей ссылке. Тот же Google заинтересован, чтобы его поиск работал как минимум не медленнее, чем у его конкурентов, а видео и реклама воспроизводились без задержек. Иначе клиентура быстро перебежит к кому-то ещё. По сути, монополия таких крупных гигантов во многом строится именно на очень широких каналах связи и множестве CDN по всему миру. Вы можете быть очень крутой компанией с точки зрения технологии, но вам не запустить второй YouTube без многомиллиардных вложений в дата-центры.

Ну и, наконец, провайдер. Он будет только рад максимально замкнуть трафик пользователей внутри своей сети и минимизировать свои затраты на пиринг с другими провайдерами на точках обмена трафиком. Это особенно актуально с учётом того, что видеоконтент сейчас является одним из основных потребителей мобильного и стационарного трафиков. Не зря тот же Netflix и другие компании согласились принудительно снизить качество своего видео с 4К до 1080p, чтобы разгрузить сети европейских провайдеров на время пандемии коронавируса. Множество людей ушло в вынужденный простой, перегрузив сети потоковым видео, не давая возможности нормально работать удалённо всем остальным.

Жутковатая олигополия


CDN — несомненно, очень крутая технология. Проблема в том, что она требует больших капитальных затрат и закладывает потенциальную мину под будущее Всемирной паутины. По сути, если вы достаточно крупная компания, то вам почти неизбежно надо идти к кому-то из небольшого списка компаний. Крупнейшие сети:

  1. Cloudflare.
  2. Azure CDN.
  3. Amazon CloudFront.
  4. Akamai Technologies.
  5. Google Cloud CDN.

В результате в случае программной ошибки на любом из них у вас попросту отвалится множество сервисов, которые хостятся на их мощностях, например, отказ Cloudflare в 2019 году. Они тогда залили кривое правило на Cloudflare Web Application Firewall и распространили его глобально. В итоге они получили стопроцентную нагрузку на свои ноды по CPU. Клиенты по всему миру на сотнях ресурсов в это время массово получали 502 ошибки (Bad Gateway). Из крупных ресурсов пострадали Discord, Reddit, Twitch и другие.

Или можно вспомнить массовое падение кучи сервисов в России во время блокировок IP-адресов Amazon по распоряжению Роскомнадзора (перебои в работе Viber, некоторых платёжных систем, сервисов регистрации на авиарейсы, системы продажи электронных полисов ОСАГО, сети научных контактов ResearchGate, центрального репозитория библиотек Java, сайтов СколТеха, МГУ, Высшей школы экономики и других вузов, научных архивов, системы подачи заявок в РФФИ и других).

Таким образом, теряется основное преимущество, сделавшее Интернет глобальным, — децентрализованность. Более того, есть ещё одна очень важная проблема. Зашифрованный мусор нельзя нормально кэшировать. Поэтому в большинстве реализаций вам придётся отдать CDN-провайдеру самое ценное — шифрование трафика между вами и клиентом. По сути, вы соглашаетесь на классический Man-in-the-middle с целью оптимизации доставки контента. Это создаёт дополнительные риски концентрации приватной информации пользователей в одних и тех же руках. Более подробно проблему олигополии мы раскрывали тут.

Можно ли обойтись без CDN?


Да, можно. Если ваша потенциальная аудитория находится в одном регионе и не будет страдать от большого пинга, то CDN вам не нужен. Что делать, если я хочу просто играть локально или обеспечить высокий пинг людям не в Москве?

Можно ограничиться локальным сервером. Собственно, у нас часто берут VDS в Екатеринбурге, Новосибирске, Казани и Петербурге как раз для игровых серверов либо для проектов для локальных офисов. А VDS во Франкфурте, Лондоне или Амстердаме нужны тем, кто использует тех же трейдинговых ботов или что-то парсит: там ближе к биржам и источникам данных.

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

Если на вашем сервере Minecraft стоит лимит в 30 игроков, то вы получите вполне прогнозируемый трафик между вами и клиентами. Более того, статическими данными в данном случае будут разве что кастомные текстуры, наборы плагинов со стороны сервера или что-то подобное. Всё остальное будет обрабатываться на стороне клиента.

В зависимости от выбранного типа сервера вам потребуется развернуть на виртуальной машине либо полностью ванильную версию игры, либо, что более вероятно, использовать платформу, поддерживающую сторонние моды, например, Bukkit. На 30–50 игроков вам потребуется порядка 6 Гб оперативной памяти в зависимости от числа модов, которые вы навесите на свой сервер, и размеров карты. К CPU тоже предъявляются высокие требования. Из-за архитектуры игры вы сможете задействовать только одно ядро для вычислений, поэтому предпочтительнее высокая частота, нежели число ядер.

И самое интересное — сеть. В целом довольно скромного канала в 10–20 Мегабит/с будет вполне достаточно. Гораздо критичнее сразу предусмотреть размещение игровых серверов как можно ближе к игрокам. Поверьте, крипер, который вас убивает через секунду после того, как вы успешно от него убежали, или проваливание сквозь блок из-за большой задержки гарантированно вызовет много нецензурной лексики со стороны игроков. Поэтому близкие к вашей аудитории сервера с низкими пингами — вполне себе альтернатива CDN в некоторых случаях. У нас, например, есть свободные мощности в Новосибирске и Казани с хорошей сетевой связностью.

Итого


Вам, скорее всего, не нужен CDN, если:

  1. У вас очень лёгкие данные и нет тяжёлого фото-/видеоконтента.
  2. Для ваших клиентов некритичны задержки в несколько дополнительных секунд при первом подключении.
  3. У вас не планируется резких пиковых нагрузок во время обновлений или распродаж.
  4. У вас ценные приватные данные, и вы не можете делегировать HTTPS-шифрование сторонним компаниям.

Если же клиенты размазаны по всему миру, а контент тяжёлый, то придётся идти к кому-то вроде Cloudflare. Если вы очень крупная компания, а требования к безопасности высокие, то, возможно, вы так или иначе придёте к собственной частной сети CDN, чтобы не доверять сторонним компаниям своих данных.

На что обратить внимание при переходе на CDN:

  1. География присутствия. У вашего вендора должны быть ноды в точках наибольшей концентрации ваших клиентов. Проанализируйте логи и свою аудиторию. Вы должны покрыть региональными узлами максимальный процент посетителей.
  2. Связность. Если провайдер CDN имеет узел в Москве, но гонит туда трафик странными петлями через Австралию, то это не решит ваших бизнес-проблем.
  3. Технологический стек. Убедитесь, что провайдер обеспечивает все нужные вам технологии работы с трафиком: HTTP/2, TLS 1.3, IPv6 и другие детали.
  4. Всегда выполняйте тщательное тестирование перед переводом промышленного трафика на новую инфраструктуру. Идеально, если у вас останется резервная схема для отката обратно на первое время: так вы сможете избежать неприятных сюрпризов.

А если будет нужен мануал для организации CDN под Windows Server 2019 Core и IIS, то мы его уже подготовили.



Теги:CDNcdn-providerсерверавтоматизациясервисоптимизациякэшированиевеб-страницаданныеVDSхостинг
Хабы: Блог компании RUVDS.com IT-инфраструктура Сетевые технологии
+74
25,1k 188
Комментарии 30
Лучшие публикации за сутки