что такое сервис в программировании
Сервисы, микросервисы и пакетно-ориентированное программирование
Многие программисты слышали о том, что иногда код следует выделять в отдельные библиотеки для дальнейшего повторного использования. Однако, вопрос, какой же все-таки код следует выделять в отдельную сущность, ставит многих разработчиков в тупик. При прочтении статей/разговоре на данную тему обычно вспоминается проблема преждевременного обобщения.
Опытные программисты обычно имеют свои правила, соблюдая которые, понимают, следует ли выделять код в повторно используемый. Например, если такой(или сильно похожий) код используется в трех местах или более. Тем не менее, все, с кем мне довелось говорить на этот счет, соглашаются с тем, что такой повторно используемый код должен существовать, его создание является благом, и на это стоит тратить свое время.
Хочу поднять тему повторного использования кода в контексте создания сервис-ориентированной и микросервисной архитектуры.
Что есть повторно используемый код
Повторно используемый код — это код, выделенный в отдельную сущность, называемую в разных языках по разному — библиотека, пакет, зависимость и т.д. Обычно такой код хранится в отдельном репозитории, и имеется документация по подключению и использованию этого кода(README.md). Дополнительно, код может быть покрыт тестами, может иметься инструкция по внесению изменений(CONTRIBUTING.md) и может быть настроен CI. Различные бейджи, прикрепленные к описанию, только улучшают визуальное представление зрелости данной сущности, а количество поставленных звезд скажет о популярности данного решения. За примерами далеко ходить не надо — достаточно открыть страницу github любого из популярных фреймворков на любимом вами языке, например vue.js. В общем, способов качественного оформления библиотек вагон и маленькая тележка.
Сервисы и микросервисы
В данной статье под сервисом понимается законченная сущность, которая выполняет определенный набор определенных задач в своем домене ответственности и предоставляет интерфейс для взаимодействия. Сервис или микросервис в данной статье с архитектурной точки зрения могут быть идентичными понятиями, вопрос лишь в масштабе. Сервис может состоять из набора микросервисов, реализующих свой участок бизнес-логики, либо быть одним гордым микросервисом.
Сервис-ориентированная архитектура предполагает, что каждый сервис минимально связан с другими. Тем не менее, межсервисное взаимодействие не исключено, а только предполагается, что оно должно быть сведено к минимуму. Для приема запросов в сервисе обычно реализуется какое-либо стандартизированное API. Это может быть что угодно — REST, SOAP, JSONRPC или новомодный GraphQL.
Условно, сервисы можно разделить на инфраструктурные и продуктовые. Продуктовые сервисы — это те, которые реализуют логику какого-либо клиентского продукта. Например, работают с заявками на его подключение, или организуют сопровождение этого продукта на всем жизненном цикле работы с ним клиента. Инфраструктурные сервисы — это больше про базовый функционал компании(или проекта), например сервис, содержащий клиентскую информацию, или сервис, хранящий информацию о тех или иных заказах. Также к инфраструктурным можно отнести сервисы, реализующие вспомогательный функционал, например сервис информирования клиентов (отправка push-сообщений или СМСок) или сервис взаимодействия с dadata.
Чуточку пофантазируем
Допустим, существует гипотетический интернет-магазин, построенный по сервис-ориентированной архитектуре. Разработчики этого чуда инженерной мысли смогли договориться между собой и пришли к выводу, что в качестве API все их сервисы будут работать, например, по jsonrpc-протоколу. Однако, поскольку интернет-магазин большой, он не стоит на месте и активно развивается, то групп разработки там несколько, пусть будет больше двух — две проектные, одна по сопровождению уже написанного. Также, для пущего эффекта, все команды пишут на одном стеке.
Архитектура гипотетического интернет-магазина:
В интернет торчит только сервис API, предоставляющий доступ для всех фронтальных систем — веб-интерфейса интернет-магазина, а также мобильных приложений.
Сервис клиентской информации хранит информацию о клиентах, умеет их заводить, авторизовывать, выдавать о них необходимую информацию.
Сервис информации о товарах хранит информацию о товарах, об их остатках и доступности для заказа, также предоставляет методы для удобного получения необходимой информации.
Сервис заказов оперирует заказами. Тут находится логика формирования заказа, его подтверждения, выбора типа оплаты и адреса доставки и т.д.
Сервис информирования клиентов умеет отправлять PUSH/SMS/email-сообщения. Тип коммуникации, допустим, зависит от настроек конкретного клиента, также клиент может настроить желаемое время получения уведомлений.
Данные сервисы условно являются инфраструктурными, поскольку без них не может функционировать интернет-магазин как таковой.
Сервисы акций и предложений и рассылки дайджеста предполагается разработать в ближайшее время проектным командам. Эти сервисы условно являются продуктовыми.
Очевидно, любой новый продуктовый сервис в большинстве случаев не сможет существовать без взаимодействия с инфраструктурными сервисами — ему скорее всего придется получать информацию по клиентам или понадобится необходимость отправлять уведомления.
В описанном выше примере намеренно сокрыты детали реализации каждого из сервисов. Так, например, сервис информирования клиентов, вероятно, имеет механизм отложенного выполнения кода, типа очереди выполнения, а сервис информации о товарах может иметь собственную админку для удобного управления товарами, а api для фронтальных систем, вероятно, имеет несколько реплик. Более того, описанная архитектура может быть не оптимальной, она просто взята из головы.
В контексте предложенной архитектуры сразу становится ясно, что для быстрой продуктовой разработки крайне необходимы готовые библиотеки. Так, важно иметь готовую реализацию jsonrpc-сервера, а также клиента к нему, поскольку это основной протокол организации межсервисного взаимодействия. Также в данном примере во весь рост встает вопрос документирования API. Очевидно, для формирования документации у команд также должен быть готовый инструмент. Если предположить, что еще есть готовый инструмент и для генерирования smd-схем для jsonrpc-серверов, то скорость разработки новых сервисов может еще больше вырасти. В итоге, внутри компании, в идеале, должен быть набор готовых библиотек, которыми пользуются все команды для выполнения типовых задач. Эти библиотеки могут быть как собственные, так и open-source’ные, главное, чтобы хорошо выполняли свои задачи. Очевидно, что команда, которая находится в общем стеке и пишет сервисы используя готовые библиотеки, будет более эффективная, нежели команда, которая постоянно велосипедит. Наличие единого фреймворка и единой базы библиотек, которые используются во всех проектных командах, я называю единой экосистемой.
А как обстоят дела в крупных компаниях?
В больших компаниях инфраструктурных сервисов куда больше, равно как и используемых протоколов взаимодействия. Количество готовых библиотек может идти на десятки или даже сотни. Выделение в повторно используемого кода здесь еще более актуально.
Так уж вышло, что у меня есть опыт работы в компании, в которой трудятся около 200 разработчиков, пишущих на различных языках — java, c#, php, python, go, js и др. Удивительно, но общую экосистему, в контексте единого стека, имеют и используют далеко не все команды разработчиков. Казалось бы, очевидная вещь — готовить повторно используемый код, оформлять его должным образом и использовать — далеко не очевидная. Конечно, команды разработчиков решают свои задачи. Кто-то использует шаблон сервиса — набор кода, составляющее ядро их каждого нового сервиса, из которого выкидывается все ненужное и дописывается нужное.
Другие команды разработчиков используют собственные велосипеды, копипастят их из проекта в проект и не заботятся о их документировании и тестировании. В общем, ощущается большая разобщенность в используемых инструментах и подходах внутри одного стека в одной компании. При этом, территориально расположенных в одном городе.
Преимущества единой экосистемы
Формирование единой экосистемы позволяет решить множество сложностей, и имеет огромный потенциал повышения производительности для большой компании. Фактически, эта практика взята из Open Source сообщества — выживают и наиболее популярны лучшие решения в своей области. Сейчас достаточно открыть любой менеджер зависимостей и только удивиться обилию предлагаемых решений. А ведь именно такой подход можно реализовать и внутри компании. Преимущества же такого подхода при реализации нового сервиса следующие:
Ложка дёгтя
Понятно, что для достижения такого подхода следует соблюдать некоторые практики, а именно вести разработку библиотек, используя семантическое версионирование, заботиться о документации и тестах, иметь настроенный ci. Это, своего рода, показатель зрелости не только команды разработки, но и разработчиков в компании в целом.
— Коллега: ты превращаешься в кассира в пятерочке
— я: всмысле?)
— Коллега: скоро будешь спрашивать «пакет надо?»
— я: раскрой пожалуйста мысль. я не понимаю
— Коллега: ну уже в который раз у тебя есть готовый пакет для решения моей задачи
Сервис-ориентированная архитектура (SOA)
Сервис-ориентированная архитектура (service-oriented architecture, SOA) придумана в конце 1980-х. Она берёт своё начало в идеях, изложенных в CORBA, DCOM, DCE и других документах. О SOA написано много, есть несколько её реализаций. Но, по сути, SOA можно свести к нескольким идеям, причём архитектура не диктует способы их реализации:
SOA — это набор архитектурных принципов, не зависящих от технологий и продуктов, совсем как полиморфизм или инкапсуляция.
В этой статье я рассмотрю следующие паттерны, относящиеся к SOA:
Общая архитектура брокера объектных запросов (CORBA)
В 1980-х началось активное использование корпоративных сетей и клиент-серверной архитектуры. Возникла потребность в стандартном способе взаимодействия приложений, которые созданы с использованием разных технологий, исполняются на разных компьютерах и под разными ОС. Для этого была разработана CORBA. Это один из стандартов распределённых вычислений, зародившийся в 1980-х и расцветший к 1991 году.
Стандарт CORBA был реализован несколькими вендорами. Он обеспечивает:
Сегодня CORBA всё ещё используется для разнородных вычислений. Например, он до сих пор является частью Java EE, хотя начиная с Java 9 будет поставляться в виде отдельного модуля.
Хочу отметить, что не считаю CORBA паттерном SOA (хотя отношу и CORBA, и SOA-паттерны к сфере распределённых вычислений). Я рассказываю о нём здесь, поскольку считаю недостатки CORBA одной из причин возникновения SOA.
Принцип работы
Сначала нам нужно получить брокер объектных запросов (Object Request Broker, ORB), который соответствует спецификации CORBA. Он предоставляется вендором и использует языковые преобразователи (language mappers) для генерирования «заглушек» (stub) и «скелетов» (skeleton) на языках клиентского кода. С помощью этого ORB и определений интерфейсов, использующих IDL (аналог WSDL), можно на основе реальных классов генерировать в клиенте удалённо вызываемые классы-заглушки (stub classes). А на сервере можно генерировать классы-скелеты (skeleton classes), обрабатывающие входящие запросы и вызывающие реальные целевые объекты.
Вызывающая программа (caller) вызывает локальную процедуру, реализованную заглушкой.
Достоинства
Недостатки
Веб-сервисы
Хотя сегодня можно найти применение для CORBA, но мы знаем, что нужно было уменьшить количество удалённых обращений, чтобы повысить производительность системы. Также требовался надёжный канал связи и более простая спецификация обмена сообщениями.
И для решения этих задач в конце 1990-х начали появляться веб-сервисы.
[Веб-]сервисы можно публиковать, находить и использовать стандартным образом вне зависимости от технологий.
— Microsoft 2004, Understanding Service-Oriented Architecture
Благодаря микросервисам мы перешли в парадигме SOA от удалённого вызова методов объекта (CORBA) к передаче сообщений между сервисами.
Но нужно понимать, что в рамках SOA веб-сервисы — не просто API общего назначения, всего лишь предоставляющие CRUD-доступ к базе данных через HTTP. В каких-то случаях эта реализация может быть полезной, но ради целостности ваших данных необходимо, чтобы пользователи понимали лежащую в основе реализации модель и соблюдали бизнес-правила. SOA подразумевает, что веб-сервисы являются ограниченными контекстами бизнес-субдоменов (business sub-domain) и отделяет реализацию от решаемых веб-сервисами задач.
С точки зрения технологий SOA не просто сервисная архитектура, а набор политик, методик и фреймворков, благодаря которым мы предоставляем и получаем нужные сервисы.
— Microsoft 2004, Understanding Service-Oriented Architecture
Достоинства
Недостатки
Очередь сообщений
У нас есть несколько приложений, которые асинхронно общаются друг с другом с помощью платформо-независимых сообщений. Очередь сообщений улучшает масштабируемость и усиливает изолированность приложений. Им не нужно знать, где находятся другие приложения, сколько их и даже что они собой представляют. Однако все эти приложения должны использовать один язык обмена сообщениями, т. е. заранее определённый текстовый формат представления данных.
Очередь сообщений использует в качестве компонента инфраструктуры программный брокер сообщений (RabbitMQ, Beanstalkd, Kafka и т. д.). Для реализации связи между приложениями можно по-разному настроить очередь:
Запрос/Ответ
Все эти паттерны можно отнести к либо к pull- (polling), либо к push-подходу:
Достоинства
Недостатки
Сервисная шина предприятия (ESB)
Сервисная шина предприятия использовала веб-сервисы уже в 1990-х, когда они только развивались (быть может, некоторые реализации сначала использовали CORBA?).
ESB возникла во времена, когда в компаниях были отдельные приложения. Например, одно для работы с финансами, другое для учёта персонала, третье для управления складом, и т. д., и их нужно было как-то связывать друг с другом, как-то интегрировать. Но все эти приложения создавались без учёта интеграции, не было стандартного языка для взаимодействия приложений (как и сегодня). Поэтому разработчики приложений предусматривали конечные точки для отправки и приёма данных в определённом формате. Компании-клиенты потом интегрировали приложения, налаживая между ними каналы связи и преобразуя сообщения с одного языка приложения в другой.
Очередь сообщений может упростить взаимодействие приложений, но она не способна решить проблему разных форматов языков. Впрочем, была сделана попытка превратить очередь сообщений из простого канала связи в посредника, доставляющего сообщения и преобразующего их в нужные форматы/языки. ESB стал следующей ступенью в естественной эволюции простой очереди сообщений.
В этой архитектуре используется модульное приложение (composite application), обычно ориентированное на пользователей, которое общается с веб-сервисами для выполнения каких-то операций. В свою очередь, эти веб-сервисы тоже могут общаться с другими веб-сервисами, впоследствии возвращая приложению какие-то данные. Но ни приложение, ни бэкенд-сервисы ничего друг о друге не знают, включая расположение и протоколы связи. Они знают лишь, с каким сервисом хотят связаться и где находится сервисная шина.
Клиент (сервис или модульное приложение) отправляет запрос на сервисную шину, которая преобразует сообщение в формат, поддерживаемый в точке назначения, и перенаправляет туда запрос. Всё взаимодействие идёт через сервисную шину, так что если она падает, то с ней падают и все остальные системы. То есть ESB — ключевой посредник, очень сложный компонент системы.
Это очень упрощённое описание архитектуры ESB. Более того, хотя ESB является главным компонентом архитектуры, в системе могут использоваться и другие компоненты вроде доменных брокеров (Domain Broker), сервисов данных (Data Service), сервисов процессной оркестровки (Process Orchestration Service) и обработчиков правил (Rules Engine). Тот же паттерн может использовать интегрированная архитектура (federated design): система разделена на бизнес-домены со своими ESB, и все ESB соединены друг с другом. У такой схемы выше производительность и нет единой точки отказа: если какая-то ESB упадёт, то пострадает лишь её бизнес-домен.
Главные обязанности ESB:
Создавая структуры связи между разными процессами, мы видели много продуктов и подходов, в которых применяются очень развитые механизмы связи. Хороший пример — сервисные шины предприятий, часто включающие в себя сложные средства маршрутизации сообщений, хореографии, преобразования и применения бизнес-правил.
— Martin Fowler 2014, Microservices
У этого архитектурного паттерна есть положительные стороны. Однако я считаю его особенно полезным в случаях, когда мы не «владеем» веб-сервисами и нам нужен посредник для трансляции сообщений между сервисами, для оркестрирования бизнес-процессами, использующими несколько веб-сервисов, и прочих задач.
Также рекомендую не забывать, что реализации ESB уже достаточно развиты и в большинстве случаев позволяют использовать для своего конфигурирования пользовательский интерфейс с поддержкой drag & drop.
Достоинства
Недостатки
Микросервисы
В основе микросервисной архитектуры лежат концепции SOA. Назначение у неё то же, что и у ESB: создать единое общее корпоративное приложение из нескольких специализированных приложений бизнес-доменов.
Главное различие микросервисов и шины в том, что ESB была создана в контексте интеграции отдельных приложений, чтобы получилось единое корпоративное распределённое приложение. А микросервисная архитектура создавалась в контексте быстро и постоянно меняющихся бизнесов, которые (в основном) с нуля создают собственные облачные приложения.
То есть в случае с ESB у нас уже были приложения, которые нам не «принадлежат», и поэтому мы не могли их изменить. А в случае с микросервисами мы полностью контролируем приложения (при этом в системе могут использоваться и сторонние веб-сервисы).
Характер построения/проектирования микросервисов не требует глубокой интеграции. Микросервисы должны соответствовать бизнес-концепции, ограниченному контексту. Они должны сохранять своё состояние, быть независимыми от других микросервисов, и потому они меньше нуждаются в интеграции. То есть низкая взаимозависимость и высокая связность привели к замечательному побочному эффекту — уменьшению потребности в интеграции.
[Микросервисы — это] маленькие автономные сервисы, работающие вместе и спроектированные вокруг бизнес-домена.
— Sam Newman 2015, Principles Of Microservices
Главным недостатком архитектуры ESB было очень сложное централизованное приложение, от которого зависели все остальные приложения. А в микросервисной архитектуре это приложение почти целиком убрано.
Ещё остались элементы, пронизывающие всю экосистему микросервисов. Но у них гораздо меньше задач по сравнению с ESB. К примеру, для асинхронной связи между микросервисами до сих пор применяется очередь сообщений, но это лишь канал для передачи сообщений, не более того. Или можно вспомнить шлюз экосистемы микросервисов, через который проходит весь внешний обмен данными.
Сэм Ньюман, автор Building Microservices, выделяет восемь принципов микросервисной архитектуры. Это:
Сообщество предпочитает другой подход: умные конечные точки и глупые каналы. Микросервисы, из которых собираются приложения, должны как можно меньше зависеть друг от друга и при этом быть очень тесно связанными — они содержат собственную доменную логику и работают скорее как фильтры с точки зрения классического Unix: получают запросы, применяют логику и генерируют ответы. Они оркестрируются с помощью простых REST-подобных протоколов, а не сложных протоколов вроде WS-Choreography или BPEL либо какого-то централизованного инструмента.
— Martin Fowler 2014, Microservices
Достоинства
Недостатки
Антипаттерн: архитектура равиоли (Ravioli Architecture)
Архитектурой равиоли обычно называют антипаттерн микросервисной архитектуры. Равиоли получаются, если микросервисов слишком много, они слишком мелкие и не отражают доменных концепций.
Заключение
В последние десятилетия SOA сильно эволюционировала. Благодаря неэффективности прежних решений и развитию технологий сегодня мы пришли к микросервисной архитектуре.
Эволюция шла по классическому пути: сложные проблемы разбивались на более мелкие, простые в решении.
Проблему сложности кода можно решать так же, как мы разбиваем монолитное приложение на отдельные доменные компоненты (разграниченные контексты). Но с разрастанием команд и кодовой базы увеличивается потребность в независимом развитии, масштабировании и развёртывании. SOA помогает добиться такой независимости, упрочняя границы контекстов.
Повторюсь, что всё дело в слабой взаимозависимости и высокой связности, причём размер компонентов должен быть больше прежнего. Необходимо прагматично оценить свои потребности: используйте SOA, лишь когда это необходимо, поскольку она сильно увеличивает сложность. И если на самом деле вы можете обойтись без SOA, то лучше выберите микросервисы подходящего размера и количества, не больше и не меньше.
SOA (сервис-ориентированная архитектура)
Что такое SOA (сервис-ориентированная архитектура)?
SOA (сервис-ориентированная архитектура) предлагает способ многократного использования программных компонентов с помощью интерфейсов сервисов. Эти интерфейсы используют общие коммуникационные стандарты таким образом, чтобы их можно было быстро включить в новые приложения, не прибегая каждый раз к глубокой интеграции.
Каждый сервис SOA содержит интеграции кода и данных, необходимые для выполнения конкретной бизнес-функции, такой как проверка кредита клиента, вычисление ежемесячного взноса или обработка заявки на ипотеку. Интерфейсы сервисов являются слабо связанными, то есть они могут использоваться даже при небольших знаниях о том, как выполняется интеграция. Доступ к сервисам предоставляется с использованием стандартных сетевых протоколов, таких как SOAP (простой протокол доступа к объектам)/HTTP или JSON/HTTP, по которым отправляются запросы на чтение или изменение данных. Сервисы публикуются таким образом, что они позволяют разработчикам быстро находить их и повторно использовать для сборки новых приложений.
Эти сервисы могут быть созданы с нуля, но часто создаются путем экспорта функций из имеющихся систем в виде интерфейсов.
Таким образом, SOA представляет собой важную веху в эволюции разработки и интеграции приложений за последние несколько десятилетий. До появления SOA в конце 1990-х годов задача подключения приложений к данным и функциям из других систем предусматривала применение сложной двухточечной интеграции, которую разработчикам приходилось заново создавать (частично или полностью) в рамках каждого нового проекта разработки. Предоставление доступа к этим функциям с помощью SOA позволяет избавиться от необходимости каждый раз заново создавать глубокую интеграцию.
Обратите внимание, что SOA часто сравнивают с более современной архитектурой микросервисов, однако они слабо связаны друг с другом и работают на разных уровнях, как будет показано далее в этой статье.
Что такое ESB?
ESB (сервисная шина предприятия) — это шаблон, в рамках которого централизованный компонент осуществляет интеграцию с базовыми системами, а затем открывает доступ к этим интеграциям в качестве интерфейсов сервисов. Она обеспечивает преобразование моделей данных, тесное взаимодействие, маршрутизацию и даже создание нескольких запросов, объединяя эти функции в одном интерфейсе сервиса, который может повторно использоваться новыми приложениями. Как правило, шаблон ESB реализован с помощью специально разработанной среды выполнения интеграции и инструментов, которые хорошо подходят для максимально эффективного выполнения указанных выше функций.
Теоретически, SOA можно реализовать без применения ESB, однако владельцы приложений вынуждены были бы искать уникальные способы предоставления доступа к интерфейсам — это очень трудоемкая задача (даже в случае многоразовых интерфейсов), которая к тому же значительно усложнит обслуживание в будущем. Фактически, в итоге ESB стали рассматриваться в качестве неотъемлемого элемента любой реализации SOA и эти термины часто использовались как синонимы, что вызывало путаницу.
Дополнительная информация о ESB приведена на веб-странице «Введение в ESB (сервисная шина предприятия)».
Преимущества SOA
SOA предлагает существенные преимущества по сравнению с предшествующими архитектурами:
Примеры SOA
Уже в 2010 году реализации SOA активно использовались передовыми компаниями практически в каждой отрасли. Например:
SOA и микросервисы
Сравнению SOA имикросервисов и описанию тонкостей взаимосвязей между ними посвящены тысячи работ. В этой статье в качестве основных отличий описываются способ сопряжения компонентов и область применения:
Архитектура микросервисов появилась и получила широкое распространение на фоне растущей популярности виртуализации, облачных вычислений, гибких методик разработки и DevOps. Большая часть преимуществ микросервисов в этих контекстах связана с полным отделением компонентов, в результате которого упрощаются и улучшаются следующие процессы:
Для подробного изучения различий между SOA и микросервисами, обратитесь к веб-странице «SOA и микросервисы: в чем разница?»
В той же степени, в которой архитектура микросервисов обладает потенциалом для улучшения гибкости, масштабируемости и устойчивости разработки приложений, эти методики можно применить в области интеграции. Это важно, поскольку со временем централизованный шаблон ESB вместе с отвечающими за его работу специалистами по интеграции может превратиться в слабое звено. Заимствуя принципы микросервисов, мы можем разбить ESB на серию мелкомодульных, децентрализованных интеграций. Это один из базовых принципов гибкой интеграции.
SOA и IBM Cloud
По мере все более широкого внедрения гибридного облачного подхода вам потребуется трансформировать множество приложений, включая те из них, которые основаны на SOA, с применением более легких и гибких моделей облачного развертывания. IBM является одним из первопроходцев в сфере SOA, а предложения и услуги IBM Cloud помогут задействовать ваши существующие инвестиции в SOA и перенести их в облако.
Сделайте следующий шаг:
SOA обеспечивает возможность использования сервисов по разным каналам вне зависимости от расположения базового приложения или базы данных. Такой подход позволяет позволяет организации получить максимальную отдачу от инвестиций в процессе модернизации приложений на пути в облако.