Исключение тайм-аута, когда размер входных данных дочернего рабочего процесса огромен

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 взят из org.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 идентификаторов в массив и передать это обратно в рабочий процесс. Затем рабочий процесс создает один дочерний рабочий процесс для каждого идентификатора. Затем каждый дочерний рабочий процесс вызывает другое действие с идентификатором для загрузки данных из БД. Но это действие должно передать этот огромный JSON в дочерний рабочий процесс, это нормально? А что если RestActivitiesWorker делает 100 вставок в БД, что делать, если он потерпит неудачу в середине?

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


person Gordon Sun    schedule 19.06.2020    source источник


Ответы (1)


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

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

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