Перейти к основному содержимому

Двенадцатифакторная методология в микросервисе Spring Boot

· 14 мин. чтения

1. Обзор

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

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

2. Что такое методология двенадцати факторов?

Методология двенадцати факторов представляет собой набор из двенадцати передовых методов разработки приложений, предназначенных для работы в качестве службы . Первоначально это было разработано Heroku для приложений, развернутых в качестве сервисов на их облачной платформе еще в 2011 году. Со временем это оказалось достаточно общим для любой разработки программного обеспечения как услуги (SaaS).

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

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

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

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

3. Микросервис с Spring Boot

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

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

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

Spring Boot — это платформа приложений, основанная на Spring, которая избавляет от многих шаблонов, связанных с разработкой корпоративного приложения. Это дает нам перспективную, но гибкую платформу для разработки микросервисов. В этом руководстве мы будем использовать Spring Boot для доставки микросервиса с использованием методологии двенадцати факторов.

4. Применение двенадцатифакторной методологии

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

Теперь, кто хотел бы начать фильм, а затем отказаться от него позже? Что нам нужно, так это простой сервис для записи и запроса фильмов, которые мы смотрели:

./04d65fc0e7430208d8f9e5e311c0d1bf.jpg

Это довольно простой и стандартный микросервис с хранилищем данных и конечными точками REST. Нам нужно определить модель, которая также будет отображать постоянство:

@Entity
public class Movie {
@Id
private Long id;
private String title;
private String year;
private String rating;
// getters and setters
}

Мы определили объект JPA с идентификатором и несколькими другими атрибутами. Давайте теперь посмотрим, как выглядит контроллер REST:

@RestController
public class MovieController {

@Autowired
private MovieRepository movieRepository;
@GetMapping("/movies")
public List<Movie> retrieveAllStudents() {
return movieRepository.findAll();
}

@GetMapping("/movies/{id}")
public Movie retrieveStudent(@PathVariable Long id) {
return movieRepository.findById(id).get();
}

@PostMapping("/movies")
public Long createStudent(@RequestBody Movie movie) {
return movieRepository.save(movie).getId();
}
}

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

4.1. Кодовая база

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

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

git init

Эту команду следует запускать из корня приложения. Приложение на этом этапе уже содержит файл .gitignore, который эффективно ограничивает управление версиями сгенерированных файлов. Итак, мы можем сразу создать начальный коммит:

git add .
git commit -m "Adding the bootstrap of the application."

Наконец, мы можем добавить удаленное устройство и отправить наши коммиты на удаленное устройство, если захотим (это не является строгим требованием):

git remote add origin https://github.com/<username>/12-factor-app.git
git push -u origin master

4.2. Зависимости

Далее, двенадцатифакторное приложение всегда должно явно объявлять все свои зависимости . Мы должны сделать это, используя манифест объявления зависимости. В Java есть несколько инструментов управления зависимостями, таких как Maven и Gradle. Мы можем использовать один из них для достижения этой цели.

Итак, наше простое приложение зависит от нескольких внешних библиотек, таких как библиотека для поддержки REST API и для подключения к базе данных. Давайте посмотрим, как мы можем декларативно определить их с помощью Maven.

Maven требует от нас описания зависимостей проекта в файле XML, обычно известном как объектная модель проекта (POM):

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>

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

4.3. Конфигурации

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

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

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

Spring предоставляет файл конфигурации, в котором мы можем объявить такие конфигурации и прикрепить их к переменным среды:

spring.datasource.url=jdbc:mysql://${MYSQL_HOST}:${MYSQL_PORT}/movies
spring.datasource.username=${MYSQL_USER}
spring.datasource.password=${MYSQL_PASSWORD}

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

В Windows мы можем установить переменную среды перед запуском приложения:

set MYSQL_HOST=localhost
set MYSQL_PORT=3306
set MYSQL_USER=movies
set MYSQL_PASSWORD=password

Мы можем использовать инструмент управления конфигурацией, такой как Ansible или Chef , для автоматизации этого процесса.

