![]() |
|
Модераторы: feodorv |
![]()
|
|
| mabrarov |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 100 Регистрация: 12.1.2011 Где: Казань Репутация: нет Всего: 9 |
Согласен. Только меня постоянно мучает вопрос: "ну все равно же эти потоки как-то должны "общаться" друг с другом?" Критические секции/мютексы очень похожи в этом случае на вырожденный вариант очереди с размерм в один элемент. Как сообщить thread-based объекту session, что пора кхм.. завершиться? Тупо закрыть сокет (на котором thread-based session м/б залочена в блокирующем вводе/выводе) в другом потоке - выглядит как-то криво (я знаю, что так и делают). Использовать Windows-события - форменное извращение. Использовать Windows Event для ожидания окончания ввода-вывода + дополнительный Event и WaitForMultipleObjects - натуральный костыль. Понятно, что есть разница м/у "красивая теория" и "суровая практика", но так хочется чего-то обобщенного. Это сообщение отредактировал(а) mabrarov - 15.11.2011, 09:17 |
|||
|
||||
| Lazin |
|
||||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3820 Регистрация: 11.12.2006 Где: paranoid oil empi re Репутация: 5 Всего: 154 |
Можно не закрывать а сделать сокету shutdown, если религия не позволяет закрывать сокет, можно использовать pooling, читаем из сокета с таймаутом, при достижении таймаута проверяем не нужно ли завершиться, либо не превышено ли критическое время ожидания ответа и выполняем соответствующие действия, можно и закрыть(в чем проблема просто тупо закрыть сокет я не очень понимаю). Мы не знаем какая там происходит обработка данных, может там вообще не потребуется синхронизация или потребуется очень простая синхронизация. Добавлено через 7 минут и 36 секунд
ты не поверишь! xD мьютекс (если это fair мьютекс) это и есть очередь, самая настоящая, first in first out |
||||
|
|||||
| drug007 |
|
|||
|
Бывалый ![]() Профиль Группа: Участник Сообщений: 196 Регистрация: 3.11.2011 Репутация: 1 Всего: 1 |
Согласен, но к первому предложению добавлю, что также event driven сервер имеет смысл использовать, когда бизнес-логика тоже event driven, как в моем случае. Т.о. drawback от распределенной логики все равно будет присутствовать, зато архитектура приложения будет единой. Плюс это не конкретное задание на конкретный продукт с конкретными требованиями, это больше исследовательская модель для бизнес-логики, поэтому выбор event driven модели как более универсальной оправдан даже несмотря на больший оверкод и оверхед. А уже при допиливании вполне можно будет сделать конкретные версии. Хотя требования к латентности в моем случае высокие и это большой минус асинхронному серверу, но с другой стороны, т.к. логика тоже асинхронная, отказавшись от асинхронного сервера я просто перенесу латентность с ввода/вывода на логику, а латентность все равно останется. Ибо код в цепочке асинхронных вызовов всегда будет дольше обрабатываться, чем аналогичный код вызываемый последовательно из-за отсутствия лишних вызовов. Это сообщение отредактировал(а) drug007 - 15.11.2011, 10:49 |
|||
|
||||
| mabrarov |
|
||||||||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 100 Регистрация: 12.1.2011 Где: Казань Репутация: нет Всего: 9 |
Это уже выглядит как костыль. Нет, я понимаю что так делали и делают. Это такой "рабочий" вариант - но все равно костыль, как ни крути. Добавлено @ 10:44
Проблемы особой нет. За исключением логики. Наш класс session получается не простой. Его метод session::close() можно вызывать из любого потока в любое время. Но только, если underlying socket library гарантирует то же самое для socket::close() (shutdown). Плохо, когда классы так сильно связаны с потоками. В случае ma::echo::server::session - session связан с task scheduler (asio::io_service::strand и asio::io_service). А тот - с потоками. Добавлено @ 10:47
В том-то и дело, что синхронизация в каком-либо виде требуется всегда. Даже если это web-сервер. Хотя бы для того чтобы тот же session_manager мог дать команду "завершиться" всем session. Добавлено @ 10:49
Э, ну это уже нечестно Это сообщение отредактировал(а) mabrarov - 15.11.2011, 11:18 |
||||||||
|
|||||||||
| mabrarov |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 100 Регистрация: 12.1.2011 Где: Казань Репутация: нет Всего: 9 |
На счет оверкода (что-то без регистрации перестали пускать).
Вкратце, я понимаю, что "не писать сложный код, потому что (именно) условия задачи позволяют обойтись более простым" в производстве нормально. "My personal bias is to try to avoid the complexity side of such tradeoffs, but sometimes its advantages are too compelling to ignore" (Andrew Koenig). Это сообщение отредактировал(а) mabrarov - 15.11.2011, 11:11 |
|||
|
||||
| mabrarov |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 100 Регистрация: 12.1.2011 Где: Казань Репутация: нет Всего: 9 |
Я имел в виду shared data (например, флаги и состояния), защищенные критическими секциями/мютексами. Это сообщение отредактировал(а) mabrarov - 15.11.2011, 11:31 |
|||
|
||||
| Lazin |
|
||||||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3820 Регистрация: 11.12.2006 Где: paranoid oil empi re Репутация: 5 Всего: 154 |
ето как? ничего не понял, где они высокие? высокие, это когда десятки микросекунд, а не сотни миллисекунд
латентность сервера = I/O time + CPU time, оно в любом случае никуда не денется, используя разные архитектуры сервера можно немного менять второе слагаемое, но не первое
Неа, не костыль. Close - это когда нужно остановить обмен данными через сокет на одной из сторон без ведома второй. Если нужно быстро остановить сервер, то это как раз тот случай. Не костыль, это когда у нас в протоколе есть возможность остановить сессию выполнив определенные действия. А если серверу действительно нужно просто взять и отвалиться, то нужно именно сделать close и все равно из какого потока, главное что-бы все отвалилось сразу.
И в event driven архитектуре в том числе. Мало того, в event driven сервере ее сделать сложнее, ибо нужно синхронизировать не только разные сессии но и внутри сессии. Скажем в рамках одного подключения пришли 2 сообщения, одно начало обрабатываться в одном потоке, второе в другом. Именно поэтому в asio есть strand-ы. Либо у нас будет один io_service на поток, в этом случае вам придется возиться с балансировкой нагрузки. В случае threaded сервера нужно просто синхронизировать доступ к общим данным. Это проще. Можно вообще построить threaded сервер так, что-бы каждый поток крутил что-то вроде цикла обработки сообщений, тобишь был event driven но в рамках одного соединения, в этом случае можно будет отказаться от общей памяти, организовав обмен сообщениями между потоками. Это плохо только тогда, когда сессий может быть очень много. В остальных случаях это скорее хорошо, ибо не нужно об этом думать. |
||||||
|
|||||||
| mabrarov |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 100 Регистрация: 12.1.2011 Где: Казань Репутация: нет Всего: 9 |
Согласен. |
|||
|
||||
| Lazin |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3820 Регистрация: 11.12.2006 Где: paranoid oil empi re Репутация: 5 Всего: 154 |
вообще, автор писал что у него тяжелая обработка данных происходит, это автоматически означает низкую пропускную способность event driven сервера
max event dirven server throughput = number of CPUs / CPU time per query для многопоточного сервера: max threaded server throughput = number of threads / (IO time per query + CPU time per query) вторая формула справедлива до тех пор, пока мы еще не уперлись в возможности процессора, то есть он не загружен на 100% отсюда видно, что в том случае, если IO time per query сильно больше чем CPU time per query, то нужно использовать event driven архитектуру, в противном случае(интенсивные вычисления) - нужно использовать threaded архитектуру |
|||
|
||||
| mabrarov |
|
||||||||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 100 Регистрация: 12.1.2011 Где: Казань Репутация: нет Всего: 9 |
Все дело в том, что в идеале, хотелось бы иметь по-меньше классов (тот же сокет), которые имели бы thread-safe методы, так как это дается не бесплатно и предполагает, что класс заранее планировался для использования в многопоточной среде. Плохо by-design, но вполне используется, потому как никому не хочется лезть в дебри event driven. Добавлено @ 11:57
Ну это вроде бы уже "обсосали". Конечно, да. Классика же. Я просто о своем (о наболевшем) начал, как обычно. Добавлено @ 12:01
В том-то и дело, что в event driven архитектуре на базе Asio мы (архитектурно) разгружаем класс session от непосредственной синхронизации (и от знания того, что он будет использоваться в многопоточной среде), оставляя синхронизацию strand-ам. Добавлено @ 12:04
"что-то вроде цикла обработки сообщений" обеспечивает strand. "в этом случае можно будет отказаться от общей памяти, организовав обмен сообщениями между потоками" - так это и есть очередь - та же общая память, почти тот же strand. Пора заканчивать. Сплошной оффтоп пошел. Просто приятно обсудить наболевшие вопросы. Это сообщение отредактировал(а) mabrarov - 15.11.2011, 12:08 |
||||||||
|
|||||||||
| Lazin |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3820 Регистрация: 11.12.2006 Где: paranoid oil empi re Репутация: 5 Всего: 154 |
с каких это пор ф-я WSAClose стала классом? шутка вам не кажется, что использовать event driven подход для того что-бы остановить event driven систему это как-то не ок? я лично люблю останавливать сервер так, что-бы это произошло за ограниченное время (1), каждая сессия смогла обработать разрыв соединения так, что-бы не испортить что-либо в базе или еще где нибудь (2). Вот close для этого оч. хорошо подходит. В коде потока сессии это все выражается в том, что один из send-ов или recv-ов бросает исключение а какой-нибудь try - catch его ловит. Причем все это происходит в предсказуемом порядке, сначала перестаем принимать новые подключения, потом закрываем первую сессию, первая сессия завершилась, закрываем вторую... В случае event driven тоже все просто, только вместо try catch у нас вызывается один из хэндлеров. Проблема этого подхода в том, что нужно явным образом посигналить(установить event или еще что нибудь) о том что сессия - все. Помимо этого, код обработки разрыва соединения приходится дублировать между всеми обработчиками. Помимо этого сокет может быть закрыт не только во время ожидания выпонения операции чтения-записи, но и во время обработки данных, в этом случае следующий вызов send_async/recv_async (или как это там называется) бросит исключение, вот вам еще одна точка обработки ситуации разрыва соединения. В общем, сложнее это. Добавлено через 9 минут и 14 секунд нужно помнить что у тебя все должно идти через strand, вызовешь случайно метод класса - сессии не через strand и все хотя я согласен с тем что если мы пришли к тому что-бы городить цикл обработки сообщений внутри каждого потока, то проще просто использовать boost.asio у меня - все |
|||
|
||||
| drug007 |
|
||||
|
Бывалый ![]() Профиль Группа: Участник Сообщений: 196 Регистрация: 3.11.2011 Репутация: 1 Всего: 1 |
В общих чертах бизнес-логика представляет собой набор взаимосвязанных КА (и сама КА тоже). Переход одного КА в другое состояние может являться событием для других. И такая "волна" событий распространяется от источника первоначального события. И таких источников много, и они влияют друг на друга. Более того, КА появляются и удаляются динамически. Плюс есть задача репликации данных между серверами - проще делать репликацию, когда у тебя есть событие, которое говорит, что такие-то данные изменились, линейный алгоритм может означать только периодический обзор всех данных на предмет изменения. На данный момент я думаю, что реализовать такую модель линейным алгоритмом будет сложнее, чем с помощью событий. Хотя я могу заблуждаться. Немного оффтоп, но насколько верны мои предположения о простоте реализации такого способа репликации?
Пинг, что я привел, это качество каналов связи. Это не требование иметь такую латентность, а требование сохранять функциональность при таком пинге. Ибо сервер, работоспособный в LAN, при первом же запуске в WAN показал, что такие пинги не для него. Сам же сервер должен иметь латентность, стремящуюся к нулю. Вот тут категорически не соглашусь. Вы же сами утверждали, что потоковая версия имела латентность вдвое меньше чем асинхронная? А это как раз первое слагаемое. |
||||
|
|||||
| Lazin |
|
||||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3820 Регистрация: 11.12.2006 Где: paranoid oil empi re Репутация: 5 Всего: 154 |
так то для IPC на одной машине, асинхронная версия делала в 2 раза больше системных вызовов чем синхронная
события != асинхронность, в данном случае все очень даже синхронно, изменилось состояние -> сгенерировалось событие -> изменилось состояние другого КА и тд вот если бы изменения в разных КА могли происходить с разной скоростью, то это была бы асинхронная модель, но я не вижу в этом смысла |
||||
|
|||||
| drug007 |
|
|||
|
Бывалый ![]() Профиль Группа: Участник Сообщений: 196 Регистрация: 3.11.2011 Репутация: 1 Всего: 1 |
Похоже на то, что вы разговариваете о чем то до боли знакомом вам обоим. Настолько знакомом, что вы даже детали некоторые пропускаете, т.к. понимаете друг друга с полуслова. А вот я посмотрев данные формулы, пришел к выводу, что они не выражают общий случай, а могут быть применены только в определенном контексте, который не был озвучен. Мой опыт пока не позволяет понимать вас с полуслова без деталей. =) Поэтому я не буду комментировать формулы, а просто их проигнорирую, при все своем уважении. Или попрошу уточнить, если это не уведет в оффтоп. Это сообщение отредактировал(а) drug007 - 15.11.2011, 12:47 |
|||
|
||||
| mabrarov |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 100 Регистрация: 12.1.2011 Где: Казань Репутация: нет Всего: 9 |
Ну почему же. Как раз в event driven системе останов (имеется в виду плановый, а не исключительная ситуация с обрывом всего и вся) - это просто event, который получает сессия. Дальше она уже сама правильно (!) завершит работу. Например, сначала дождется окончания обработки очередного запроса СУБД, отправит подготовленный ответ, а уже потом сделает shutdown + close. В случае же прямого вызова socket::close() из другого потока, если поток (thread) сессии был заблокирован на "отправке подготовленного ответа" (блокирующий socket::write()) - мы как раз получим невозможность реализации планового останова. Конечно, в реальности "прямой вызов socket::close() из другого потока" для планового останова threaded session никто не делает. Просто session в случае, если сокет закрывать нельзя ("отправка подготовленного ответа") через примитивы синхронизации лочит session shared data и устанавливает флаг "не вздумайте закрыть сокет". session::close() так же лочит session shared data, если "разрешено" - закрывает сокет и, наконец, обязательно устанавливает флаг "пора закругляться по такой-то причине" (а ниже основной поток сервера уже ждет а-ля session::join()). threaded session в этом случае должна так же периодически лочить session shared data и проверять флаг останова (ну да, atomic-варианты никто не отменял) - чувствуете, насколько логика такой session связана с потоками в отличие от использования asio::io_service::strand (который, по сути, обычная concurrent очередь функторов)?. Логика в обоих случаях одна и та же. Просто event driven + threads "разрывает мозг" необходимостью выносить участки кода (те что в threaded session идут м/у проверками флага останова) в отдельные event/task и добавляет накладных расходов (нехило так - как и любой task-based parallelism). В реальном мире - все есть КА. И работает как раз event driven и именно параллельно. Event driven сложнее именно из-за C/C++ - у этих языков все на более низком уровне (и хорошо). Взять тот же Erlang, и, думаю, будет уже не так "больно мозгу". На этом закончу мое участие в теме (особенно, с учетом того, что я согласен с Lazin и меня просто задевает то, что частенько стараются избавиться от сложности многопоточных асинхронных event-driven серверов лишь потому, что... нет готового решения по типу "просто написать модуль для nginx") и пойду обедать. Это сообщение отредактировал(а) mabrarov - 15.11.2011, 13:48 |
|||
|
||||
![]()
|
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | C/C++: Сети | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |