Поскольку мобильные приложения и приложения, основанные на данных, все больше доминируют, пользователи требуют доступа в реальном времени ко всему и везде. Системная устойчивость и отзывчивость больше не «хороши»; это важные бизнес-требования. Предприятиям все чаще приходится переходить от статических централизованных архитектур в пользу гибких, распределенных и гибких систем. Но с чего начать и с каким подходом к архитектуре все еще немного размыто, а шумиха вокруг микросервисов постепенно уходит, пока индустрия программного обеспечения исследует различные архитектуры и стили реализации. И есть много способов реализовать архитектуру на основе микросервисов на виртуальной машине Java (JVM) или вокруг нее.
Наиболее перспективными кажутся те, которые основаны на принципах Реактивного Манифеста . Он определяет характеристики, которые приводят к большим системам, которые состоят из более мелких, более гибких, слабосвязанных и масштабируемых. Поскольку они по сути управляются сообщениями и распространяются, эти платформы соответствуют требованиям современных архитектур микросервисов. В то время как Lagom предлагает продуманный подход к тесным ограждениям, который поддерживает только архитектуры микросервисов, Play и Akka позволяют вам воспользоваться преимуществами реагирования для построения системы в стиле микросервисов, но не ограничивают вас этим подходом.
Микросервисы с аккой
Akka — это инструментарий и среда выполнения для создания в JVM высококонкурентных, распределенных и устойчивых приложений, управляемых сообщениями. «Актеры» Akka являются одним из инструментов в наборе инструментов Akka, который позволяет вам писать параллельный код, не думая о низкоуровневых потоках и блокировках. Другие инструменты включают Akka Streams и Akka http. Хотя Akka написан на Scala, есть и Java API. Когда люди говорят о микросервисах, они сосредотачиваются на «микро» части, говоря, что услуга должна быть небольшой. Я хочу подчеркнуть, что при разделении системы на сервисы важно учитывать правильные границы между сервисами, согласовывать их с ограниченным контекстом, возможностями бизнеса и требованиями изоляции. В результате система на основе микросервисов может достичь своих требований к масштабируемости и устойчивости, упрощая развертывание и управление.
Документация Akka содержит подробное описание упрощенного приложения для управления IoT. Это позволяет пользователям запрашивать данные датчика. Он не предоставляет никаких внешних API для упрощения и фокусируется только на дизайне приложения и использует API на основе акторов для устройств, чтобы сообщать свои данные обратно в часть управления. Это схема архитектуры высокого уровня.
Актеры организованы в строгое дерево, где жизненный цикл каждого ребенка привязан к родителю и где родители несут ответственность за решение судьбы детей-неудачников. Все, что вам нужно сделать, это переписать вашу архитектурную схему, которая содержала вложенные блоки в дерево.
Проще говоря, каждый компонент управляет жизненным циклом подкомпонентов. Никакой подкомпонент не может пережить родительский компонент. Именно так работает иерархия актеров. Кроме того, желательно, чтобы компонент обрабатывал сбой своих подкомпонентов. «Содержимое» взаимосвязи компонентов сопоставляется с «дочерними» отношениями субъектов. Если вы посмотрите на микросервисные архитектуры, вы ожидаете, что компоненты верхнего уровня также являются субъектами верхнего уровня. Это действительно возможно, но не рекомендуется. Поскольку нам не нужно соединять отдельные сервисы обратно через внешние протоколы, а инфраструктура Akka также управляет жизненным циклом субъекта, мы можем создать одного субъекта верхнего уровня в системе субъекта и смоделировать основные службы как дочерние элементы этого субъекта. Архитектура актера строится на тех же чертах, на которые должна опираться микросервисная архитектура.
Подробности о том, как реализовать классы IoTSupervisor и DeviceManager, вы найдете в официальном руководстве Akka .
Как актеры общаются
Глядя на актера устройства, чья простая задача — собирать измерения температуры и сообщать о них по запросу. При работе с объектами вы обычно проектируете API как интерфейсы, которые в основном представляют собой набор абстрактных методов, которые должны быть заполнены фактической реализацией. В мире актеров аналогами интерфейсов являются протоколы. Протокол в приложении на основе актера — это сообщение для устройств (Код 1)
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
|
public static final class ReadTemperature { long requestId; public ReadTemperature( long requestId) { this .requestId = requestId; } } public static final class RespondTemperature { long requestId; Optional<Double> value; public RespondTemperature( long requestId, Optional<Double> value) { this .requestId = requestId; this .value = value; } } |
Я пропускаю много информации о заказе сообщений и гарантиях доставки . Проектирование системы с предположением, что сообщения могут быть потеряны в сети, является наиболее безопасным способом построения архитектуры на основе микросервисов. Это может быть сделано, например, путем реализации функции повторной отправки, если сообщение теряется. И это причина, почему сообщение также содержит requestId. Теперь запрашивающий актер будет отвечать за сопоставление запросов с актерами. Первый черновой набросок DeviceActor:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
class Device extends AbstractActor { // ... Optional<Double> lastTemperatureReading = Optional.empty(); @Override public void preStart() { log.info( "Device actor {}-{} started" , groupId, deviceId); } @Override public void postStop() { log.info( "Device actor {}-{} stopped" , groupId, deviceId); } @Override // react to received messages of ReadTemperature public Receive createReceive() { return receiveBuilder() .match(ReadTemperature. class , r -> { getSender().tell( new RespondTemperature(r.requestId, lastTemperatureReading), getSelf()); }).build(); } } |
Текущая температура изначально установлена на Optional.empty () и просто отправляется обратно при запросе. Простой тест для устройства показан в коде 3.
1
2
3
4
5
6
7
8
9
|
@Test public void testReplyWithEmptyReadingIfNoTemperatureIsKnown() { TestKit probe = new TestKit(system); ActorRef deviceActor = system.actorOf(Device.props( "group" , "device" )); deviceActor.tell( new Device.ReadTemperature(42L), probe.getRef()); Device.RespondTemperature response = probe.expectMsgClass(Device.RespondTemperature. class ); assertEquals(42L, response.requestId); assertEquals(Optional.empty(), response.value); } |
(Код 3: Тестирование актера устройства)
Полный пример, если система IoT содержится в документации Akka .
Когда не использовать микросервисы
Микросервисы — правильный выбор, если у вас есть система, которая слишком сложна, чтобы ее можно было использовать как монолит. Как утверждает Мартин Фаулер в своей статье о « МикросервисПремиум ». Суть в том, что даже не стоит рассматривать архитектуру микросервисов, если у вас нет слишком большой и сложной системы, чтобы ее можно было построить как простой монолит. Но также верно и то, что сегодня многоядерные процессоры, облачные вычисления и мобильные устройства являются нормой, что означает, что все новые системы являются распределенными системами с самого начала. И это также приводит к совершенно другому и более сложному миру для работы. Логическим шагом сейчас является переключение мышления с сотрудничества между объектами в одной системе на сотрудничество по индивидуально масштабируемым системам. Системы микросервисов.
Опубликовано на Java Code Geeks с разрешения Маркуса Эйзела, партнера нашей программы JCG . Смотреть оригинальную статью здесь: МИКРОСЕРВИСЫ С АККА
Мнения, высказанные участниками Java Code Geeks, являются их собственными. |