Ищете лучший способ поделиться интерфейсом между микросервисами с quarkus - PullRequest
0 голосов
/ 09 июля 2020

Я все еще новичок в микросервисах, и у меня есть несколько c основных архитектурных вопросов, которые я не могу решить прямо сейчас. Я использую для реализации фреймворк 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. через @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 затем был включен как зависимость как в проекты «Постоянство», так и в проекты «Генератор данных». В проекте «Постоянство» я реализую службу из приведенного выше примера и пытаюсь обратиться к соответствующему интерфейсу в проекте «DataGenerator» через @Inject.

К сожалению, это не работает. Когда я создаю службу, я получаю сообщение о том, что требуемая зависимость PersistenceApi, которую я хочу включить через @Inject в службу DataGenerator, не может быть введена в виде UnsatisfiedResolutionException.

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

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

Заранее благодарю

1 Ответ

0 голосов
/ 12 июля 2020

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

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...