Ищете лучший способ поделиться интерфейсом между микросервисами с quarkus
Я все еще новичок в микросервисах, и у меня есть несколько основных архитектурных вопросов, которые я не могу решить прямо сейчас. Я использую для реализации фреймворк Quarkus со стандартными расширениями, такими как quarkus-resteasy и quarkus-rest-client.
Сценарий:
У меня есть пример службы "Постоянство", которую я хочу внешне заполнить данными через вызов REST в выделенном проекте Maven.
@Path("/api/persistence")
@Products(MediaType.APPLICATION_JSON)
public class Persistence{
@Inject
EntityManager entityManager;
@POST
@Transactional
public Response create(PostDto postDto) {
Post post = toPostMapper.toResource(postDto);
entityManager.persist(post);
return Response.ok(postDto).status(201).build();
}
}
В то же время хотелось бы иметь микросервис DataGenerator
который генерирует соответствующие данные и передает их в Persistence
Обслуживание.
Моя проблема: совместное использование API
Оба сервиса были созданы как проекты Maven. Согласно учебным пособиям, я нашел правильный способ - объявить интерфейс (здесь он называетсяPersistenceApi
) в DataGenerator
проект как этот
@Path("/api/persistence")
@Products(MediaType.APPLICATION_JSON)
@RegisterRestClient
public interface PersistenceApi {
@POST
@Transactional
public Response create(PostDto post) ;
}
Затем этот интерфейс интегрируется в DataGenerator
service через @Inject, что приводит к следующему примерному сервису.
@RequestScoped
@Path("/api/datagenerator")
@Products("application/json")
@Consumes("application/json")
public class DataGenerator{
@Inject
@RestClient
PersistenceApi persistenceApi
@POST
public void getPostExamplePostToPersistence() {
PostDto post = new PostDto();
post.setTitle("Find me in db in persistence-service")
persistenceApi.create(post);
}
}
у меня есть PersistenceService
работает локально на порту 8181 и добавили следующую запись в application.properties
из DataGenerator
проект, чтобы сервис можно было найти.
furnace.collection.item.service.PersistenceApi/mp-rest/url=http://localhost:8181
furnace.collection.item.service.PersistenceApi/mp-rest/scope=javax.inject.Singleton
Я считаю "неправильным" объявлять интерфейс в моем DataGenerator
, потому что на данный момент я не замечаю, когда API, предоставляемый Persistence
сервисные изменения. Соответственно, может возникнуть идея разместить интерфейс вPersistence
сервис, который затем реализуется моим конкретным Persistence
реализация и приводит к следующему коду.
@Path("/api/persistence")
@Products(MediaType.APPLICATION_JSON)
@RegisterRestClient
public class PersistenceApiImpl implements PersistenceApi {
@Inject
EntityManager entityManager;
@POST
@Transactional
public Response create(PostDto fruit) {
Post post = toPostMapper.toResource(fruit);
entityManager.persist(post);
return Response.ok(fruit).status(201).build();
}
}
Чтобы использовать их в своих DataGenerator
проект, мне нужно было бы включить Persistence
проект как зависимость в моем DataGenerator
проект, который для меня звучит как "монолит с дополнительными ступенями" и поэтому кажется неправильным с точки зрения "разделения интересов".
Я пробовал следующий подход: я создал еще один проект Maven под названиемPersistenceApi
который содержит только соответствующие PersistenceApi
. ЭтаPersistenceApi
Затем проект был включен как зависимость в проекты "Сохранение" и "Генератор данных". В проекте "Постоянство" я реализую службу из приведенного выше примера и пытаюсь обратиться к соответствующему интерфейсу в проекте "Генератор данных" через@Inject
.
К сожалению, это не работает. Когда я создаю сервис, я получаю сообщение о том, что требуемая зависимостьPersistenceApi
, который я хочу включить через @Inject
в DataGenerator
сервис, не может быть введен в виде UnsatisfiedResolutionException
.
Теперь мои вопросы:
- Я не вижу, что мне здесь не хватает. Не могли бы вы помочь мне?
- Является ли такое совместное использование API с выделенными проектами Api жизнеспособным способом или подход "монолит с дополнительными шагами" действительно подходит?
Заранее спасибо.
1 ответ
Это обычная проблема с микросервисами. Как и в книге "Микросервисы: Grundlagen flexibler Softwarearchitekturen" Эберхарда Вольфа (я видел, что вы тоже немец), я следую идее, что микросервисы должны иметь такую же взаимосвязь, как и команды, разрабатывающие их, и как организация, для которой вы их разрабатываете (иметь посмотрите на закон Конвея). Поэтому сервисы, состоящие в основном из независимых команд, должны разрабатываться независимо, и изменения api одной службы не должны влиять на другую во время обновления.
Если вы разрабатываете обе службы в своей команде, я думаю, вы можете объединить их так, как вы это делаете, потому что вам не нужно работать вместе с другими командами и не возникнет огромных накладных расходов. Обратите внимание, что вам придется выпускать обе службы вместе. Если это всегда нормально для вас, сэкономьте свое время и сделайте это по-своему, если нет, посмотрите API-версии:
Я использую управление версиями api, поэтому старый api по-прежнему доступен в "v1/", а новый - в "v2/". Таким образом, у команды, стоящей за другим микросервисом, будет достаточно времени, чтобы обновить свой сервис.
Взгляните на предметно-ориентированный дизайн, чтобы узнать о различных способах интеграции ограниченных контекстов (= услуг) и последствиях связывания. Без поддержки версий API вы будете вынуждены сотрудничать, и вам нужно выпускать вместе. Может быть, вы предпочитаете Заказчик-Поставщик или даже конформист.
Чтобы проверить совместимость между обеими службами, взгляните на контракты, ориентированные на потребителя, и Pact. Вы также можете создавать открытые файлы api и отслеживать их изменения, но это только поможет уведомить людей об изменениях.