В чем разница между: асинхронной, неблокирующей и Event-Base архитектурой? - PullRequest
77 голосов
/ 28 октября 2011
  1. В чем разница между:

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

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

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

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

Ответы [ 5 ]

79 голосов
/ 29 февраля 2012

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

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

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

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

18 голосов
/ 13 апреля 2012

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

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

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

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

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

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

3 голосов
/ 10 ноября 2011

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

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

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

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

Три термина связаны, но для меня это разные понятия,Впрочем, люди могут использовать их несколько взаимозаменяемо.

2 голосов
/ 28 октября 2011

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

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

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

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

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

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

1 голос
/ 22 февраля 2018

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

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

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

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

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

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

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

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

1) Это становится отказом в обслуживании из-за продуктивности ... вы должны думать ОЧЕНЬ больше, и на этом пути вы совершаете много ошибок.

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

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

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

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

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

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

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

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

...