Spring boot Распределенная транзакция - PullRequest
0 голосов
/ 09 июля 2019

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

Вот постановка задачи.

У нас есть один микросервис Composite, который должен взаимодействовать с другими 2-мя атомными микросервисами (которые явно предназначены для конкретной цели) и иметь отдельную базу данных, например. Мы можем рассматривать эти 2 микросервиса как

  1. STUDENT_SERVICE (STU_DB)
  2. TEACHER_SERVICE (TEACHR_DB)

Здесь, в Composite Service Usecase, пользователь (Администратор) может назначить Учителя для ученика для определенного курса и т. Д.

Интересно, как мы можем решить эту проблему в одной транзакции, поскольку каждая служба (STUDENT_SERVICE и TEACHER_SERVICE) имеет отдельную БД, и все должно происходить в одной транзакции - либо фиксация, либо откат.

Поскольку эти 2 службы являются отдельными, и я вижу, что JTA не поможет, поскольку он предназначен для развертывания этих 2 приложений (служб) на одном сервере приложений!

Я отказался от JTAкак упомянуто выше // Класс псевдо-кода CompositeService {

AssignStaff(resquest){

//txn Start
updateStudentServiceAPI(request);
UpdateTeacherServiceAPI(request);
//txn End
}


} 

Система должна быть в согласованном состоянии после выполнения API

1 Ответ

0 голосов
/ 10 июля 2019

Это сложный вопрос, даже если он не очевиден с первого взгляда.

Функциональность, к которой вы обращаетесь, понимается как антишаблон для архитектуры микросервиса.

Микросервисная архитектура в целом является распределенной системой. Транзакции в распределенных системах сложны (см. https://martin.kleppmann.com/2015/09/26/transactions-at-strange-loop.html). Ваше приложение состоит из двух служб.

JTA - это Java API для транзакций в стиле ACID. ACID-транзакции обычно требуют блокировки в базах данных. Поскольку транзакция охватывает несколько сервисов (в вашем случае их два), сбой одного сервиса может заблокировать обработку другого сервиса. В этом случае вы теряете преимущество микросервисной архитектуры - слабую связь и независимость сервисов. Вы можете в конечном итоге построить распределенный монолит (см. Хорошую статью https://blog.christianposta.com/microservices/the-hardest-part-about-microservices-data/).

Btw. Есть несколько дискуссий на тему транзакций в микросервисах здесь, в Stackoverflow. Просто найдите или проверьте, например,

Какие у вас варианты

(отказ от ответственности: я разработчик для http://narayana.io, и представленные варианты представлены с точки зрения Java EE и Narayana. Могут быть и другие проекты, предоставляющие аналогичную функциональность. Кроме того, даже Narayana прекрасно интегрируется с Spring, возможно, вы необходимо решить некоторые проблемы интеграции.)

  • вам действительно нужно запустить транзакцию в стиле ACID в вашем проекте - иначе вы настаиваете, что вам нужно поведение транзакции в соответствии с описанием. Тогда вам нужно распределить транзакции по сервисам. Тогда, если сервисы обмениваются данными через REST, вы можете рассмотреть, например, Narayana REST-AT (http://jbossts.blogspot.com/2011/03/rest-cloud-and-transactions.html,, здесь вы можете начать поиск быстрого запуска https://github.com/jbosstm/quickstart/tree/master/rts)
  • Вы ослабляете свои требования к атомарности, а затем можете использовать некоторую модель транзакции, ослабляющую согласованность (вы можете быть последовательной). Вы можете рассмотреть, например, LRA (https://github.com/eclipse/microprofile-lra/blob/master/spec/src/main/asciidoc/microprofile-lra-spec.adoc). (К сожалению, спецификация и реализация еще не готовы, но PoC может быть запущен в текущем состоянии.)
  • Вы хотите полностью использовать другой подход для обработки транзакций. Затем вы можете исследовать источники событий. Вы бы развернули, например, Apache Kafka и отправлять события для обновления в хранилище событий. Каждый сервис будет читать эти события и обновлять независимо базы данных.
...