Архитектурное решение для асинхронных запросов API для очереди зависимых сообщений - PullRequest
0 голосов
/ 18 мая 2019

Мне нужно реализовать какой-нибудь скрипт для экспорта данных из одного сервиса в другой. Сервис Origin написан с использованием языка PHP. Служба назначения имеет SOAP API с MQ под капотом, поэтому каждый запрос к этому API преобразуется в сообщение, которое отправляется в очередь и ожидает обработки. Сервер API отвечает на этот запрос только с идентификатором сообщения, поэтому мне нужно выполнить один или несколько дополнительных запросов с этим идентификатором сообщения в качестве параметра, чтобы получить статус и результат обработки моего первоначального запроса.

Основная проблема в том, что у меня много данных для обработки, когда следующий запрос зависит от результата предыдущего запроса. Я собираюсь использовать какую-то службу MQ на стороне клиента, чтобы заставить клиента «ждать» результата успешной обработки предыдущего запроса. На данный момент в стеке нашего проекта есть 2 таких сервиса: Kafka и Gearman. Было бы замечательно решить проблему с использованием этих тем без необходимости установки дополнительных служб.

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

[
  'title' => 'Cars',
  'folders' => [
    [
      'title' => 'Chevrolet',
      'folders' => [],
      'files' => [
        ['file' => '/path/to/images/dir/camaro.jpg'],
        ['file' => '/path/to/images/dir/tahoe.jpg']
      ]
    ],
  ]
]

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

// Ask API to create folder
>>> ['action' => 'create-folder', 'name' => 'Cars', 'parent' => 'null']
// Get ID of the message in queue
<<< ['status' => 'received', 'message-id' => 123]
// Request message status
>>> ['action' => 'get-message-result', 'message-id' => 123]
// Get ID of the created folder
<<< ['status' => 'created', 'folder-id' => 1]

// Perform next request using ID of created folder as parent ID
>>> ['action' => 'create-folder', 'name' => 'Chevrolet', 'parent' => 1]
<<< ['status' => 'received', 'message-id' => 124]
>>> ['action' => 'get-message-result', 'message-id' => 124]
<<< ['status' => 'pending']
// ... Maybe rerun request multiple times because of server delays
>>> ['action' => 'get-message-result', 'message-id' => 124]
<<< ['status' => 'created', 'folder-id' => 2]

// Upload physical file
>>> ['action' => 'upload-file', 'path' => '/path/to/images/dir/camaro.jpg']
<<< ['status' => 'received', 'message-id' => 125],
>>> ['action' => 'get-message-result', 'message-id' => 125]
// Get path to the uploaded file, generated by server
<<< ['status' => 'created', 'file-name' => '/tmp/_190402934.jpg'],

// Create DB record linked to that physical file
>>> ['action' => 'create-file', 'path' => '/tmp/_190402934.jpg'],
<<< ['status' => 'received', 'message-id' => 126],
>>> ['action' => 'get-message-result', 'message-id' => 126]
<<< ['status' => 'created', 'file-id' => 100],
// ... and so on

Главное, что я хочу показать, это то, что один запрос зависит от другого. Результат запроса не содержит данных об успехе, только идентификатор сообщения в очереди, поэтому для получения данных результата необходимо выполнить неизвестное количество дополнительных запросов после основного. И только после получения необходимых данных (например, идентификатора созданной папки) очередь клиента может перейти к следующему шагу.

Не могли бы вы помочь мне с вашими предложениями по эффективному способу реализации этого? Можно ли это реализовать с помощью Gearman или / и Kafka?

Возможно ли установить какое-либо ограничение на MQ клиента, которое будет ограничивать службу для запуска следующего запроса API только после получения требуемого результата предыдущего запроса (независимо от задержки и количества дополнительных запросов 'get-message-result' между основным запросом) и фактический результат обработки этого запроса)?

Может быть, вы могли бы предложить несколько примеров, статей или книг, где были решены похожие проблемы?

...