Название: Алгоритм высоконагруженного сервера Отправлено: RedDog от Январь 19, 2011, 10:16 Прочитал много тем о высоконагруженных серверах, но так и не понял ничего.
Ситуация у меня следующая: Есть TCP сервер, который по запросу от клиента должен выслать ему файл 20-150мб. Одномоментно клиентов может быть сотни/тысячи. На сегодняшний момент на каждого клиента создается свой сокет, по которому пересылается файл. Код: class NetworkServer : public QObject Добавление нового подключения в массив сокетов: Код: void NetworkServer::on_newConnection() Код: void NetworkServer::on_recieveCommand() Но на каждого клиента создавать свой сокет накладно. Как быть? Как на один сокет повесить несколько клиентов? Название: Re: Алгоритм высоконагруженного сервера Отправлено: merke от Январь 19, 2011, 10:27 Тут уж надо уже смотреть не в сторону как повесить на один сокет несколько клиентов, хотя такое мне кажется невозможным, а курить в сторону многопоточности.
Название: Re: Алгоритм высоконагруженного сервера Отправлено: RedDog от Январь 19, 2011, 10:30 Тут уж надо уже смотреть не в сторону как повесить на один сокет несколько клиентов, хотя такое мне кажется невозможным, а курить в сторону многопоточности. Допустим, я сделаю, что каждый отдельный сокет будет висеть в своем потоке (либо по 10 сокетов на поток), тогда при 1000 клиентах получится 1000 открытых сокетов, думаю система от такого количества заткнется.Название: Re: Алгоритм высоконагруженного сервера Отправлено: merke от Январь 19, 2011, 10:38 Нет не заткнется) Иначе ни как...
Название: Re: Алгоритм высоконагруженного сервера Отправлено: BRE от Январь 19, 2011, 10:38 думаю система от такого количества заткнется. А ты не думай - ты проверь. :)Название: Re: Алгоритм высоконагруженного сервера Отправлено: RedDog от Январь 19, 2011, 10:45 Итого получается:
1. При старте сервера создается отдельный поток, в котором слушается порт 2. При подключении нового клиента создается новый сокет, и новый поток, в который сокет перемещается 3. При подключении N-нного (N<M) клиента создается новый сокет, который помещается в работающий отдельный поток 4. При подключении N-нного (N>M) клиента создается новый сокет, и новый поток, сокет перемещается в новый поток 5. "Сканируем" M потоков на количество работающих клиентов, и при отключении одного из них помещаем в этот поток нового N+1 клиента Я на верном пути? Название: Re: Алгоритм высоконагруженного сервера Отправлено: brankovic от Январь 19, 2011, 11:42 Итого получается: 1. При старте сервера создается отдельный поток, в котором слушается порт 2. При подключении нового клиента создается новый сокет, и новый поток, в который сокет перемещается 3. При подключении N-нного (N<M) клиента создается новый сокет, который помещается в работающий отдельный поток 4. При подключении N-нного (N>M) клиента создается новый сокет, и новый поток, сокет перемещается в новый поток 5. "Сканируем" M потоков на количество работающих клиентов, и при отключении одного из них помещаем в этот поток нового N+1 клиента Я на верном пути? В целом да, только пункты 3-5 лучше убрать. Один сокет -- один поток. Название: Re: Алгоритм высоконагруженного сервера Отправлено: RedDog от Январь 19, 2011, 11:48 Один сокет -- один поток. 10 000 потоков сервер выдержит!?Название: Re: Алгоритм высоконагруженного сервера Отправлено: BRE от Январь 19, 2011, 11:53 10 000 потоков сервер выдержит!? Некоторые выдерживают.http://ru.wikipedia.org/wiki/Проблема_10000_соединений (http://ru.wikipedia.org/wiki/Проблема_10000_соединений) Упс. Это я про соединения. 10 000 потоков не надо. Модель - на каждого клиента свой поток - скорее подходит для лабораторной работы, чем для боевых условий. Посмотри на алгоритм работы, например, nginx. Кстати, мы здесь несколько раз обсуждали подобные темы. Поищи. Название: Re: Алгоритм высоконагруженного сервера Отправлено: ufna от Январь 19, 2011, 12:00 Мне кажется, при таком числе соединений, работает не один сервер, а кластер.
Название: Re: Алгоритм высоконагруженного сервера Отправлено: brankovic от Январь 19, 2011, 12:55 Упс. Это я про соединения. 10 000 потоков не надо. Модель - на каждого клиента свой поток - скорее подходит для лабораторной работы, чем для боевых условий. На работе по 2000 тредов демона отлично работали (под линукс). Но балансировщик nginx стоял и да, кластер. Посмотри на алгоритм работы, например, nginx. Если задача просто отдать файл, то можно выпилить а-ля nginx по асинхронной схеме. Как только задача усложняется, то сразу лучше создавать тред на коннект, так удобнее в разы. А ресурсов треды не так много жрут (опять в линуксе). Мне кажется, при таком числе соединений, работает не один сервер, а кластер. Согласен, т.к. непонятно, как этот один сервер с 10k коннектами будет отдавать 10k файлов по 150 мб. Какой же канал нужен, чтобы от такой отдачи толк был? Название: Re: Алгоритм высоконагруженного сервера Отправлено: BRE от Январь 19, 2011, 13:36 Как только задача усложняется, то сразу лучше создавать тред на коннект, так удобнее в разы. Удобнее для кого, для разработчика? Согласен, реализуется проще.Эффективней в работе? Сомневаюсь. А ресурсов треды не так много жрут (опять в линуксе). Не так много, по сравнению с чем?Попробуй по-запускать не 2 000 потоков, а 5 000, 10 000. И не на кластере. Название: Re: Алгоритм высоконагруженного сервера Отправлено: Sahab от Январь 19, 2011, 13:55 каждый поток - на каждый клиент (соединение) - это бред
Цитировать Нет не заткнется) Иначе ни как... - улыбнуло[added] Кстати подобная тема уже поднималась. Название: Re: Алгоритм высоконагруженного сервера Отправлено: brankovic от Январь 19, 2011, 14:42 Удобнее для кого, для разработчика? Да. Когда задача всё время усложняется, то тащить за собой асинхронную архитектуру становится очень тяжело. Эффективней в работе? Сомневаюсь. Не эффективнее, а "не на много хуже". Тред пулу, например, уступает на копейки. Асинхронный же вариант ещё чуть шустрее, но учитывая возню с разработкой оно того не стоит. А ресурсов треды не так много жрут (опять в линуксе). Не так много, по сравнению с чем?Попробуй по-запускать не 2 000 потоков, а 5 000, 10 000. И не на кластере. Не так много, как top пишет. Большая часть памяти маппится, но не используется. 10000 тредов на тестах тянет легко, но реальный сервер под нагрузкой просто не отрабатывал больше 1000-2000 коннектов. edit: т.е. накладные расходы cpu на создание треда были << логики треда, а накладные расходы памяти на тред << размера базы данных в памяти каждый поток - на каждый клиент (соединение) - это бред зависит от задачи, но ладно, в данной может и бред. Просто реально прежде чем выпилить убер-асинк-сервер, может попробовать простой вариант и посмотреть, во что упираемся? В гигабитную сетевушку, например, или в неприемлимую скорость для каждого из 10000 клиентов. Название: Re: Алгоритм высоконагруженного сервера Отправлено: BRE от Январь 19, 2011, 18:15 Не эффективнее, а "не на много хуже". Тред пулу, например, уступает на копейки. Асинхронный же вариант ещё чуть шустрее, но учитывая возню с разработкой оно того не стоит. Не так много, как top пишет. Большая часть памяти маппится, но не используется. 10000 тредов на тестах тянет легко... А ты сам пробовал запускать или так думаешь? ;) Вот для примера такая программа: Код
У меня она откушала 92 Мб реальной (не виртуальной!) памяти и почти 20% процессорного времени (по мнению top'а). Заметь, проверял это на не самой последней машине (4 ядра x86_64, память DDR3 и т.д.). Только на переключения контекста между 10 000 потоков мы потратили почти пятую часть процессорного времени, ну и немного памяти на стеки. ;) Название: Re: Алгоритм высоконагруженного сервера Отправлено: JamS007 от Январь 20, 2011, 20:45 Как сказал один человек на этом форуме: "потоки не плодят ядра в системе".
Во-первых Вам следует определиться, будете ли вы использовать многопоточную машину, ибо если не будете - то потоки будут только мешать, но, сервер с такой нагрузкой на одноядерной машине - это явно не айс. По моему лучший вариант в таком случае - количество тредов = количество ядер в системе. Сервер в таком случае функционирует приблизительно так: В главном потоке обрабатываются все соединения. Каждое новое соединение проверяется в бан-листе и если его там нет - передается дескриптор сокета в наименее загруженный рабочий поток, в котором осуществляется последующая обработка клиента. Коэффициент загруженности потоков определять каждый раз, когда нужно передать нового клиента. Название: Re: Алгоритм высоконагруженного сервера Отправлено: _govorilka от Январь 21, 2011, 08:44 А почему если надо всего лишь отдавать файлики в сеть просто не взять nginx? Чем существующие решения не устраивают?
Писать высоко нагруженный сервер на Qt... Мне, кажется, что вместо решение проблемы с нитями, тут надо подумать: "а нужны ли в данном проекте сигналы и слоты, которые в 10-100 медленнее обычных вызовов функций"... Интересно, а кто-нибудь когда-нибудь вообще писал демоны на Qt, с такой нагрузкой, как здесь описано?.. Только не ради курсовой или диплома, написать и использовать не одно и тоже... Название: Re: Алгоритм высоконагруженного сервера Отправлено: RedDog от Январь 21, 2011, 09:52 А почему если надо всего лишь отдавать файлики в сеть просто не взять nginx? Чем существующие решения не устраивают? Сказали написать, хозяин - барин :)Писать высоко нагруженный сервер на Qt... Мне, кажется, что вместо решение проблемы с нитями, тут надо подумать: "а нужны ли в данном проекте сигналы и слоты, которые в 10-100 медленнее обычных вызовов функций"... Интересно, а кто-нибудь когда-нибудь вообще писал демоны на Qt, с такой нагрузкой, как здесь описано?.. Только не ради курсовой или диплома, написать и использовать не одно и тоже... Название: Re: Алгоритм высоконагруженного сервера Отправлено: _govorilka от Январь 21, 2011, 12:15 Сказали написать, хозяин - барин :) Но если сказали... Очень много зависит от задачи: протокол, платформа, количество клиентов. Если протокол должен быть HTTP/HTTPS то всё-таки лучше взять готовый сервер, например nginx и завернуть его в обёртки на Qt, если уж сказали. Если протокол и безопасность передачи не имеет значения, то можно попробывать P2P, тогда у тебя получиться бесплатный кластер, пример использования torrent есть в Qt. Название: Re: Алгоритм высоконагруженного сервера Отправлено: brankovic от Январь 21, 2011, 19:23 Не так много, как top пишет. Большая часть памяти маппится, но не используется. 10000 тредов на тестах тянет легко... А ты сам пробовал запускать или так думаешь? ;) Только без кьют, примерно такой код под pthread, машина такая же (intel 4x core, 8Gb), плюс на чистом C. На счёт памяти сколько съела, так не надо setStackSize делать. В любом случае 92 мега это копейки для сервера. У меня она откушала 92 Мб реальной (не виртуальной!) памяти и почти 20% процессорного времени (по мнению top'а). Ну так это 10000 тредов _только_ переключающихся, и съела всего 20% core cpu time / 4 cores = 5% cpu time, не так и много, учитывая, что полезной нагрузки нет. А как только полезная нагрузка появляется, то 5% превращаются в 0.5%, просто треды не будут успевать отрабатывать. Сказали написать, хозяин - барин :) Я так думал, что задача учебная, для практики лучше nginx трудно сделать. Название: Re: Алгоритм высоконагруженного сервера Отправлено: BRE от Январь 21, 2011, 20:10 Только без кьют, примерно такой код под pthread, машина такая же (intel 4x core, 8Gb), плюс на чистом C. А ты думаешь в Qt какие-то особые потоки? Или их как то "утолстили"? QThread это просто врапер над pthread (это под linux).На счёт памяти сколько съела, так не надо setStackSize делать. В любом случае 92 мега это копейки для сервера. На самом деле не важно использовал я setStackSize или нет. Установка размера стека влияет в первую очередь на виртуальную память выделяемую для процесса, реально же для стека каждого потока все равно выделилось по одной странице (4 Кб) физической памяти. А расширятся стеки будут при необходимости. Поэтому, для оценки затрат физической памяти и не важно какой использовался размер стека в потоке: 64000 байт как установил его я или 10 Мб (!) как установила бы его система по умолчанию.Кстати, на стеки для 10 тысяч потоков нужно реальной памяти: стек 4 Кб - 40 Мб стек 8 Кб - 80 Мб ... стек 64 Кб - 640 Мб ... Ну так это 10000 тредов _только_ переключающихся, и съела всего 20% core cpu time / 4 cores = 5% cpu time, не так и много, учитывая, что полезной нагрузки нет. А как только полезная нагрузка появляется, то 5% превращаются в 0.5%, просто треды не будут успевать отрабатывать. Нууу. Если программа, которая ничего не делая отъедает 5% процессорного времени, считается нормальной... :)Все таки как современные ресурсы компьютеров расслабляют разработчиков. :) Вместо того, что бы искать эффективные решения, можно просто попросить заказчика купить железо по-мощней, а если мощнее нет - то предложить подождать пару лет, пока оно появиться. ;) Название: Re: Алгоритм высоконагруженного сервера Отправлено: brankovic от Январь 21, 2011, 22:44 Нууу. Если программа, которая ничего не делая отъедает 5% процессорного времени, считается нормальной... :) Не совсем так. Как только даём полезную нагрузку, число тредов упадёт (скажем, до 2000 -- просто упрёмся в мощность цпу), после этого доля переключений станет 0.01%. Т.е. в тесте 5%, в реальной задаче меньше. Все таки как современные ресурсы компьютеров расслабляют разработчиков. :) Вместо того, что бы искать эффективные решения, можно просто попросить заказчика купить железо по-мощней, а если мощнее нет - то предложить подождать пару лет, пока оно появиться. ;) Ну да. Только один момент: железо по-мощнее уже есть всегда, поскольку есть кластера. А вопрос только в том, стОит ли платить 120 штук супер-программисту или дешевле платить 50 и на сэкономленные покупать по серваку в месяц. Тут чистая экономика. Название: Re: Алгоритм высоконагруженного сервера Отправлено: BRE от Январь 21, 2011, 23:12 Не совсем так. Как только даём полезную нагрузку, число тредов упадёт (скажем, до 2000 -- просто упрёмся в мощность цпу), после этого доля переключений станет 0.01%. Т.е. в тесте 5%, в реальной задаче меньше. Ээээ... Что значит упрется в мощность цпу? А если нужно реально обслужить 5000 клиентов, пусть и с меньшей скоростью? А если 10000? Выход твой подход с этим не справиться? ;)А еще совсем недавно, каких нибудь 10 лет назад, вычислительная мощность компьютеров была послабей, а сервера были и клиентов обслуживали... :) Ну да. Только один момент: железо по-мощнее уже есть всегда, поскольку есть кластера. А вопрос только в том, стОит ли платить 120 штук супер-программисту или дешевле платить 50 и на сэкономленные покупать по серваку в месяц. Тут чистая экономика. Да это все понятно.Все идет к тому, что скоро хомячки будут сервера писать, на java. Название: Re: Алгоритм высоконагруженного сервера Отправлено: developer от Январь 22, 2011, 11:08 Цитировать Ну да. Только один момент: железо по-мощнее уже есть всегда, поскольку есть кластера. А вопрос только в том, стОит ли платить 120 штук супер-программисту или дешевле платить 50 и на сэкономленные покупать по серваку в месяц. Тут чистая экономика. Интересно, а что потом говорить клиентам которие будут пользоваться вашим софтом (очень глючным, поскольку секономили на программисте). Им просто глубоко в носу количество ваших серваком, им нужен качественный сервис. Тут нужно найти золотую середину, или убедить супер-программиста работать за те деньги которие вы можете платить. Название: Re: Алгоритм высоконагруженного сервера Отправлено: brankovic от Январь 22, 2011, 12:16 А если нужно реально обслужить 5000 клиентов, пусть и с меньшей скоростью? А если 10000? Тогда кластер + разбиение клиентов по слоям и будет хоть миллион клиентов. Ну хорошо, допустим випилен сервер на 10к клиентов, а завтра нужно держать 100к, так всё равно придётся разносить по машинам. Тут опять вопрос: сколько времени понадобилось на выпиливание (+отладка, сервер-то сложный), сколько это стоило? Не дешевле ли было прикупить компов для тривиальной реализации, а потом выпиливать сложный сервер? А если функциональность с низким траффиком, но нетривиальной логикой, насколько просто будет добавить новую фичу в сложный сервер? Да это все понятно. Все идет к тому, что скоро хомячки будут сервера писать, на java. не совсем, просто супер-программисты научатся своё время ценить больше, чем ресурсы и да, перейдут на какой-нибудь питон. Это неизбежно, рано или поздно память и ресурсы процессора станут (почти) бесконечными. Уже сейчас есть такая тенденция: пишем по-быстрому на perl/php/python, потом переписываем на C, чтобы урезать расходы, в то время, как бизнес уже работает. Постепенно этап переписывания отпадёт. Название: Re: Алгоритм высоконагруженного сервера Отправлено: Igors от Январь 22, 2011, 13:27 Тогда кластер + разбиение клиентов по слоям и будет хоть миллион клиентов. Ну хорошо, допустим випилен сервер на 10к клиентов, а завтра нужно держать 100к, так всё равно придётся разносить по машинам. Тут опять вопрос: сколько времени понадобилось на выпиливание (+отладка, сервер-то сложный), сколько это стоило? Не дешевле ли было прикупить компов для тривиальной реализации, а потом выпиливать сложный сервер? А если функциональность с низким траффиком, но нетривиальной логикой, насколько просто будет добавить новую фичу в сложный сервер? Я далек от всего этого веба (и слава богу), но мне было бы интересно узнать что то за волшебный "кластер". То есть можно написать "тупо" (1 коннект на 1 клиента) и потом "кластер" решит все проблемы? Если несложно, "на пальцах" поясните основные идеиСпасибо Название: Re: Алгоритм высоконагруженного сервера Отправлено: ufna от Январь 22, 2011, 13:44 А первая ссылка в гугле не? )
Название: Re: Алгоритм высоконагруженного сервера Отправлено: brankovic от Январь 22, 2011, 13:57 Я далек от всего этого веба (и слава богу), но мне было бы интересно узнать что то за волшебный "кластер". Кластеры бывают разные, я имею ввиду не суперкомпьютерный кластер, а множество машин соединённых по лану в датацентре. Схема примерно такая: Есть некий сервер, пусть отдающий файлы. Есть N машин, на каждой стоит такой сервер. Есть M "внешних" машин, на которых стоит nginx. Клиент обращается на одну из внешних M машин, nginx, в зависимости от слоя клиента, проксирует запрос на один из несколько из N серверов. Существуют нюансы, но в целом всё примитивно. |