Встраиваемые системы — приложения, состоящие из небольших специализированных компьютеров, встроенных в конкретное устройство, — требуют специфического подхода к микросервисам, пишет на портале The New Stack Боб Реселман, известный разработчик ПО и системный архитектор.

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

Но для встраиваемых систем все обстоит несколько иначе.

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

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

Программирование MOA для встраиваемых систем требует иного подхода к проектированию и реализации.

Микросервисно-ориентированная «архитектура 101»

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

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

Как правило, эти сервисы отправляют и получают данные, используя известный транспортный протокол, такой как TCP, UDP или HTTP. Некий организационный механизм внешнего клиента, например веб-страница или нативный код, работающий на настольных или мобильных устройствах, объединяет различные сервисы в единое представление всего приложения. Однако, как уже говорилось, каждый из сервисов, составляющих MOA, размещается удаленно.

Фронтенд приложения обращается к удаленной службе маршрутизации/контроллера. Эта служба знает местоположение микросервисов, составляющих приложение, и переадресует вызов соответствующему сервису в соответствии с каким-либо идентификатором, который является частью кода вызова. Микросервис обрабатывает вызов и отправляет результат обратно в маршрутизатор/контроллер для дальнейшей обработки — или, если данный вызов завершен, ответ отправляется вызывающему клиенту.

Базовый шаблон для микросервисно-ориентированной архитектуры

Идея разделения приложения на функциональности, размещаемые в удаленных местах, берет свое начало в удаленных вызовах процедур (RPC). MOA опирается на шаблон RPC, добавляя набор обычных требований. В рамках MOA каждый микросервис:

  • поддерживает одну задачу;
  • является дискретным;
  • несет свои собственные данные;
  • является транспортируемым;
  • является эфемерным.

Вот что означает каждое из этих требований:

  • Поддержка одной задачи. Микросервис должен ограничивать свое поведение одной задачей, такой как служба входа в систему, служба заказа, служба покупки, служба обработки транзакций по кредитным картам, служба поддержки профилей клиентов, служба выполнения налоговых расчетов или служба протоколирования.

    Один микросервис может использовать другой микросервис; например, сервис покупки может использовать сервис расчета налогов для определения общей суммы заказа. Однако не следует объединять два сервиса в одну кодовую базу или единую единицу развертывания.
  • Дискретность. Микросервис должен быть дискретным, то есть ограничиваться одной единицей развертывания и быть хорошо ограниченным в сети. Такой единицей развертывания может быть контейнер Linux или артефакт кода, например Java-файл .jar, DLL .NET или двоичный файл Rust. В случае встраиваемой системы единицей развертывания может быть реальная часть оборудования.

    Внутреннее устройство микросервиса должно быть закрытым и недоступным для общественности. В то же время публичный доступ должен обеспечиваться хорошо определенным API.
  • Несет собственные данные. Микросервис несет свои собственные данные и не обменивается ими с другими микросервисами, кроме как через свой API. Как правило, микросервис имеет собственную базу данных или хорошо изолированные таблицы в базе данных. Хотя избыточность данных между микросервисами может иметь место, это условие приемлемо и необходимо для поддержания микросервисом своего собственного рабочего состояния и границ.
  • Транспортабельность. Должна быть возможность переноса микросервиса в любую среду хостинга в любое время. Транспортабельность важна в ситуации, когда микросервис работает на машине, которая вышла из строя, например, лишилась электропитания, и должен быть перенесен на другую функционирующую машину.
  • Эфемерность. Должна быть возможность создавать или уничтожать микросервис по требованию. Это особенно важно в ситуациях, когда микросервис выполняет высокоинтенсивные вычисления и должен существовать только для удовлетворения сиюминутного спроса. Например, микросервис выполняет обработку спецэффектов для определенного видеофайла.

Что особенного в MOA для встраиваемых устройств?

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

Прежде всего, большинство дата-центров используют Linux для управления своими машинами. Linux — это полнофункциональная ОС, занимающая много места как в памяти, так и на диске. Даже если использовать урезанный дистрибутив Linux, например Alpine, в котором есть только основные функции, такая ОС занимает 5 Мб памяти.

Многие встраиваемые чипы, такие как EPS32, поставляются с 520 Кб встроенной оперативной памяти, часть которой отведена под энергонезависимое хранилище. Некоторые чипы могут иметь до 4 Мб оперативной памяти и от 2 Мб до 16 Мб флэш-памяти при использовании специальной конфигурации.

Тем не менее, если встраиваемое устройство имеет ограниченный объем памяти, менее 4 Мб, то Linux на нем работать не будет. Встраиваемые устройства, как правило, используют ту или иную версию операционной системы реального времени (RTOS). FreeRTOS, используемая в чипсете ESP32, требует всего 5-10 Кб для хранения кода, а объем оперативной памяти может достигать 300 Кб. Как видите, системные ресурсы встраиваемых устройств мизерны по сравнению с машинами, работающими в дата-центрах.

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

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

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

Одним словом, процесс развертывания и обновления микросервисов для встраиваемых систем сильно зависит от физического состояния аппаратного обеспечения системы. Но есть и еще одно существенное ограничение: обмен данными.

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

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

Однако обмен данными между встроенными процессорами, которые работают на борту конкретного устройства, например автомобиля, и внешними устройствами, такими как мобильный телефон, требует особого внимания. Большинство встроенных процессоров поставляются вместе с другими микросхемами на небольшой мини-плате. В эти мини-платы встроены функции Bluetooth и Wi-Fi. Встроенные чипсеты могут обмениваться данными с внешними устройствами, используя эти возможности. Связь с использованием двоичных форматов остается жизнеспособной, если встроенный чипсет обменивается данными с известным внешним устройством в соответствии с известным форматом.

Однако в некоторых случаях, например, при обмене данными по протоколу HTTP с удаленным веб-API, предписывается использовать более громоздкие текстовые форматы данных. С учетом ограничений по объему памяти и хранилища каждого встроенного чипсета обмен текстовыми данными может стать проблемой.

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

Выделенный прокси позволяет встроенным чипсетам эффективно коммуницировать с внешними устройствами

Маршрутизация сервисов — еще один момент. Так же как MOA, работающей в дата-центре, нужен API-шлюз для маршрутизации трафика к назначенным микросервисам, MOA, работающей во встраиваемой среде, тоже нужен такой механизм маршрутизатора/контроллера. В автомобиле им является электронный блок управления (ECU), работающий в локальной сети контроллеров (CAN).

Шина CAN в автомобиле использует ECU для координации обмена данными между микросервисами, работающими на встраиваемых устройствах

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

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

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

Системы управления полетами (FCS) и системы управления зданиями (BMS) также имеют механизм для поддержания и сообщения об общем состоянии. В FCS механизм управления также иногда называется компьютером управления полетом. В BMS этот компонент называется контроллером автоматизации здания или контроллером системы автоматизации здания. Этот контроллер сообщает о состоянии всех подсистем в здании, таких как системы отопления, вентиляции и кондиционирования воздуха, освещения, безопасности, лифты, электрические системы и оборудование пожарной безопасности.

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

Складывая все вместе

Взрывной рост Интернета вещей и «умных» устройств — от «умных» домов до автономных автомобилей и фабрик, управляемых роботами, и всего остального — предоставляет разработчикам ПО, хорошо знакомым с МОА, все больше возможностей для работы со встраиваемыми системами.

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