Что является основой функционирования асинхронного обмена по шине
Шаблоны асинхронного обмена сообщениями и высокий уровень доступности
Асинхронный обмен сообщениями может осуществляться различными способами. Служебная шина Azure поддерживает асинхронность за счет механизма сохранения и пересылки. Этот механизм оперирует очередями, разделами и подписками. В обычном (синхронном) режиме сообщения отправляются в очереди и разделы, а поступают из очередей и подписок. Для создаваемых приложений важно, чтобы эти сущности всегда были доступны. На случай, если работоспособность сущности изменится по какой-либо причине, нужно иметь возможность предоставить доступ к сущности, которая будет работать в ограниченном режиме, но все же удовлетворять большинство потребностей.
Для реализации различных сценариев связи в приложениях обычно используются шаблоны асинхронного обмена сообщениями. Вы можете создавать приложения, в которых клиенты смогут отправлять сообщения в службы, даже если они не запущены. В приложениях, для которых характерны скачки нагрузки, сбалансировать нагрузку можно с помощью очередей, которые используются для буферизации передаваемых данных. Наконец, для распределения сообщений между несколькими компьютерами вы можете воспользоваться простым, но эффективным балансировщиком нагрузки.
Чтобы обеспечить доступность всех этих сущностей, следует предусмотреть ситуации, в которых эти сущности могут стать недоступными для устойчивой системы обмена сообщениями. Существуют такие виды ограниченной доступности сущностей для приложений:
Для каждого из указанных типов ошибок существуют режимы, которые обеспечат дальнейшую работу приложения с определенным уровнем ограничений. Например, если система может отправлять сообщения, но не может их получать, вы по-прежнему будете получать заказы от клиентов, но не сможете их обрабатывать. В этой статье рассматриваются возможные проблемы и способы их устранения. В служебной шине реализовано несколько способов устранения рисков, которые мы рекомендуем использовать. В этой статье также рассматриваются правила использования этих способов.
Надежность служебной шины
Существует несколько способов решения проблем с сообщениями и сущностями, а также рекомендации по надлежащему использованию этих способов. Для понимания этих рекомендаций необходимо сначала определить участки служебной шины, которые потенциально подвержены сбоям. Благодаря архитектуре систем Azure все эти проблемы обычно имеют краткосрочный характер. В общих чертах можно выделить следующие причины недоступности.
Термин хранилище может означать как хранилище Azure, так и SQL Azure.
В служебной шине предусмотрен ряд способов устранения рисков, связанных с этими проблемами. В следующих разделах рассматривается каждая из этих проблем и способы их устранения.
Регулирование
Регулирование в служебной шине позволяет управлять скоростью обмена сообщениями «кооперативным» способом. Каждый отдельный узел служебной шины хранит множество сущностей. Для каждой из этих сущностей требуются ресурсы центрального процессора, памяти, хранилища и др. Если использование какого-либо из ресурсов превысит установленные ограничения, служебная шина может отклонить запрос. Вызывающий объект получит исключение занятости сервера и повторит попытку через 10 секунд.
Для устранения этой проблемы код должен прочитать ошибку и не допустить повторной отправки сообщения по крайней мере в течение 10 секунд. Так как эта ошибка может возникать в различных частях клиентского приложения, логику повторной отправки рекомендуется реализовать отдельно в каждой части. Такой код предотвращает выполнение регулирования благодаря секционированию очереди или раздела.
Проблема с зависимостью в Azure
В любом из компонентов Azure время от времени могут возникать проблемы, связанные с работой службы. Например, обновление системы, которая используется служебной шиной, может привести к временному снижению производительности этой системы. Чтобы избежать таких проблем, служебная шина регулярно проверяет и реализует способы устранения рисков. Однако при применении этих способов возможны побочные эффекты. Например, для устранения временных проблем с хранилищем в служебной шине реализована система, которая обеспечивает согласованное выполнение операций отправки сообщений. При устранении рисков отправленное сообщение может появиться в соответствующей очереди или подписке через 15 минут, после чего оно станет доступным для получения. Вообще говоря, эта проблема не затронет большинство сущностей. Тем не менее, в зависимости от количества сущностей в служебной шине Azure, такое устранение рисков иногда необходимо для некоторых клиентов служебной шины.
Сбой служебной шины в единой подсистеме
В любом приложении возможны обстоятельства, которые могут привести к несогласованности внутреннего компонента служебной шины. Когда служебная шина обнаруживает это, она собирает из приложения данные, которые помогут диагностировать проблему. После сбора данных приложение перезапускается, чтобы вернуться в согласованное состояние. Этот происходит довольно быстро, но сущность может стать недоступной. Обычно простой длится недолго, но иногда может достигать нескольких минут.
В таких случаях клиентское приложение инициирует исключение времени ожидания или исключение обмена сообщениями. Служебная шина содержит средство для устранения этой проблемы, которое реализовано в виде автоматизированной логики повтора для клиента. Если период повторных попыток исчерпан, а сообщение все еще не доставлено, можно использовать другие возможности, описанные в статье Рекомендации по изолированию приложений от простоев и аварий служебной шины.
Дальнейшие действия
Вы ознакомились с основами асинхронного обмена сообщениями в служебной шине. Дополнительные сведения см. в статье Рекомендации по изолированию приложений от простоев и аварий служебной шины.
Шины микропроцессорной системы и циклы обмена
Циклы обмена информацией делятся на два основных типа:
В некоторых микропроцессорных системах существует также цикл «чтение-модификация- запись » или же «ввод-пауза- вывод «. В этих циклах процессор сначала читает информацию из памяти или устройства ввода/вывода, затем как-то преобразует ее и снова записывает по тому же адресу. Например, процессор может прочитать код из ячейки памяти, увеличить его на единицу и снова записать в эту же ячейку памяти. Наличие или отсутствие данного типа цикла связано с особенностями используемого процессора.
Особое место занимают циклы прямого доступа к памяти (если режим ПДП в системе предусмотрен) и циклы запроса и предоставления прерывания (если прерывания в системе есть). Когда в дальнейшем речь пойдет о таких циклах, это будет специально оговорено.
Во время каждого цикла устройства, участвующие в обмене информацией, передают друг другу информационные и управляющие сигналы в строго установленном порядке или, как еще говорят, в соответствии с принятым протоколом обмена информацией.
Длительность цикла обмена может быть постоянной или переменной, но она всегда включает в себя несколько периодов сигнала тактовой частоты системы. То есть даже в идеальном случае частота чтения информации процессором и частота записи информации оказываются в несколько раз меньше тактовой частоты системы.
Чтение кодов команд из памяти системы также производится с помощью циклов чтения. Поэтому в случае одношинной архитектуры на системной магистрали чередуются циклы чтения команд и циклы пересылки (чтения и записи) данных, но протоколы обмена остаются неизменными независимо от того, что передается — данные или команды. В случае двухшинной архитектуры циклы чтения команд и записи или чтения данных разделяются по разным шинам и могут выполняться одновременно.
2.1. Шины микропроцессорной системы
Прежде чем переходить к особенностям циклов обмена, остановимся подробнее на составе и назначении различных шин микропроцессорной системы.
Шина данных — это основная шина, ради которой и создается вся система. Количество ее разрядов (линий связи) определяет скорость и эффективность информационного обмена, а также максимально возможное количество команд.
Шина данных всегда двунаправленная, так как предполагает передачу информации в обоих направлениях. Наиболее часто встречающийся тип выходного каскада для линий этой шины — выход с тремя состояниями.
Шина управления — это вспомогательная шина, управляющие сигналы на которой определяют тип текущего цикла и фиксируют моменты времени, соответствующие разным частям или стадиям цикла. Кроме того, управляющие сигналы обеспечивают согласование работы процессора (или другого хозяина магистрали, задатчика, master) с работой памяти или устройства ввода/вывода (устройства-исполнителя, slave ). Управляющие сигналы также обслуживают запрос и предоставление прерываний, запрос и предоставление прямого доступа.
Сигналы шины управления могут передаваться как в положительной логике (реже), так и в отрицательной логике (чаще). Линии шины управления могут быть как однонаправленными, так и двунаправленными. Типы выходных каскадов могут быть самыми разными: с двумя состояниями (для однонаправленных линий), с тремя состояниями (для двунаправленных линий ), с открытым коллектором (для двунаправленных и мультиплексированных линий).
По используемому типу обмена магистрали микропроцессорных систем также делятся на синхронные и асинхронные.
Шины микропроцессорной системы и циклы обмена
Циклы обмена информацией делятся на два основных типа:
В некоторых микропроцессорных системах существует также цикл «чтение-модификация- запись » или же «ввод-пауза- вывод «. В этих циклах процессор сначала читает информацию из памяти или устройства ввода/вывода, затем как-то преобразует ее и снова записывает по тому же адресу. Например, процессор может прочитать код из ячейки памяти, увеличить его на единицу и снова записать в эту же ячейку памяти. Наличие или отсутствие данного типа цикла связано с особенностями используемого процессора.
Особое место занимают циклы прямого доступа к памяти (если режим ПДП в системе предусмотрен) и циклы запроса и предоставления прерывания (если прерывания в системе есть). Когда в дальнейшем речь пойдет о таких циклах, это будет специально оговорено.
Во время каждого цикла устройства, участвующие в обмене информацией, передают друг другу информационные и управляющие сигналы в строго установленном порядке или, как еще говорят, в соответствии с принятым протоколом обмена информацией.
Длительность цикла обмена может быть постоянной или переменной, но она всегда включает в себя несколько периодов сигнала тактовой частоты системы. То есть даже в идеальном случае частота чтения информации процессором и частота записи информации оказываются в несколько раз меньше тактовой частоты системы.
Чтение кодов команд из памяти системы также производится с помощью циклов чтения. Поэтому в случае одношинной архитектуры на системной магистрали чередуются циклы чтения команд и циклы пересылки (чтения и записи) данных, но протоколы обмена остаются неизменными независимо от того, что передается — данные или команды. В случае двухшинной архитектуры циклы чтения команд и записи или чтения данных разделяются по разным шинам и могут выполняться одновременно.
2.1. Шины микропроцессорной системы
Прежде чем переходить к особенностям циклов обмена, остановимся подробнее на составе и назначении различных шин микропроцессорной системы.
Шина данных — это основная шина, ради которой и создается вся система. Количество ее разрядов (линий связи) определяет скорость и эффективность информационного обмена, а также максимально возможное количество команд.
Шина данных всегда двунаправленная, так как предполагает передачу информации в обоих направлениях. Наиболее часто встречающийся тип выходного каскада для линий этой шины — выход с тремя состояниями.
Шина управления — это вспомогательная шина, управляющие сигналы на которой определяют тип текущего цикла и фиксируют моменты времени, соответствующие разным частям или стадиям цикла. Кроме того, управляющие сигналы обеспечивают согласование работы процессора (или другого хозяина магистрали, задатчика, master) с работой памяти или устройства ввода/вывода (устройства-исполнителя, slave ). Управляющие сигналы также обслуживают запрос и предоставление прерываний, запрос и предоставление прямого доступа.
Сигналы шины управления могут передаваться как в положительной логике (реже), так и в отрицательной логике (чаще). Линии шины управления могут быть как однонаправленными, так и двунаправленными. Типы выходных каскадов могут быть самыми разными: с двумя состояниями (для однонаправленных линий), с тремя состояниями (для двунаправленных линий ), с открытым коллектором (для двунаправленных и мультиплексированных линий).
По используемому типу обмена магистрали микропроцессорных систем также делятся на синхронные и асинхронные.
Шины микропроцессорной системы и циклы обмена
Циклы обмена информацией делятся на два основных типа:
В некоторых микропроцессорных системах существует также цикл «чтение-модификация- запись » или же «ввод-пауза- вывод «. В этих циклах процессор сначала читает информацию из памяти или устройства ввода/вывода, затем как-то преобразует ее и снова записывает по тому же адресу. Например, процессор может прочитать код из ячейки памяти, увеличить его на единицу и снова записать в эту же ячейку памяти. Наличие или отсутствие данного типа цикла связано с особенностями используемого процессора.
Особое место занимают циклы прямого доступа к памяти (если режим ПДП в системе предусмотрен) и циклы запроса и предоставления прерывания (если прерывания в системе есть). Когда в дальнейшем речь пойдет о таких циклах, это будет специально оговорено.
Во время каждого цикла устройства, участвующие в обмене информацией, передают друг другу информационные и управляющие сигналы в строго установленном порядке или, как еще говорят, в соответствии с принятым протоколом обмена информацией.
Длительность цикла обмена может быть постоянной или переменной, но она всегда включает в себя несколько периодов сигнала тактовой частоты системы. То есть даже в идеальном случае частота чтения информации процессором и частота записи информации оказываются в несколько раз меньше тактовой частоты системы.
Чтение кодов команд из памяти системы также производится с помощью циклов чтения. Поэтому в случае одношинной архитектуры на системной магистрали чередуются циклы чтения команд и циклы пересылки (чтения и записи) данных, но протоколы обмена остаются неизменными независимо от того, что передается — данные или команды. В случае двухшинной архитектуры циклы чтения команд и записи или чтения данных разделяются по разным шинам и могут выполняться одновременно.
2.1. Шины микропроцессорной системы
Прежде чем переходить к особенностям циклов обмена, остановимся подробнее на составе и назначении различных шин микропроцессорной системы.
Шина данных — это основная шина, ради которой и создается вся система. Количество ее разрядов (линий связи) определяет скорость и эффективность информационного обмена, а также максимально возможное количество команд.
Шина данных всегда двунаправленная, так как предполагает передачу информации в обоих направлениях. Наиболее часто встречающийся тип выходного каскада для линий этой шины — выход с тремя состояниями.
Шина управления — это вспомогательная шина, управляющие сигналы на которой определяют тип текущего цикла и фиксируют моменты времени, соответствующие разным частям или стадиям цикла. Кроме того, управляющие сигналы обеспечивают согласование работы процессора (или другого хозяина магистрали, задатчика, master) с работой памяти или устройства ввода/вывода (устройства-исполнителя, slave ). Управляющие сигналы также обслуживают запрос и предоставление прерываний, запрос и предоставление прямого доступа.
Сигналы шины управления могут передаваться как в положительной логике (реже), так и в отрицательной логике (чаще). Линии шины управления могут быть как однонаправленными, так и двунаправленными. Типы выходных каскадов могут быть самыми разными: с двумя состояниями (для однонаправленных линий), с тремя состояниями (для двунаправленных линий ), с открытым коллектором (для двунаправленных и мультиплексированных линий).
По используемому типу обмена магистрали микропроцессорных систем также делятся на синхронные и асинхронные.
Использование асинхронного обмена сообщениями для улучшения доступности
Привет, Хаброжители! Мы недавно сдали в типографию книгу Криса Ричардсона, цель которой — научить успешно разрабатывать приложения с использованием микросервисной архитектуры. В книге обсуждаются не только преимущества, но и недостатки микросервисов. Вы узнаете, в каких ситуациях имеет смысл применять их, а когда лучше подумать о монолитном подходе.
Основное внимание в книге уделяется архитектуре и разработке. Она рассчитана на любого, в чьи обязанности входят написание и доставка программного обеспечения, в том числе на разработчиков, архитекторов, технических директоров и начальников отделов по разработке.
Ниже представлен отрывок из книги «Использование асинхронного обмена сообщениями»
Использование асинхронного обмена сообщениями для улучшения доступности
Как вы видели, разнообразные механизмы IPC подталкивают вас к различным компромиссам. Один из них связан с тем, как механизм IPC влияет на доступность. В этом разделе вы узнаете, что синхронное взаимодействие с другими сервисами в рамках обработки запросов снижает степень доступности приложения. В связи с этим при проектировании своих сервисов вы должны по возможности использовать асинхронный обмен сообщениями.
Сначала посмотрим, какие проблемы создает синхронное взаимодействие и как это сказывается на доступности.
3.4.1. Синхронное взаимодействие снижает степень доступности
REST — это чрезвычайно популярный механизм IPC. У вас может возникнуть соблазн использовать его для межсервисного взаимодействия. Но проблема REST заключается в том, что это синхронный протокол: HTTP-клиенту приходится ждать, пока сервис не вернет ответ. Каждый раз, когда сервисы общаются между собой по синхронному протоколу, это снижает доступность приложения.
Чтобы понять, почему так происходит, рассмотрим сценарий, представленный на рис. 3.15. У сервиса Order есть интерфейс REST API для создания заказов. Для проверки заказа он обращается к сервисам Consumer и Restaurant, которые тоже имеют REST API.
Создание заказа состоит из такой последовательности шагов.
Эта проблема не уникальна для взаимодействия на основе REST. Доступность снижается всякий раз, когда для ответа клиенту сервис должен получить ответы от других сервисов. Здесь не поможет даже переход к стилю взаимодействия «запрос/ответ» поверх асинхронных сообщений. Например, если сервис Order пошлет сервису Consumer сообщение через брокер и примется ждать ответа, его доступность ухудшится.
Если вы хотите максимально повысить уровень доступности, минимизируйте объем синхронного взаимодействия. Посмотрим, как это сделать.
3.4.2. Избавление от синхронного взаимодействия
Существует несколько способов уменьшения объема синхронного взаимодействия с другими сервисами при обработке синхронных запросов. Во-первых, чтобы полностью избежать этой проблемы, все сервисы можно снабдить исключительно асинхронными API. Но это не всегда возможно. Например, публичные API обычно придерживаются стандарта REST. Поэтому некоторые сервисы обязаны иметь синхронные API.
К счастью, чтобы обрабатывать синхронные запросы, вовсе не обязательно выполнять их самому. Поговорим о таких вариантах.
Использование асинхронных стилей взаимодействия
В идеале все взаимодействие должно происходить в асинхронном стиле, описанном ранее в этой главе. Представьте, к примеру, что клиент приложения FTGO применяет для создания заказов асинхронный стиль взаимодействия вида «запрос/асинхронный ответ». Чтобы создать заказ, он отправляет сообщение с запросом сервису Order. Затем этот сервис асинхронно обменивается сообщениями с другими сервисами и в итоге возвращает клиенту ответ (рис. 3.16).
Клиент и сервис общаются асинхронно, отправляя сообщения через каналы. Ни один из участников этого взаимодействия не блокируется в ожидании ответа.
Такая архитектура была бы чрезвычайно устойчивой, потому что брокер буферизирует сообщения до тех пор, пока их потребление не станет возможным. Но проблема в том, что у сервисов часто есть внешний API, который использует синхронный протокол вроде REST и, как следствие, обязан немедленно отвечать на запросы.
Если у сервиса есть синхронный API, доступность можно улучшить за счет репликации данных. Посмотрим, как это работает.
Одним из способов минимизации синхронного взаимодействия во время обработки запросов является репликация данных. Сервис хранит копию (реплику) данных, которые ему нужны для обработки запросов. Чтобы поддерживать реплику в актуальном состоянии, он подписывается на события, публикуемые сервисами, которым эти данные принадлежат. Например, сервис Order может хранить копию данных, принадлежащих сервисам Consumer и Restaurant. Это позволит ему обрабатывать запросы на создание заказов, не обращаясь к этим сервисам. Такая архитектура показана на рис. 3.17.
Сервисы Consumer и Restaurant публикуют события всякий раз, когда их данные меняются. Сервис Order подписывается на эти события и обновляет свою реплику.
В некоторых случаях репликация данных — это хорошее решение. Например, в главе 5 описывается, как сервис Order реплицирует данные сервиса Restaurant, чтобы иметь возможность проверять элементы меню. Один из недостатков этого подхода связан с тем, что иногда он требует копирования больших объемов данных, что неэффективно. Например, если у нас много заказчиков, хранить реплику данных, принадлежащих сервису Consumer, может оказаться непрактично. Еще один недостаток репликации кроется в том, что она не решает проблему обновления данных, принадлежащих другим сервисам.
Чтобы решить эту проблему, сервис может отсрочить взаимодействие с другими сервисами до тех пор, пока он не ответит своему клиенту. Речь об этом пойдет далее.
Завершение обработки после возвращения ответа
Еще один способ устранения синхронного взаимодействия во время обработки запросов состоит в том, чтобы выполнять эту обработку в виде следующих этапов.
Представьте, что сервис Order действует таким образом. Он создает заказ с состоянием PENDING и затем проверяет его, обмениваясь асинхронными сообщениями с другими сервисами. На рис. 3.18 показано, что происходит при вызове операции createOrder(). Цепочка событий выглядит так.
Сервис Order может получить сообщения ConsumerValidated и OrderDetailsValidated в любом порядке. Чтобы знать, какое из них он получил первым, он меняет состояние заказа. Если первым пришло сообщение ConsumerValidated, состояние заказа меняется на CONSUMER_VALIDATED, а если OrderDetailsValidated — на ORDER_DETAILS_VALIDATED. Получив второе сообщение, сервис Order присваивает заказу состояние VALIDATED.
После проверки заказа сервис Order выполняет оставшиеся шаги по его созданию, о которых мы поговорим в следующей главе. Замечательной стороной этого подхода является то, что сервис Order сможет создать заказ и ответить клиенту, даже если сервис Consumer окажется недоступным. Рано или поздно сервис Consumer восстановится и обработает все отложенные сообщения, что позволит завершить проверку заказов.
Недостаток возвращения ответа до полной обработки запроса связан с тем, что это делает клиент более сложным. Например, когда сервис Order возвращает ответ, он дает минимальные гарантии по поводу состояния только что созданного заказа. Он отвечает немедленно, еще до проверки заказа и авторизации банковской карты клиента. Таким образом, чтобы узнать о том, успешно ли создан заказ, клиент должен периодически запрашивать информацию или же сервис Order должен послать ему уведомительное сообщение. Несмотря на всю сложность этого подхода, во многих случаях стоит предпочесть его, особенно из-за того, что он учитывает проблемы с управлением распределенными транзакциями, которые мы обсудим в главе 4. В главах 4 и 5 я продемонстрирую эту методику на примере сервиса Order.
Резюме
Для Хаброжителей скидка 30% на предзаказ книги по купону — Микросервисы