В чем разница между: асинхронной, неблокирующей и событийной архитектурой?

  1. Какая разница между:

    • Asynchronous,
    • Неблокирующий и
    • Event-base архитектуры?
  2. Может ли что-то быть одновременно асинхронным и неблокирующимсобытийным)?

  3. Что важнее всего в программировании, чтобы что-то было: асинхронное, неблокирующее и / или событийная (или все 3)?

Если бы вы могли привести примеры, это было бы здорово.

Этот вопрос задается, потому что я читал эту замечательную статью StackOverflow на аналогичную тему, но она не Не отвечаю на мои вопросы выше.




Ответы (5)


Асинхронный Асинхронный буквально означает несинхронный. Электронная почта асинхронная. Вы отправляете письмо и не ожидаете ответа СЕЙЧАС. Но это не неблокирующий. По сути, это означает архитектуру, в которой «компоненты» отправляют сообщения друг другу, не ожидая немедленного ответа. HTTP-запросы синхронны. Отправьте заявку и получите ответ.

Неблокирующий. Этот термин чаще всего используется в отношении ввода-вывода. Это означает, что когда вы выполняете системный вызов, он немедленно вернется с любым результатом, не переводя ваш поток в спящий режим (с большой вероятностью). Например, неблокирующие вызовы чтения / записи возвращаются со всем, что они могут сделать, и ожидают, что вызывающий абонент выполнит вызов снова. Например, try_lock - это неблокирующий вызов. Он будет заблокирован, только если блокировка может быть получена. Обычная семантика для системных вызовов - блокировка. read будет ждать, пока не будет данных, и переведет вызывающий поток в спящий режим.

Event-base Это термин происходит от libevent. неблокирующие вызовы чтения / записи сами по себе бесполезны, потому что они не говорят вам, «когда», если вы перезвоните им (повторить попытку). select / epoll / IOCompletionPort и т. д. - это разные механизмы для определения из ОС, «когда» эти вызовы должны возвращать «интересные» данные. libevent и другие подобные библиотеки предоставляют оболочки для этих средств мониторинга событий, предоставляемых различными операционными системами, и предоставляют согласованный API для работы, работающий в разных операционных системах. Неблокирующий ввод-вывод идет рука об руку с Event-base.

Я думаю, что эти термины частично совпадают. Например, протокол HTTP является синхронным, но реализация HTTP с использованием неблокирующего ввода-вывода может быть асинхронной. Опять же, неблокирующий вызов API, такой как чтение / запись / try_lock, является синхронным (он немедленно дает ответ), но «обработка данных» является асинхронной.

person Rohit Karlupia    schedule 28.02.2012
comment
Хороший момент по поводу неблокирования, требующего постоянного опроса, в то время как асинхронный режим может быть основан на push. - person Alexander Torstling; 17.10.2015
comment
Вы определили синхронный как получение немедленного ответа, но когда я гуглил синхронно, все словари определяли его как «происходит одновременно», а не «немедленный ответ». - person IntelliData; 27.10.2016
comment
Как меня блокируют, когда я отправляю электронное письмо, но не жду ответа? Я могу заняться своими делами, пока жду ответа. - person Koray Tugay; 22.03.2017

В асинхронном оборудовании код просит какую-то сущность сделать что-то и может делать другие вещи, пока действие выполняется; как только действие завершено, сущность обычно каким-то образом сигнализирует коду. Неблокирующая архитектура будет отмечать спонтанно возникающие действия, которые могут быть интересны коду, и позволять коду спрашивать, какие такие действия произошли, но код узнает о таких действиях только тогда, когда он явно спрашивает о них. Архитектура, основанная на событиях, будет подтверждать код, когда события происходят спонтанно.

Рассмотрим последовательный порт, из которого код захочет получить 1000 байт.

В архитектуре блокирующего чтения код будет ждать, пока не прибудет 1000 байт, или пока он не решит отказаться.

В архитектуре с асинхронным чтением код сообщит драйверу, что он хочет 1000 байтов, и получит уведомление, когда будет получено 1000 байтов.

