Текстовая онлайн-трансляция при большой нагрузке



    Большую роль в жизни нашего сайта играют онлайн-трансляции презентаций Apple. Помимо текстово-графической трансляции, которые делают многие русскоязычные ресурсы, мы предлагаем нашим читателям вести обсуждение в чате, а также ведем прямой аудио-эфир с комментариями всего происходящего. Как и в предыдущие разы, нашим постоянным ведущим помогали Кира Тверская (Эхо Москвы) и Эльдар Муртазин. Такой живой формат позволяет нам слышать реакцию ведущих в режиме реального времени, что согласитесь, довольно интересно.

    В прошлый раз на презентации iPhone 4S мы немного оплошались, и не смогли достойно подготовиться к наплыву посетителей (к слову, было около 3500 клиентов). Главной ошибкой было то, что страница трансляции представляла собой вывод плагина Wordpress, соответственно при каждом обращении дергался не только сам интерпретатор PHP, но и вся система Wordpress. После проведения трансляции стало очевидно, что от такой позорной схемы надо избавляться.

    Ходят слухи, что в марте компания Apple представит новую версию своего планшетника iPad 3. Нам повезло, и 19 января мы смогли обкатать новую схему трансляции на гораздо меньшей нагрузке, чем будет в марте. По понятным причинам, людей, заинтересованных в образовательной презентации Apple, было намного меньше.

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

    Вот общая схема распределения текстового контента.



    Ключевую роль в этой схеме играют сервера-раздатчики, способные поддерживать несколько тысяч долгоживущих HTTP-соединений и практически мгновенно раздавать новые данные подключенным клиентам. Их работа основана на Comet-сервере Dklab Realplexor, о котором на хабре писал сам разработчик DmitryKoterov.

    Админка — это простой веб-интерфейс, написанный на PHP. Позволяет вести несколько трансляций, и в них добавлять, удалять и редактировать отдельные сообщения ленты трансляции. Принцип работы админки заключается в следующем:
    1. админ вводит новое сообщение для ленты трансляции
    2. сообщение добавляется в базу данных админки
    3. из базы данных вытаскиваются первые 10 сообщений и формируется файл index.htm
    4. из базы данных вытаскиваются все сообщения и формируется файл full.htm
    5. получившиеся файлы index.htm и full.htm загружаются на CDN CloudStorage при помощью OpenStack API
    6. новое сообщение отправляется на раздачу всем Comet-серверам, с помощью примерно таких POST-запросов:
      POST / HTTP/1.1
      Host: comet1.live.appleinsider.ru
      Content-Length: 30
      X-Realplexor: identifier=ai
      
      {"time":"07:36","text":"test"}
    Теперь, как это выглядит со стороны клиента, т.е. слушателя/читателя онлайн-трансляции.

    Клиент вводит адрес live.appleinsider.ru и у него сравнительно быстро загружается закешированная HTML-страница. Напомню, CloudStorage — это облачное хранилище от компании Clodo, обладающее широким каналом и высокой скоростью доставки контента.

    В этой «затравке» имеется Javascript-код, который выбирает случайное число от 1 до 4 и производит подключение к одному из Comet-серверов comet1—comet4:
    <script type="text/javascript">
    var comet = new Dklab_Realplexor("http://comet"+(1+Math.floor(Math.random()*4))+".live.appleinsider.ru");
    comet.subscribe("ai", receive_post);
    comet.execute();
    
    function receive_post (msg, id) {
        if(msg){
            $("#onair .new").removeClass("new");
            html = "<li class='new'><span class='date'>"+msg.time+"</span> "+msg.text+"</li>";
            $("#onair").prepend(html);
        }
        $("#chat").append(msg.text);
        document.title = "*Новое сообщение*";
        setTimeout( function(){document.title = "AppleInsider.ru";}, 5000);
    }
    </script>
    Вообще их можно было разнести в разные дата-центры, но в нашем случае мы решили не заморачиваться и просто нагрузить 4 ядра процессора. Каждый процесс dklab_realplexor занимал по одному ядру, а балансировку по ядрам осуществлял nginx. При появлении новых сообщений на одном из раздатчиков они практически мгновенно доставлялись клиентам, которые к нему подключены.

    И, в заключение, небольшой технический отчет по проведенной трансляции:

    Дата проведения трансляции: 19 января
    Время аудиовещания AppleInsider.ru: 18:30-20:00
    Время проведения презентации Apple: 19:00-20:00
    Аудиопоток слушали: максимум 750 человек
    Текстовую трансляцию читали: максимум 420 человек
    В чате сидели: максимум 140 человек


    Текстовые раздатчики


    Трафик статического хранилища CloudStorage, live.appleinsider.ru/index.htm


    Трафик и использование процессора динамического раздатчика, comet*.live.appleinsider.ru



    Радио


    Аудиопоток раздавался по схеме, описанной в предыдущем моем посте. Запись можно найти здесь.




    Чат


    Чат представляет собой сильно допиленный веб-интерфейс Candy к конференции Jabber-сервера (у нас ejabberd).




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

    Комментарии 7

      +1
      А вы с запасом аж 4 реалплексора взяли? потому что 400+ подключений по идее и один должен легко выдерживать.
        +1
        ответил вам постом ниже (не туда кликнул)
        +1
        Да, по паре причин.
        Во-первых, Dklab Realplexor однопоточный и грузит одно ядро, следовательно CPU может стать узким местом. Таким образом тут мы расширили узкое место до 4 ядер.
        Во-вторых. Собственно, потестировали схему равномерного случайного распределния раздатчиков. Вообще эти раздатчики можно разместить в разных дата-центрах, чтобы распределить нагрузку на каналы хостеров, и чтобы на пожарный случай иметь второй запасной сервер. Думаю, в марте мы так и поступим (разделим на два датацентра Клодо: Оверсан-Меркурий и KIAEHOUSE).
          +2
          Спасибо, да я так и предполагал, но решил уточнить архитектуру. Верное решение.
          Кстати, но можно было рассмотреть и создание собственного сервиса — на Node.JS подобный сервис (и нагрузки) будет достаточно одного ядра и с запасом (на моем тесте синтетическом, упирались в потолок CPU при 16К+ паралельных сокетов, если же что-то типа jsonp-лонгполлинг, что как раз делает реалплексор, то думаю потолок еще выше, при этом все клиенты постоянно получают данные). Впрочем, ваш выбор вполне адекватный и хороший.
          +1
          Пробовал Realplexor использовать в своем проект — не понравилось. Очень сильно грузил процессор. Нашел на их форуме многочисленные сообщения о подобной проблеме, но все они были без ответа. Ну и подключение доп.библиотек не слишком радует. В итоге перешел на nginx_http_push_module ( goo.gl/g9Pgp — ссылка на статью на highload.com.ua )
            0
            Попробуйте c++-версию, в ней все проблемы решены. Она лежит в том зе репозитории. Формат конфигов и вообще работа с ней — идентична перловой.
              0
              Спасибо, буду иметь ввиду. Может быть, в будущем пригодится. Сейчас переходить уже смысла не вижу.

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

          Самое читаемое