vladd Опубликовано 26 февраля, 2014 · Жалоба После мучений с udpxy и борьбы с распуханием xproxy в астре, что сильно обострилось в канун олимпиады, решил по быстрому сделать свое решение. Представляю на суд общественности то, что получилось в итоге и прошу желающих протестировать. Принцип работы - слушание по умолчанию всех udp-каналов, полученных из командной строки, запись их в небольшой буфер, и отдача клиентам по http с небольшим прекешем (2 секунды). Это позволяет клиенту очень быстро выполнить буферизацию и сразу начать просмотр. Особенно шустрое включение происходит на smart tv. Используется epoll, что позволяет улучшить качество работы, однако из-за этого программа собирается только в linux. Запускается так: ./inputtcp -p <порт> -u 239.71.91.1:1234 -u 239.71.91.2:1234 … Программа начинает слушать на заданном http-порту и обслуживает группы 239.71.91.1:1234, 239.71.91.2:1234 и остальные, заданные при запуске. Любые другие группы вызовут ошибку 404. Формат запроса - стандартный - /udp/239.71.91.1-1234, статистику можно получить по запросу /stat - по всем клиентам. Особенно понравилась возможность смотреть количество переполнений буфера у клиентов - поле overruns в таблице. Из ограничений - пока все работает в одном треде, но ничего не мешает запустить несколько экземпляров софтины, исходя из количества ядер, для обслуживания разных групп на разных портах, и сформировать плейлист исходя из этого. Также в файле inputtcp.с можно подправить максимальное количество подключений (стоит сейчас 512). По опыту - работает у нас уже 2 недели, пики в 300 пользователей в момент трансляции закрытия олимпиады и прочих событий пережили нормально. Качество не сравнить с udpxy, в котором уже при 50 клиентах начинались затыки и рассыпания, а HD вообще было невозможно смотреть. Здесь же с этим все идеально. Больше у нас по tcp не смотрят. Будет интересно, если кто-нибудь попробует на большем количестве абонентов. itcp.tar.gz Вставить ник Цитата Ответить с цитированием Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах More sharing options...
Ivan_83 Опубликовано 27 февраля, 2014 · Жалоба udpxy давно пора закапывать, там уже помочь не чем :) У меня пока была однопоточная тянула до 3 гигабит на выход при одном гиге входа, на интеле выше средней приличности. Вставить ник Цитата Ответить с цитированием Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах More sharing options...
^rage^ Опубликовано 27 февраля, 2014 · Жалоба закапывайте обратно. скоро выложу http-стример с zero-copy и дающий 4Гбит/с с одного ядра E5620 при 57% cpu usage(этого ядра) и 40k коннектов. epoll/kqueue + sendfile. работает на фре, линуксе и должно на соляре. Вставить ник Цитата Ответить с цитированием Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах More sharing options...
maxlapshin Опубликовано 27 февраля, 2014 · Жалоба 4 гигабита и 40К соединений? Это же 100 кбит поток. Вставить ник Цитата Ответить с цитированием Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах More sharing options...
^rage^ Опубликовано 28 февраля, 2014 (изменено) · Жалоба 4 гигабита и 40К соединений? Это же 100 кбит поток. Число клиентов тут роли не играет(точнее, оно влияет на число контекстсвитчей, т.к. для большего числа файловых дескрипторов придется звать sendfile). Про вашу нелюбовь к sendfile() я помню, но если файл всегда в кеше - проблем никаких. вот nginx очень интересно работает на побочных эффектах AIO(читая через aio 1 байт, а всё остальное - sendfile). тут нашелся человек с 40G в лабе, так что посмотрим. Изменено 28 февраля, 2014 пользователем ^rage^ Вставить ник Цитата Ответить с цитированием Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах More sharing options...
zedsh Опубликовано 14 марта, 2014 · Жалоба Себе на тест поставил. Вставить ник Цитата Ответить с цитированием Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах More sharing options...
hellion Опубликовано 25 марта, 2014 · Жалоба Что-то не компилиться на убунуту х64 13.04 /itcp# make gcc -lglib-2.0 -lpthread -g -o inputtcp inputtcp.o socket.o packbuf.o helper.o reqhead.o resphead.o resource.o radix-tree.o inputtcp.o: In function `http_thread': /home/user/itcp/inputtcp.c:375: undefined reference to `pthread_detach' inputtcp.o: In function `main': /home/user/itcp/inputtcp.c:767: undefined reference to `pthread_create' collect2: ошибка: выполнение ld завершилось с кодом возврата 1 make: *** [inputtcp] Ошибка 1 Вставить ник Цитата Ответить с цитированием Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах More sharing options...
zedsh Опубликовано 25 марта, 2014 · Жалоба gcc -o inputtcp inputtcp.o socket.o packbuf.o helper.o reqhead.o resphead.o resource.o radix-tree.o -lglib-2.0 -lboost_system -lpthread -g -lrt Вставить ник Цитата Ответить с цитированием Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах More sharing options...
rustriton Опубликовано 25 марта, 2014 · Жалоба Первые результаты тестирования показали хорошие результаты, но в статистеке заметил вот такую штуку 225.2.2.129:1234 total packets=18509943 bufpos=1942 х.109.235.134 time=25:31, queue=224 fd=92 in_epoll=0 overruns=166 х.109.235.134 time=182:59, queue=3446 fd=91 in_epoll=0 overruns=1183 х.109.235.134 time=190:9, queue=1397 fd=89 in_epoll=0 overruns=1234 Как понимаю не закрываються конекты :( overruns только увеличиваються Можно ли установить timeout если overruns превысит какого то значения? Вставить ник Цитата Ответить с цитированием Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах More sharing options...
maxlapshin Опубликовано 25 марта, 2014 · Жалоба > pthread_create(&http_thread_t, NULL, http_thread, harg); Вы серьезно? На каждого клиента тред? Вставить ник Цитата Ответить с цитированием Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах More sharing options...
hellion Опубликовано 25 марта, 2014 · Жалоба gcc -o inputtcp inputtcp.o socket.o packbuf.o helper.o reqhead.o resphead.o resource.o radix-tree.o -lglib-2.0 -lboost_system -lpthread -g -lrt собрал без -lboost_system запускается, но все равно не работает. Иногда картинка появиться, но дальше не показывает... =ERROR REPORT==== 25-Mar-2014::13:41:08 === ** Generic server <0.46.0> terminating ** Last message in was {http,#Port<0.956>, {http_request,'GET', {abs_path,"/udp/239.0.100.1:1234"}, {1,0}}} ** When Server state == {state,#Port<0.956>,undefined} ** Reason for termination == ** {unhandled_path,"/udp/239.0.100.1:1234"} >> ~n =ERROR REPORT==== 25-Mar-2014::13:41:08 === ** Generic server <0.47.0> terminating ** Last message in was {http,#Port<0.957>, {http_request,'GET', {abs_path,"/udp/239.0.100.1:1234"}, {1,0}}} ** When Server state == {state,#Port<0.957>,undefined} ** Reason for termination == ** {unhandled_path,"/udp/239.0.100.1:1234"} Вставить ник Цитата Ответить с цитированием Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах More sharing options...
maxlapshin Опубликовано 25 марта, 2014 · Жалоба запускается, но все равно не работает. Иногда картинка появиться, но дальше не показывает... =ERROR REPORT==== 25-Mar-2014::13:41:08 === ** Generic server <0.46.0> terminating ** Last message in was {http,#Port<0.956>, {http_request,'GET', {abs_path,"/udp/239.0.100.1:1234"}, {1,0}}} ** When Server state == {state,#Port<0.956>,undefined} ** Reason for termination == ** {unhandled_path,"/udp/239.0.100.1:1234"} >> ~n =ERROR REPORT==== 25-Mar-2014::13:41:08 === ** Generic server <0.47.0> terminating ** Last message in was {http,#Port<0.957>, {http_request,'GET', {abs_path,"/udp/239.0.100.1:1234"}, {1,0}}} ** When Server state == {state,#Port<0.957>,undefined} ** Reason for termination == ** {unhandled_path,"/udp/239.0.100.1:1234"} подскажу немного: у вас работает сервер на эрланге, а не на C Вставить ник Цитата Ответить с цитированием Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах More sharing options...
hellion Опубликовано 25 марта, 2014 · Жалоба запускается, но все равно не работает. Иногда картинка появиться, но дальше не показывает... =ERROR REPORT==== 25-Mar-2014::13:41:08 === ** Generic server <0.46.0> terminating ** Last message in was {http,#Port<0.956>, {http_request,'GET', {abs_path,"/udp/239.0.100.1:1234"}, {1,0}}} ** When Server state == {state,#Port<0.956>,undefined} ** Reason for termination == ** {unhandled_path,"/udp/239.0.100.1:1234"} >> ~n =ERROR REPORT==== 25-Mar-2014::13:41:08 === ** Generic server <0.47.0> terminating ** Last message in was {http,#Port<0.957>, {http_request,'GET', {abs_path,"/udp/239.0.100.1:1234"}, {1,0}}} ** When Server state == {state,#Port<0.957>,undefined} ** Reason for termination == ** {unhandled_path,"/udp/239.0.100.1:1234"} подскажу немного: у вас работает сервер на эрланге, а не на C Удалил эрланге, толку нету все равно( ./inputtcp -p 8899 -u 239.0.100.1:1234 accepted http connection from 172.16.1.248:59745 Status ok 172.16.1.248:59745 requested: </udp/239.0.100.1:1234> Preparing sender thread sender thread for http found skipping 1 packets и в влц не показывает Вставить ник Цитата Ответить с цитированием Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах More sharing options...
vladd Опубликовано 25 марта, 2014 · Жалоба > pthread_create(&http_thread_t, NULL, http_thread, harg); Вы серьезно? На каждого клиента тред? Тред на http-сессию, для обработки запроса. После этого fd клиента передается в общий пул и тред убивается. skipping 1 packets и в влц не показывает Судя по выделенному, не идет udp-поток. Посмотри несколько раз /stat - увеличивается ли атрибут total packets? Вставить ник Цитата Ответить с цитированием Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах More sharing options...
hellion Опубликовано 26 марта, 2014 · Жалоба skipping 1 packets и в влц не показывает Судя по выделенному, не идет udp-поток. Посмотри несколько раз /stat - увеличивается ли атрибут total packets? Неа, не увеличивается total packets, картинка в влц появилась и зависла. Вставить ник Цитата Ответить с цитированием Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах More sharing options...
shapik Опубликовано 1 апреля, 2014 · Жалоба закапывайте обратно. скоро выложу http-стример с zero-copy и дающий 4Гбит/с с одного ядра E5620 при 57% cpu usage(этого ядра) и 40k коннектов. epoll/kqueue + sendfile. работает на фре, линуксе и должно на соляре. День добрый ! А когда выложите то? Хочется пощупать ))) Уж больно аппетитно выглядит. )) Вставить ник Цитата Ответить с цитированием Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах More sharing options...
morf Опубликовано 5 апреля, 2014 · Жалоба Согласен. Вставить ник Цитата Ответить с цитированием Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах More sharing options...
^rage^ Опубликовано 6 апреля, 2014 · Жалоба Тред на http-сессию, для обработки запроса. После этого fd клиента передается в общий пул и тред убивается. и что, при 8k запросов в секунду будете создавать/убивать 8k тредов в секунду? может, лучше пул тредов? Вставить ник Цитата Ответить с цитированием Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах More sharing options...
maxlapshin Опубликовано 6 апреля, 2014 · Жалоба Это же не HLS сервер, а UDP -> HTTP прокси. 8К подключений в секунду — это нерассчетная нагрузка. Вопрос в другом: каждый клиент будет стоить в такой системе порядка 2 мегабайт памяти. Т.е. 4000 клиентов обойдутся чисто в 8 Гб только на стеки тредов. Архитектура с тредом на клиента имеет кучу изъянов и странно её видеть в чем-то, что делается сегодня. Вставить ник Цитата Ответить с цитированием Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах More sharing options...
vladd Опубликовано 6 апреля, 2014 · Жалоба Еще раз - треда на клиента нет, есть тред только на время обработки запроса GET. Потом тред убивается и работа идет только с клиентским fd. На 500 клиентах количество занимаемой памяти не изменилось ни на мегабайт. и что, при 8k запросов в секунду будете создавать/убивать 8k тредов в секунду? может, лучше пул тредов? При таких нагрузках уже будут ресурсы допилить либо эту программу, либо купить что-то готовое. Пока же у нас 300-400 клиентов, и не в секунду, а в час пик одновременно смотрящих, под такие запросы и сделал софтину. Бесплатные решения не устраивали, а коммерческие - были неоправданно дорогие. Неа, не увеличивается total packets, картинка в влц появилась и зависла. Значит 100% не идет мультикаст-поток, или прекращает идти после запуска. Точно не включен fast leave, ограничение количества потоков или еще что-нибудь в этом роде? Программа запрашивает все потоки сразу, и должна получать их даже если никто не смотрит. Вставить ник Цитата Ответить с цитированием Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах More sharing options...
Ivan_83 Опубликовано 7 апреля, 2014 · Жалоба Вспомнился Courier Mail Server 1.56 и ранее, он тоже создавал по потоку на клиента. А досить его было легко: нужно было только создать одновременно пачку соединений (порядка 2к под х32) и всё, память кончалась и он высыпался. Здесь такая же история: цепляемся несколько тыщ коннектов, и не шлём данных или по одному байту можно цедить запрос, и где то кончится память :) Вставить ник Цитата Ответить с цитированием Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах More sharing options...
vladd Опубликовано 7 апреля, 2014 · Жалоба Вспомнился Courier Mail Server 1.56 и ранее, он тоже создавал по потоку на клиента. Третий раз - по потоку на клиента не создается. Тред создается только на время обработки запроса GET, потом убивается и дальше клиент обслуживается главным процессом через epoll. На сотни тысяч одновременных подключений оно и не рассчитано, для этого есть другие решения. Свою задачу предложенное решение выполняет более, чем хорошо. Если у вас во внутренней сети есть проблема c ddos-ерами, то это можно решить парой строчек в iptables. Или доработать софтину, и выложить изменения тут :) Вставить ник Цитата Ответить с цитированием Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах More sharing options...
vitalyb Опубликовано 7 апреля, 2014 · Жалоба Третий раз - по потоку на клиента не создается. Тред создается только на время обработки запроса GET, потом убивается и дальше клиент обслуживается главным процессом через epoll. Речь о том, что клиент подключается и шлет букву "G". Через минуту - букву "E"... к 30й минуте подходим к CRLF первой строки запроса... Вставить ник Цитата Ответить с цитированием Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах More sharing options...
Ivan_83 Опубликовано 7 апреля, 2014 · Жалоба Третий раз - по потоку на клиента не создается. Тред создается только на время обработки запроса GET, потом убивается и дальше клиент обслуживается главным процессом через epoll. Ещё раз перечитайте внимательно предыдущий пост. По шагам: 1. Подключаемся и не шлём запрос, просто висим, итого: потоки +1 2. Подключаемся ещё раз и не шлём запрос, просто висим, итого: потоки +2 ... Все эти треды будут висеть и ждать гет запрос. Если у вас во внутренней сети есть проблема c ddos-ерами, то это можно решить парой строчек в iptables. Или доработать софтину, и выложить изменения тут :) Я свою лучше ещё доработаю, начинать с начала как то не интересно :) Там уже дошло до разгребания MPEG2-TS: она научилась собирать у себя в памяти все нужные PSI таблицы, умеет их обратно выдавать в самом начале потока новому клиенту, чтобы он не дропал до пол секунды потока пока дождётся этих самых таблиц. Отсюда до HLS рукой подать :) И заодно EPG (EIT) у меня тоже собирается (тк это часть PSI), научить отдавать через веб в любом формате дело пары вечеров. zerocopy тоже не проблема, совсем немного менять, дольше вникать в особенности линуха и искать стенд для тестов на 10г или более. Вставить ник Цитата Ответить с цитированием Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах More sharing options...
vladd Опубликовано 8 апреля, 2014 · Жалоба 1. Подключаемся и не шлём запрос, просто висим, итого: потоки +1 Если такая проблема есть, доработать не сложно - либо в iptables, либо ограничением количества подключений с одного IP в самой софтине. Это явно не тянет на фатальный баг. У нас внутри сети ддосеров не наблюдалось, а в открытый интернет сервер не светим. Я свою лучше ещё доработаю, начинать с начала как то не интересно :) Я знаю, что у тебя хорошее решение, только для 200-300 пользователей дороговато, особенно с ежегодными платежами. Вставить ник Цитата Ответить с цитированием Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах More sharing options...