В неблокирующей архитектуре код может в любой момент спросить, сколько байтов прибыло, и может прочитать любые или все такие данные, когда сочтет нужным, но единственный способ узнать, когда все данные прибыли, - это спросить; если код хочет узнать в течение четверти секунды, когда прибыл 1000-й байт, он должен проверять каждую четверть секунды или около того.

В архитектуре, основанной на событиях, драйвер последовательного порта будет уведомлять приложение каждый раз, когда поступают какие-либо данные. Драйвер не знает, сколько байтов требуется приложению, поэтому приложение должно иметь возможность обрабатывать уведомления для сумм, которые меньше или больше, чем требуется приложению.

person supercat    schedule 13.04.2012

Итак, чтобы ответить на ваш первый и второй вопрос:

Неблокирование фактически то же самое, что и асинхронный - вы делаете вызов, и вы получите результат позже, но пока это происходит, вы можете делать что-то еще. Блокировка - наоборот. Вы ждете звонка, прежде чем продолжить свое путешествие.

Теперь асинхронный / неблокирующий код звучит просто фантастически, и это так. Но у меня есть слова предупреждения. Асинхронный / неблокирующий режим отлично подходит для работы в ограниченных средах, например, в мобильном телефоне ... рассмотрите ограниченный ЦП / память. Это также хорошо для интерфейсной разработки, когда ваш код должен каким-то образом реагировать на виджет пользовательского интерфейса.

Асинхронность имеет фундаментальное значение для того, как все операционные системы должны работать - они делают дерьмо за вас в фоновом режиме и будят ваш код, когда они сделали то, что вы просили, а когда этот вызов не работает, вам говорят, что это не так. работают либо по исключению, либо по какому-либо объекту кода возврата / ошибки.

В тот момент, когда ваш код запрашивает что-то, на что потребуется время, ваша ОС знает, что может заняться другими делами. Ваш код - процесс, поток или эквивалент, блоки. Ваш код полностью не обращает внимания на то, что еще происходит в ОС, пока он ожидает установления этого сетевого подключения, или пока он ожидает этого ответа от HTTP-запроса, или пока он ожидает этого чтения / записи файла, и скоро. Ваш код мог бы «просто» ждать щелчка мыши. То, что на самом деле происходило в то время, было то, что ваша ОС плавно управляла, планировала и реагировала на «события» - вещи, на которые ОС обращает внимание, такие как управление памятью, ввод-вывод (клавиатура, мышь, диск, Интернет), другие задачи, восстановление после сбоя и т. д.

Операционные системы чертовски хардкорны. Они действительно хорошо скрывают от вас, программиста, все сложные асинхронные / неблокирующие вещи. Именно так большинство программистов пришли к тому, что мы имеем сегодня, с программным обеспечением. Сейчас мы достигли пределов ЦП, люди говорят, что для повышения производительности можно делать что-то параллельно. Это означает, что асинхронный / неблокирующий режим кажется очень подходящим вариантом, и да, если ваше программное обеспечение этого требует, я могу согласиться.

Если вы пишете внутренний веб-сервер, действуйте осторожно. Помните, что вы можете масштабировать по горизонтали гораздо дешевле. Netflix / Amazon / Google / Facebook - очевидные исключения из этого правила просто потому, что для них дешевле использовать меньше оборудования.

Я скажу вам, почему асинхронный / неблокирующий код - это кошмар для серверных систем ...

1) Это превращается в отказ в обслуживании продуктивности ... вы должны думать НАМНОГО больше, и на этом пути вы делаете много ошибок.

2) Следы стека в реактивном коде становятся неразборчивыми - трудно понять, что называется, что, когда, почему и как. Удачи с отладкой.

3) Вы должны больше думать о том, как что-то терпит неудачу, особенно когда многие вещи выходят из строя по сравнению с тем, как вы их отправили. В старом мире вы делали одно дело за раз.

4) Сложнее проверить.

5) Сложнее поддерживать.

6) Это больно. Программирование должно приносить радость и веселье. Только мазохисты любят боль. Люди, которые пишут параллельные / реактивные фреймворки, являются садистами.

