Ищете лучший способ поделиться интерфейсом между микросервисами с 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.

Теперь мои вопросы:

  1. Я не вижу, что мне здесь не хватает. Не могли бы вы помочь мне?
  2. Является ли такое совместное использование API с выделенными проектами Api жизнеспособным способом или подход "монолит с дополнительными шагами" действительно подходит?

Заранее спасибо.

1 ответ

Это обычная проблема с микросервисами. Как и в книге "Микросервисы: Grundlagen flexibler Softwarearchitekturen" Эберхарда Вольфа (я видел, что вы тоже немец), я следую идее, что микросервисы должны иметь такую ​​же взаимосвязь, как и команды, разрабатывающие их, и как организация, для которой вы их разрабатываете (иметь посмотрите на закон Конвея). Поэтому сервисы, состоящие в основном из независимых команд, должны разрабатываться независимо, и изменения api одной службы не должны влиять на другую во время обновления.

Если вы разрабатываете обе службы в своей команде, я думаю, вы можете объединить их так, как вы это делаете, потому что вам не нужно работать вместе с другими командами и не возникнет огромных накладных расходов. Обратите внимание, что вам придется выпускать обе службы вместе. Если это всегда нормально для вас, сэкономьте свое время и сделайте это по-своему, если нет, посмотрите API-версии:

Я использую управление версиями api, поэтому старый api по-прежнему доступен в "v1/", а новый - в "v2/". Таким образом, у команды, стоящей за другим микросервисом, будет достаточно времени, чтобы обновить свой сервис.

Взгляните на предметно-ориентированный дизайн, чтобы узнать о различных способах интеграции ограниченных контекстов (= услуг) и последствиях связывания. Без поддержки версий API вы будете вынуждены сотрудничать, и вам нужно выпускать вместе. Может быть, вы предпочитаете Заказчик-Поставщик или даже конформист.

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

Другие вопросы по тегам