4.4. Услуги поддержки

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

В нашем приложении мы использовали MySQL в качестве резервной службы для обеспечения постоянства.

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

@Repository
public interface MovieRepository extends JpaRepository<Movie, Long> {
}

Как мы видим, это не зависит напрямую от MySQL. Spring обнаруживает драйвер MySQL в пути к классам и динамически предоставляет специфичную для MySQL реализацию этого интерфейса. Кроме того, он извлекает другие детали напрямую из конфигураций.

Итак, если нам нужно перейти с MySQL на Oracle, все, что нам нужно сделать, это заменить драйвер в наших зависимостях и заменить конфигурации.

4.5. Создавайте, выпускайте и запускайте

Методология двенадцати факторов строго разделяет процесс преобразования кодовой базы в работающее приложение на три отдельных этапа:

  • Этап сборки: здесь мы берем кодовую базу, выполняем статические и динамические проверки, а затем генерируем исполняемый пакет, например JAR. Используя такой инструмент, как Maven , это довольно тривиально:
mvn clean compile test package
  • Стадия выпуска: на этом этапе мы берем исполняемый пакет и комбинируем его с правильными конфигурациями. Здесь мы можем использовать Packer с поставщиком, таким как Ansible , для создания образов Docker:
packer build application.json
  • Стадия выполнения. Наконец, это стадия, на которой мы запускаем приложение в целевой среде выполнения. Если мы используем Docker в качестве контейнера для выпуска нашего приложения, запуск приложения может быть достаточно простым:
docker run --name <container_id> -it <image_id>

Наконец, нам не обязательно выполнять эти этапы вручную. Вот где Jenkins очень удобен со своим декларативным конвейером.

4.6. Процессы

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

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

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

4.7. Привязка порта

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

В нашем случае мы разработали приложение с использованием Spring Boot. Spring Boot, помимо многих других преимуществ, предоставляет нам встроенный сервер приложений по умолчанию. Следовательно, JAR, который мы создали ранее с помощью Maven, полностью способен выполняться в любой среде, просто имея совместимую среду выполнения Java:

java -jar application.jar

Здесь наше простое приложение предоставляет свои конечные точки через HTTP-привязку к определенному порту, например 8080. После запуска приложения, как мы делали выше, должна быть возможность доступа к экспортированным службам, таким как HTTP.

Приложение может экспортировать несколько служб, таких как FTP или WebSocket , путем привязки к нескольким портам.

4.8. параллелизм

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

Методология двенадцати факторов предлагает приложениям полагаться на процессы для масштабирования. Фактически это означает, что приложения должны быть спроектированы таким образом, чтобы распределять рабочую нагрузку между несколькими процессами. Однако отдельные процессы могут свободно использовать внутри себя модель параллелизма, такую как Thread .

Приложение Java при запуске получает один процесс, который привязан к базовой JVM. Что нам действительно нужно, так это способ запуска нескольких экземпляров приложения с интеллектуальным распределением нагрузки между ними. Поскольку мы уже упаковали наше приложение в виде контейнера Docker , Kubernetes — естественный выбор для такой оркестровки.

4.9. одноразовость

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

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

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

4.10. Соотношение разработки и производства

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

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

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

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

4.11. Журналы

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

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

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

Это мы можем передать в Elasticsearch для хранения и индексации. Наконец, мы можем создавать осмысленные информационные панели для визуализации в Kibana .

4.12. Административные процессы

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

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

В нашем примере, как нам заполнить наше приложение уже просмотренными фильмами? Хотя мы можем использовать нашу милую маленькую конечную точку, но это может показаться непрактичным. Что нам нужно, так это скрипт для выполнения однократной загрузки. Мы можем написать небольшую функцию Java для чтения списка фильмов из файла и их пакетного сохранения в базе данных.

Более того, мы можем использовать Groovy, интегрированный со средой выполнения Java , для запуска таких процессов.

5. Практические приложения

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

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

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

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

6. Заключение

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