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...