Здравствуйте, stronciy77, Вы писали:
Pzz>>Это вопрос о постановке задачи: что делать, если данные поступают быстрее, чем клиенты успевают их потреблять?
S>Пробрасывать все данные которые не успел получить пользователь, то есть не получил лови следующий пакет ! ( К сожалению это единственных выход.)
Совершенно не обязательно это единственный выход.
Скорость поступления данных от чего зависит? Если данные летят с неограниченной скоростью (т.е., скорость определяется только скоростью рассылки), то при предложенном вами подходе только один, самый быстрый, клиент будет получать все данные. Остальным останется только зубами щелкать
Если же у источника данный есть своё собственное ограничение скорости, то возможны варианты. К примеру, клиенты, которые успевают в среднем, но не успевают в пиках, могли бы получать все данные без потерь, если обеспечить для них буферизацию. И только при переполнении такого буфера пришлось бы данные выбрасывать.
S>Не создавать же для каждого пользователя пул сообщений и раздавать с него ? Тогда подтврждение получения будет потреблять еще больше ресурсов !
У вас не высоконагруженный сервер, и проблемы с нагрузкой существуют только от плохой реализации. Нормальная реализация делала бы все вышеперечисленное, создавая загрузку на процессор, которую в микроскоп не разглядишь.
S>Вот такое ожидаемое поведение, что успел, то и получил
И что им делать, бедолагам, если данные с пропусками? Они хоть должны знать-то, что не все получили?
Re[8]: Нагруженный TCP сервер как и на чем реализовать
Здравствуйте, Pzz, Вы писали:
Pzz>Здравствуйте, stronciy77, Вы писали:
Pzz>>>Это вопрос о постановке задачи: что делать, если данные поступают быстрее, чем клиенты успевают их потреблять?
S>>Пробрасывать все данные которые не успел получить пользователь, то есть не получил лови следующий пакет ! ( К сожалению это единственных выход.)
Pzz>Совершенно не обязательно это единственный выход.
Pzz>Скорость поступления данных от чего зависит? Если данные летят с неограниченной скоростью (т.е., скорость определяется только скоростью рассылки), то при предложенном вами подходе только один, самый быстрый, клиент будет получать все данные. Остальным останется только зубами щелкать
Скорость поступления данных довольно большая. В среднем 4 раза в секунду, приходят пакеты от 1кб до 4кб, очень редко более длинные, скажем по 8кб
Это строки ограниченные знаком '$' сейчас работает ретранслятор, который перенаправляет всем клиентам с такой же скоростью данные, но из-за медленных накапливается пул в памяти (от меня не зависящий) который сам медленно раздает всем, и если медленных ребят много, скажем 50 из 100 , то все начинают получать данные очень медленно. Как програмно определять кто быстрый кто медленный я не знаю. И даже не догадываюсь.
Pzz>Если же у источника данный есть своё собственное ограничение скорости, то возможны варианты. К примеру, клиенты, которые успевают в среднем, но не успевают в пиках, могли бы получать все данные без потерь, если обеспечить для них буферизацию. И только при переполнении такого буфера пришлось бы данные выбрасывать.
Ок, буфер, это общая куча, или для каждого свой ? Если общая куча, то тогда будет обратный трафик, с номером, последнего принятого пакета, и нагрузка на выгребание всех данных пришедших за это время... Если у каждого свой, то как это сделать, в потоках ?
S>>Не создавать же для каждого пользователя пул сообщений и раздавать с него ? Тогда подтврждение получения будет потреблять еще больше ресурсов !
Pzz>У вас не высоконагруженный сервер, и проблемы с нагрузкой существуют только от плохой реализации. Нормальная реализация делала бы все вышеперечисленное, создавая загрузку на процессор, которую в микроскоп не разглядишь.
Так какая реализация будет самая лучшая для такой задачи ?
Pzz>И что им делать, бедолагам, если данные с пропусками? Они хоть должны знать-то, что не все получили?
А вот это проблема, потому что в принципе данные критичны ... Но как их доставлять медленным ребятам, я до сих пор не знаю !
Re[9]: Нагруженный TCP сервер как и на чем реализовать
Здравствуйте, stronciy77, Вы писали:
S>Скорость поступления данных довольно большая. В среднем 4 раза в секунду, приходят пакеты от 1кб до 4кб, очень редко более длинные, скажем по 8кб
Ну т.е., даже если 4 раза в секунду по 4К, это 16К в секунду, т.е., 128 килобит. Копейки, если ваши клиенты не сидят на телефонном модеме
S>Это строки ограниченные знаком '$' сейчас работает ретранслятор, который перенаправляет всем клиентам с такой же скоростью данные, но из-за медленных накапливается пул в памяти (от меня не зависящий) который сам медленно раздает всем, и если медленных ребят много, скажем 50 из 100 , то все начинают получать данные очень
Это вы в каждом письме повторяете. Я уже запомнил, спасибо.
S>медленно. Как програмно определять кто быстрый кто медленный я не знаю. И даже не догадываюсь.
Ну, например, по тому факту, что очередь к данному клиенту доросла до ограничителя. Но это не будет работать, если источник данных может вывалить слишком много за раз.
S>Ок, буфер, это общая куча, или для каждого свой ? Если общая куча, то тогда будет обратный трафик, с номером, последнего принятого пакета, и нагрузка на выгребание всех данных пришедших за это время... Если у каждого свой, то как это сделать, в потоках ?
Зачем вам обратный трафик?
Потоки вам только мешают в этой задаче. Я бы сделал все в одном потоке. Выглядит это сложнее, но на самом деле — проще, т.к. не надо думать о синхронизации.
Можно сделать общий буфер, можно сделать по буферу для каждого клиента — при таком маленьком трафике любое решение будет работать. Я бы сделал общий кольцевой буфер с одним write pointer'ом, который сдвигается, когда в буфер добавляют данные, и по одному read pointer'у на каждого получателя. Но при этом может быть сложно вычислить, кто (а, вернее, на сколько) отстает больше всех — не сканировать же все 50-100 указателей каждый раз (RB-деревья рулят, но вы вряд ли захотите с ними возиться).
С другой стороны, по буферу на клиента при такой маленькой скорости тоже будет вполне адекватным решением.
Pzz>>И что им делать, бедолагам, если данные с пропусками? Они хоть должны знать-то, что не все получили? S>А вот это проблема, потому что в принципе данные критичны ... Но как их доставлять медленным ребятам, я до сих пор не знаю !
Вы никак не можете доставить данные быстрее, чем можете. Вопрос в том, что вы делаете, если обнаруживаете, что данных у вас больше, чем в дырку пролазит.
Вполне адекватным может быть решение 1) написать в требованиях минимальную скорость канала к клиенту 2) закрывать соединение, если клиент не выполняет этого требования
Re: Нагруженный TCP сервер как и на чем реализовать
Здравствуйте, stronciy77, Вы писали:
S>То есть накапливать для каждого пользователя (стек пакетов) и при очередном обходе, выгребать столько сколько может принять на данный момент ? А как получить подтверждение что он получил предыдущий пакет ? Хранить MTU каждого и вычислять сколько может принять ? То есть не могу в голове собрать картинку Придется рисовать на бумаге.
Подтверждение о получении потока байтов Вы можете получить от получателя. Заложите это в свой протокол. Как может в этом помочь MTU — для меня загадка.
Re[6]: Нагруженный TCP сервер как и на чем реализовать
Здравствуйте, stronciy77, Вы писали:
S>И потом я же не cisco как я узнаю, кто у меня медленный, кто быстрый ?
А при чем здесь это? А накопить статистику? Вы же можете реализовать такой протокол поверх TCP, используя который сможете определять скорость передачи и снижать/повышать ее по мере необходимости.
Re[4]: Нагруженный TCP сервер как и на чем реализовать
Здравствуйте, AltCtrlDel, Вы писали:
ACD>Ну, асинхронные методы то там есть, конечно. А так, от твоей реализации именно твоей задачи зависит. Если "медленные", застревают и не успевают забирать иногда, так у меня для этого случая специально sqlite прикручена в виде внешнего буфера. Для медленных клиентов смотри размер их mtu, может они вообще через GPRS заходят. Не передавай мелкими порциями, накопи хотя бы до mtu*3, а то много полупустых пакетов летать будет.
Какие все умные, а шизею. Интересно, сейчас все сетевые программы так и пишутся, или бывают исключения.
Hints:
0) Не mtu, а mss
1) Какой смысл накапливать до mtu*3, если передается все равно кусками по mtu?
2) Какой смысл накапливать до..., если это автоматически делает TCP?
3) Как узнать mtu пира?
Re[2]: Нагруженный TCP сервер как и на чем реализовать
Здравствуйте, Kernan, Вы писали:
K>У тебя в коде не используются неблокирующие сокеты. Прочитай про pool/epool и сделай через него. Либы, которые оборачивают это дело libevent, boost::asio и 9000 других.
У него венда, вообще-то. В венду пока не положили epool. Может, к 12-й версии положат. А может, решат, что родные IOCP ничем не хуже
Re[2]: Нагруженный TCP сервер как и на чем реализовать
Переход на C++ не решит проблемы.
Надо следить за буфером клиента — время за которое он полностью отправляет данные.
В синхронном варианте это интервал времени, за которое отрабатывает send
В асинхронном — время между вызовом send и onSend
Синхронный вариант не подходит в вашем случае, потому что первый медленный клиент обеспечивает задержку всем остальным.
Придется использовать асинхронные сокеты, с очередью сообщений на каждого клиента.
Если приходит новое сообщение, когда предыдущее еще не отправлено (не было onSend) — его не надо пихать в send, а положить в очередь.
Обязательно организовать отстрел клиента по максимальному количеству сообщений в очереди — иначе рано или поздно приложение выжрет память и свалится.
В общем надо понимать, что с задержками для медленных клиентов бороться бесполезно — если у них канал ужее, чем поток данных — то это гарантированные задержки, рост очереди и отстрел рано или поздно.
Ваша цель — минимизировать ущерб быстрым клиентам.
На чем писать — дело вкуса. У C#, Java нет проблем с производительностью для такой задачи
Связываться с C++ если нет опыта я бы не рекомендовал.
Если очень хочется — то boost:asio.
На чистых сокетах слишком много возможностей выстрелить себе в ногу.
Re[5]: Нагруженный TCP сервер как и на чем реализовать
S>То есть накапливать для каждого пользователя (стек пакетов) и при очередном обходе, выгребать столько сколько может принять на данный момент ?
когда у тебя заполнится выходная очередь для клиента, а подтверждения по tcp не будут поступать, то очередная асинхронная передача сама подвиснет.
S> А как получить подтверждение что он получил предыдущий пакет ?
Для этого, в своём слое, поверх TCP, делаешь подтверждения от клиентов.
Re[5]: Нагруженный TCP сервер как и на чем реализовать
Поправка принята. Настроить или узнать, при желании, мы можем размер mtu, но данные то передадутся mss = mtu-40 при IPv4 (а при использовании SSL ещё меньше).
Pzz>1) Какой смысл накапливать до mtu*3, если передается все равно кусками по mtu?
Именно потому что мы не контролируем, как поток по пакетам шинкуется. Если посылаем мелкими порциями, то порции, всё таки, должны быть большие. Чтобы остатки реже передавались.
Pzz>2) Какой смысл накапливать до..., если это автоматически делает TCP?
Он ждёт десятки-сотни милисекунд поступления новых данных для передачи, потом остатки, всё таки уходят. Если отсылаем черз 50 мС, тогда всё равно, конечно.
Pzz>3) Как узнать mtu пира?
Можно просто ориентироваться по типу подключения, настроить размер буфера клиента зная его тип соединения, настроить в винде, узнать выполнив пингование с запретом фрагментации...
Re: Нагруженный TCP сервер как и на чем реализовать
Здравствуйте, AltCtrlDel, Вы писали:
Pzz>>0) Не mtu, а mss
ACD> Поправка принята. Настроить или узнать, при желании, мы можем размер mtu, но данные то передадутся mss = mtu-40 при IPv4 (а при использовании SSL ещё меньше).
Вот до выделенного и надо было остановиться. Тогда никто не узнал бы, что вы не в курсе, что SSL живет над TCP, а не наоборот
Pzz>>1) Какой смысл накапливать до mtu*3, если передается все равно кусками по mtu?
ACD> Именно потому что мы не контролируем, как поток по пакетам шинкуется. Если посылаем мелкими порциями, то порции, всё таки, должны быть большие. Чтобы остатки реже передавались.
А почему не mtu*5?
Pzz>>2) Какой смысл накапливать до..., если это автоматически делает TCP?
ACD> Он ждёт десятки-сотни милисекунд поступления новых данных для передачи, потом остатки, всё таки уходят. Если отсылаем черз 50 мС, тогда всё равно, конечно.
Он это делает адаптивно и достаточно разумно. Сделать лучше, чем TCP делает автоматически, можно, но надо очень хорошо понимать, что вы делаете.
Pzz>>3) Как узнать mtu пира?
ACD> Можно просто ориентироваться по типу подключения, настроить размер буфера клиента зная его тип соединения, настроить в винде, узнать выполнив пингование с запретом фрагментации...
Нельзя по типу подключение — вы не можете знать, что между вами. Да и тип подключения вы толком не узнаете. А пинг может быть закрыт. В общем, даже встроенный в TCP Path MTU discovery работает через пень-колоду, а он гораздо ближе к нижнему уровню чем все, что вы можете понаделать из user space.
Re[7]: Нагруженный TCP сервер как и на чем реализовать
ACD>> (а при использовании SSL ещё меньше). Pzz>Вот до выделенного и надо было остановиться. Тогда никто не узнал бы, что вы не в курсе, что SSL живет над TCP, а не наоборот
Не поняли ничего, и улыбаетесь
При использовании SSL к нашим данным ещё добавляется 2-3 байта размера записи ssl. Это нужно учитывать при отсылки данных нечастыми небольшими порциями. Чтобы последний байт в отдельном пакете не ушёл.
Pzz>А почему не mtu*5?
Рекомендацию такую читал в книжке. Если нужно память под буфера экономить. Дальнейшее увеличение не так существенно влияет. Исследование такое проводилось. (Ссылку искать не нанимался, если чё).
Pzz>Нельзя по типу подключение — вы не можете знать, что между вами.
Отчего же нельзя. В клиентах настройка. При плохой связи через GPRS (реальный пример) подбор размера отсылаемых порций данных позволяет увеличить пропускную способность.
Pzz> А пинг может быть закрыт.
а я про реальные ситуации
Re[2]: Нагруженный TCP сервер как и на чем реализовать
От:
Аноним
Дата:
18.02.12 12:18
Оценка:
Здравствуйте, Gomes, Вы писали:
G>Бери мою библиотеку. G>prostoserver.com
Готов взять, сразу вопрос, чем она хороша ?
Re[2]: Нагруженный TCP сервер как и на чем реализовать
От:
Аноним
Дата:
18.02.12 14:41
Оценка:
Здравствуйте, Gomes, Вы писали:
G>Бери мою библиотеку. G>prostoserver.com
Вопрос, а как посредством Вашей библоитеки, организовать прием и передачу данных на разных портах. То есть, принимать данные, с одного порта, и передавать всем клиентам но на другой порт. Что бы избежать путаницы. С считаванием данных и передачей.
Re[3]: Нагруженный TCP сервер как и на чем реализовать
Здравствуйте, Аноним, Вы писали:
А>Вопрос, а как посредством Вашей библоитеки, организовать прием и передачу данных на разных портах. То есть, принимать данные, с одного порта, и передавать всем клиентам но на другой порт. Что бы избежать путаницы. С считаванием данных и передачей.
Хотелось бы знать задачу подробней. Это клиенты подключаются на разные порты, или как?
Re[4]: Нагруженный TCP сервер как и на чем реализовать
От:
Аноним
Дата:
18.02.12 14:58
Оценка:
Здравствуйте, Gomes, Вы писали:
G>Здравствуйте, Аноним, Вы писали:
А>>Вопрос, а как посредством Вашей библоитеки, организовать прием и передачу данных на разных портах. То есть, принимать данные, с одного порта, и передавать всем клиентам но на другой порт. Что бы избежать путаницы. С считаванием данных и передачей.
G>Хотелось бы знать задачу подробней. Это клиенты подключаются на разные порты, или как?
Один порт работает на прием данных, то есть источник приема один на одном порту.
На втором порте сидит куча клиентов, которые только принемают данные.
То есть можно ли с помощью Вашей библиотеки, организовать сковозной ретранслятор ?
Вот примерно такое:
|-------------| --------> Client A
A --> port(xxx) -->| Retranslator| (port yyy) --------> Client ...
|-------------| --------> Client Z
Re[4]: Нагруженный TCP сервер как и на чем реализовать
От:
Аноним
Дата:
18.02.12 15:05
Оценка:
Здравствуйте, Gomes, Вы писали:
G>Здравствуйте, Аноним, Вы писали:
А>>Вопрос, а как посредством Вашей библоитеки, организовать прием и передачу данных на разных портах. То есть, принимать данные, с одного порта, и передавать всем клиентам но на другой порт. Что бы избежать путаницы. С считаванием данных и передачей.
G>Хотелось бы знать задачу подробней. Это клиенты подключаются на разные порты, или как?
Предыдущая схема побилась не подумал про шрифт, вот такая схема, один порт приемник (xxx), второй порт раздает клиентам все что принемается через порт (yyy) то есть нужен быстрый ретранслятор сообщений.
|-------------| |--------> Client A
A --> port(xxx) -->| Retranslator| (port yyy) |--------> Client ...
|-------------| |--------> Client Z