Исключение тайм-аута, когда размер входных данных дочернего рабочего процесса огромен - PullRequest
0 голосов
/ 19 июня 2020
16:37:21.945 [Workflow Executor taskList="PullFulfillmentsTaskList", domain="test-domain": 3] WARN com.uber.cadence.internal.common.Retryer - Retrying after failure
org.apache.thrift.transport.TTransportException: Request timeout after 1993ms
    at com.uber.cadence.serviceclient.WorkflowServiceTChannel.throwOnRpcError(WorkflowServiceTChannel.java:546)
    at com.uber.cadence.serviceclient.WorkflowServiceTChannel.doRemoteCall(WorkflowServiceTChannel.java:519)
    at com.uber.cadence.serviceclient.WorkflowServiceTChannel.respondDecisionTaskCompleted(WorkflowServiceTChannel.java:962)
    at com.uber.cadence.serviceclient.WorkflowServiceTChannel.lambda$RespondDecisionTaskCompleted$11(WorkflowServiceTChannel.java:951)
    at com.uber.cadence.serviceclient.WorkflowServiceTChannel.measureRemoteCall(WorkflowServiceTChannel.java:569)
    at com.uber.cadence.serviceclient.WorkflowServiceTChannel.RespondDecisionTaskCompleted(WorkflowServiceTChannel.java:949)
    at com.uber.cadence.internal.worker.WorkflowWorker$TaskHandlerImpl.lambda$sendReply$0(WorkflowWorker.java:301)
    at com.uber.cadence.internal.common.Retryer.lambda$retry$0(Retryer.java:104)
    at com.uber.cadence.internal.common.Retryer.retryWithResult(Retryer.java:122)
    at com.uber.cadence.internal.common.Retryer.retry(Retryer.java:101)
    at com.uber.cadence.internal.worker.WorkflowWorker$TaskHandlerImpl.sendReply(WorkflowWorker.java:301)
    at com.uber.cadence.internal.worker.WorkflowWorker$TaskHandlerImpl.handle(WorkflowWorker.java:261)
    at com.uber.cadence.internal.worker.WorkflowWorker$TaskHandlerImpl.handle(WorkflowWorker.java:229)
    at com.uber.cadence.internal.worker.PollTaskExecutor.lambda$process$0(PollTaskExecutor.java:71)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
    at java.base/java.lang.Thread.run(Thread.java:834)

Код нашего родительского рабочего процесса в основном выглядит следующим образом (JSONObject от организации json)

JSONObject[] array = restActivities.getArrayWithHugeJSONItems();
for(JSONObject hugeJSON: array) {
  ChildWorkflow child = Workflow.newChildWorkflowStub(ChildWorkflow.class);
  child.run(hugeJSON);
}

Мы выясняем, что большую часть времени родительский рабочий процесс не запускает дочерний рабочий процесс и вызывает исключение тайм-аута выше. Он пытается как сумасшедший, но безуспешно и снова и снова выводит исключение тайм-аута. Однако иногда нам очень везет, и это работает. А иногда он дает сбой еще раньше у работника активности и выдает то же исключение. Мы полагаем, что это связано с тем, что размер данных слишком велик (около 5 МБ) и не может быть отправлен в течение тайм-аута (судя по журналу, мы предполагаем, что он установлен на 2 секунды). Если мы вызываем child.run с небольшими поддельными данными, он работает на 100%.

Причина, по которой мы используем дочерний рабочий процесс, заключается в том, что мы хотим использовать Async.function для их параллельного запуска. Так как же решить эту проблему? Есть ли конфигурация таймаута экономии, которую мы должны увеличить или как-то мы можем избежать передачи огромных данных?

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

--- Обновление после ответа Максима ---

Спасибо. Я прочитал пример, но у меня остались вопросы по моему варианту использования. Скажем, у меня есть массив из 100 огромных JSON объектов в моем RestActivitiesWorker, если я не должен возвращать огромный массив в рабочий процесс, мне нужно сделать 100 обращений к базе данных, чтобы создать 100 строк записей и поместить 100 идентификаторов в array и передайте его обратно в рабочий процесс. Затем рабочий процесс создает один дочерний рабочий процесс для каждого идентификатора. Затем каждый дочерний рабочий процесс вызывает другое действие с идентификатором для загрузки данных из БД. Но это действие должно передать этот огромный JSON дочернему рабочему процессу, это нормально? А что если RestActivitiesWorker делает 100 вставок в БД, что, если он потерпит неудачу в середине?

Я думаю, это сводится к тому, что наш рабочий процесс пытается работать напрямую с огромными JSON. Мы пытаемся загрузить в нашу систему огромный JSON (5-30 МБ, не такой уж и большой) из внешней системы. Мы немного разбиваем JSON, манипулируем несколькими значениями и используем значения из нескольких полей, чтобы сделать несколько разных logi c, и, наконец, сохраняем его в нашей БД. Как нам это сделать с Temporal?

1 Ответ

1 голос
/ 19 июня 2020

Temporal / Cadence не поддерживает передачу больших двоичных объектов в качестве входных и выходных данных, поскольку использует базу данных в качестве базового хранилища. Итак, вы хотите изменить архитектуру своего приложения, чтобы этого избежать.

Стандартные обходные пути:

  • Используйте внешнее хранилище BLOB-объектов для сохранения больших данных и передачи ссылки на них в качестве параметров.
  • Кэшируйте данные в рабочем процессе или даже на хост-диске и направлять действия, которые работают с этими данными, в этот процесс или хост. См. Пример обработки файлов для этого подхода.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...