Синхронизация асинхронных вызовов API с Java - PullRequest
0 голосов
/ 11 февраля 2020

Рассмотрим следующий сценарий:

  1. Служба A вызывает службу B, чтобы выполнить задачу.
  2. Служба B возвращает «ОК» и переходит к выполнению задание асинхронно.
  3. Поскольку A получил OK от B, он также возвращает ответ тому, кто его вызвал.

Я хочу иметь возможность синхронизировать эту задачу. Служба B настраивается так, что она может выполнить вызов API к концу задачи, которую она должна выполнить. Моя идея такова:

  1. Служба A вызывает службу B, чтобы выполнить задачу.
  2. Служба B возвращает «OK» и переходит к выполнению задачи асинхронно.
  3. Служба A получает ответ от B, но не возвращает.
  4. Служба B завершает задачу и отправляет вызов API для A (определенной конечной точке и т. Д. c ... ).
  5. Служба А получает, а затем возвращает.

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

Возможно ли синхронизировать асинхронный вызов API, как это происходит с Java / Spring? Я попытался найти в Интернете для этого, но не смог найти ничего подходящего.

1 Ответ

2 голосов
/ 11 февраля 2020

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

Если это так, вы можете использовать это id как идентификатор корреляции и может реализовать стратегию ожидания с использованием CompletableFutures. Когда служба B отвечает «OK», служба A может создать завершаемое будущее, используя уникальный идентификатор в качестве ключа, и вызвать get () для этого, который будет блокироваться до тех пор, пока не будет вызвана complete (). Когда служба B завершает свою обработку, она может вызвать API для службы A с результатом, вместе с идентификатором корреляции, который теперь можно использовать для завершения будущего.

Ниже приведены некоторые основы c код только для того, чтобы передать идею

public class ServiceA {

    private Map<String, CompletableFuture<String>> correlationStore;

    public ServiceA() {
        correlationStore = new HashMap<>();
    }

    public String performTask(String id, String data) {

        CompletableFuture<String> futureResult = new CompletableFuture<>();
        String submissionResult = callServiceB(id, data);
        if (!"OK".equalsIgnoreCase(submissionResult)) {
            return "FAILED";
        }
        //Service B has accepted the request and is busy processing the result
        correlationStore.put(id, futureResult);
        String response = null;
        try {
            //Set a timeout to whatever is sensible
            response = futureResult.get(30, TimeUnit.SECONDS); // Thread is now blocked until complete() is called
        } catch (InterruptedException | ExecutionException | TimeoutException e) {
            if (e instanceof TimeoutException) {
                correlationStore.remove(id);
            }
            //Handle failure depending on your requirements
        }
        return response;
    }

    //This is called from API call back from Service B
    public void onResponse(String id, String responseData) {
        CompletableFuture<String> pendingResult = correlationStore.remove(id);
        if (pendingResult != null) {
            pendingResult.complete(responseData);
        } else {
            //Handle the scenario where there is not future waiting for a response
        }
    }
}

Однако, используя этот тип подхода, необходимо учитывать ряд вещей, например, что делать, если служба B никогда не перезванивает службе A с результат, или, скорее, если вы ожидаете, пока Служба B ответит, удалите будущее, а затем ответ вернется на более позднем этапе, что вы должны сделать, чтобы справиться с этим?

Но это теперь все до что делает ваша служба A, и каковы ваши конкретные случаи c, связанные с отказом, т. е. сохранением состояния запросов в службе A и предоставлением механизма запроса состояния и т. д. c ..

Я бы Тем не менее, настоятельно рекомендуется, в зависимости от гибкости вашего проекта, изучить механизмы организации промежуточного ПО, будь то RabbitMQ / Kafka / Pulsa r et c, поскольку все они обеспечивают отличные функциональные возможности для архитектур на основе рабочих очередей и могут быть полезны для вас в зависимости от вашей ситуации.

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