Ejecuta pasos de flujo de trabajo en paralelo

Los pasos paralelos pueden reducir el tiempo total de ejecución de un flujo de trabajo mediante la realización de varias llamadas de bloqueo al mismo tiempo.

Las llamadas de bloqueo, como sleep, las llamadas HTTP, y las devoluciones de llamada, pueden tardar desde milisegundos hasta días. Los pasos paralelos están diseñados para ayudar con esas operaciones simultáneas de larga duración. Si un flujo de trabajo debe realizar varias llamadas de bloqueo que son independientes entre sí, el uso de ramas paralelas puede reducir el tiempo total de ejecución, ya que inicia las llamadas al mismo tiempo y espera a que se completen todas.

Por ejemplo, si tu flujo de trabajo debe recuperar datos del cliente de varios sistemas independientes antes de continuar, las ramas paralelas permiten solicitudes de API simultáneas. Si hay cinco sistemas y cada uno tarda dos segundos en responder, realizar los pasos de forma secuencial en un flujo de trabajo podría tardar al menos 10 segundos; realizarlos en paralelo podría tardar solo dos.

Crea un paso paralelo

Crea un paso parallel para definir una parte de tu flujo de trabajo en la que se puedan ejecutar dos o más pasos de forma simultánea.

YAML

  - PARALLEL_STEP_NAME:
      parallel:
        exception_policy: POLICY
        shared: [VARIABLE_A, VARIABLE_B, ...]
        concurrency_limit: CONCURRENCY_LIMIT
        BRANCHES_OR_FOR:
          ...

JSON

  [
    {
      "PARALLEL_STEP_NAME": {
        "parallel": {
          "exception_policy": "POLICY",
          "shared": [
            "VARIABLE_A",
            "VARIABLE_B",
            ...
          ],
          "concurrency_limit": "CONCURRENCY_LIMIT",
          "BRANCHES_OR_FOR":
          ...
        }
      }
    }
  ]

Reemplaza lo siguiente:

  • PARALLEL_STEP_NAME: el nombre del paso paralelo.
  • POLICY (opcional): determina la acción que tomarán otras ramas cuando se produzca una excepción no controlada. La política predeterminada, continueAll, no genera ninguna acción adicional, y todas las demás ramas intentarán ejecutarse. Ten en cuenta que continueAll es la única política compatible actualmente.
  • VARIABLE_A, VARIABLE_B, y así sucesivamente: una lista de variables de escritura con alcance superior que permiten asignaciones dentro del paso paralelo. Para obtener más información, consulta Variables compartidas.
  • CONCURRENCY_LIMIT (opcional): la cantidad máxima de ramas e iteraciones que se pueden ejecutar de forma simultánea dentro de una sola ejecución de flujo de trabajo antes de que se pongan en cola más ramas e iteraciones para esperar. Esto se aplica solo a un solo paso parallel y no se aplica en cascada. Debe ser un número entero positivo y puede ser un valor literal o una expresión. Para obtener más información, consulta Límites de simultaneidad.
  • BRANCHES_OR_FOR: usa branches o for para indicar una de las siguientes opciones:
    • Ramas que se pueden ejecutar de forma simultánea.
    • Un bucle en el que las iteraciones se pueden ejecutar de forma simultánea.

Ten en cuenta lo siguiente:

  • Las ramas y las iteraciones paralelas se pueden ejecutar en cualquier orden y pueden ejecutarse en un orden diferente con cada ejecución.
  • Los pasos paralelos pueden incluir otros pasos paralelos anidados hasta el límite de profundidad. Consulta Cuotas y límites.
  • Para obtener más detalles, consulta la página de referencia de sintaxis para los pasos paralelos.

Reemplaza la función experimental por un paso paralelo

Si usas experimental.executions.map para admitir el trabajo paralelo, puedes migrar tu flujo de trabajo para usar pasos paralelos en su lugar y ejecutar bucles for normales en paralelo. Para ver ejemplos, consulta Reemplaza la función experimental por un paso paralelo.

Muestras

En estas muestras, se demuestra la sintaxis.

Realiza operaciones en paralelo (con ramas)

Si tu flujo de trabajo tiene varios conjuntos de pasos diferentes que se pueden ejecutar al mismo tiempo, colocarlos en ramas paralelas puede disminuir el tiempo total necesario para completar esos pasos.

En el siguiente ejemplo, se pasa un ID de usuario como argumento al flujo de trabajo y los datos se recuperan en paralelo de dos servicios diferentes. Las variables compartidas permiten que los valores se escriban en las ramas y se lean después de que se completen las ramas:

YAML

main:
  params: [input]
  steps:
    - init:
        assign:
          - userProfile: {}
          - recentItems: []
    - enrichUserData:
        parallel:
          shared: [userProfile, recentItems]  # userProfile and recentItems are shared to make them writable in the branches
          branches:
            - getUserProfileBranch:
                steps:
                  - getUserProfile:
                      call: http.get
                      args:
                        url: '${"https://example.com/users/" + input.userId}'
                      result: userProfile
            - getRecentItemsBranch:
                steps:
                  - getRecentItems:
                      try:
                        call: http.get
                        args:
                          url: '${"https://example.com/items?userId=" + input.userId}'
                        result: recentItems
                      except:
                        as: e
                        steps:
                          - ignoreError:
                              assign:  # continue with an empty list if this call fails
                                - recentItems: []

JSON

{
  "main": {
    "params": [
      "input"
    ],
    "steps": [
      {
        "init": {
          "assign": [
            {
              "userProfile": {}
            },
            {
              "recentItems": []
            }
          ]
        }
      },
      {
        "enrichUserData": {
          "parallel": {
            "shared": [
              "userProfile",
              "recentItems"
            ],
            "branches": [
              {
                "getUserProfileBranch": {
                  "steps": [
                    {
                      "getUserProfile":