И да, я написал как синхронизацию, так и асинхронность. Я предпочитаю синхронный, поскольку 99,99 серверных приложений могут справиться с этой парадигмой. Интерфейсным приложениям, без сомнения, нужен реактивный код, и так было всегда.

  1. Да, код может быть асинхронным, неблокирующим И основанным на событиях.

  2. Самое важное в программировании - убедиться, что ваш код работает и отвечает в приемлемое время. Придерживайтесь этого ключевого принципа, и вы не ошибетесь.

person user924272    schedule 21.02.2018
comment
** ОБНОВЛЕНИЕ ** Поиграв с Go и изучив каналы и подпрограммы, я должен сказать, что мне на самом деле нравится делать мой код более параллельным, потому что конструкции языка берут на себя всю боль от авторов фреймворка Sadist. У нас есть безопасное слово в мире асинхронной обработки - и это Go! - person user924272; 17.06.2020

Для меня неблокирование означает, что выполнение действия в потоке не зависит от выполнения других потоков, в частности, для него не требуется критическая секция.

Асинхронный означает, что выполнение происходит вне потока вызывающего и потенциально откладывается. Выполнение обычно происходит в другом потоке.

Чтение одновременных данных является неблокирующим (блокировка не требуется), но синхронным. И наоборот, одновременная запись данных в синхронном режиме является блокирующей (требуется монопольная блокировка). Один из способов сделать его неблокирующим с точки зрения основного потока - сделать запись асинхронной и отложить их выполнение.

Концепция события - это нечто иное, что, грубо говоря, означает, что вас информируют, когда что-то происходит. Если запись была выполнена асинхронно, может возникнуть событие, чтобы проинформировать другие части системы после того, как запись была выполнена. Остальные части откликнутся на событие. Система может быть построена исключительно на событиях как единственном способе связи между компонентами (подумайте о модели акторов), но это не обязательно.

Эти три термина связаны, но для меня это разные концепции. Однако может случиться так, что люди используют их как взаимозаменяемые.

person ewernli    schedule 10.11.2011

Как правило, неблокирующая архитектура основана на вызовах методов, которые, хотя они могут выполняться в течение длительного времени в рабочем потоке, не блокируют вызывающий поток. Если вызывающему потоку необходимо получить информацию о задаче, выполняемой рабочим потоком, или от нее, это должен сделать вызывающий поток.

Архитектура, основанная на событиях, основана на концепции кода, выполняемого в ответ на запускаемые события. Время выполнения кода обычно не детерминировано, но события могут вызывать методы блокировки; Тот факт, что система основана на событиях, не означает, что все, что она делает, не блокирует.

Как правило, асинхронная архитектура - это неблокирующая архитектура, основанная на событиях.

Когда выполняется асинхронный вызов, обработчики событий регистрируются в API, предоставляющем услуги синхронизации, чтобы уведомить вызывающего абонента о том, что произошло то, что его интересует. Затем вызов немедленно возвращается (неблокирующее поведение), и вызывающий может продолжить выполнение. Когда события отправляются обратно в вызывающий процесс, они будут обрабатываться в каком-то потоке этого процесса.

Важно понимать, будут ли события обрабатываться в одном потоке или нет, поскольку это повлияет на неблокирующий характер выполнения, но я лично не знаю о каких-либо библиотеках, которые выполняют управление асинхронным выполнением на однопоточный.

Я удалил приведенный выше абзац, потому что он не совсем верен, как указано. Мое намерение состояло в том, чтобы сказать, что даже несмотря на то, что операции в системе являются неблокирующими, например, выполнение вызовов к объекту ОС и продолжение выполнения, природа однопоточного выполнения означает, что когда события запущенные, они будут конкурировать с другими задачами обработки за время вычислений в потоке.

person Matt Mills    schedule 28.10.2011
comment
Разве ваш последний абзац не противоречит вашему утверждению, что асинхронная архитектура ... неблокирующая? - person nickb; 28.10.2011
comment
Думаю, я не очень хорошо постарался ответить на часть вашего вопроса, посвященную определениям; Я выложу обновление. Но нет, природа однопоточного выполнения заключается в том, что каждая операция по своей сути блокирует во время выполнения, что делает асинхронность еще более полезной. - person Matt Mills; 29.10.2011