你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

在 Azure 逻辑应用中处理错误和异常

适用范围:Azure 逻辑应用(消耗型 + 标准型)

恰当地处理依赖系统造成的停机或问题对任何集成体系结构而言可能都是一个难题。 为了帮助创建可适当处理问题和失败的可靠、可复原集成,Azure 逻辑应用提供了一流的错误和异常处理体验。

重试策略

对于最基本的异常和错误处理,如果触发器或作(如 HTTP作)上存在此功能,则可以使用重试策略。 如果触发器或操作的原始请求超时或失败,导致 408、429 或 5xx 响应,重试策略指定触发器或操作根据策略设置重新发送请求。

重试策略限制

有关重试策略、设置、限制和其他选项的详细信息,请查看重试策略限制

重试策略类型

支持重试策略的连接器操作使用“默认”策略,除非你选择其他重试策略。

重试策略 说明
默认 对于大多数操作,“默认”重试策略是指数间隔策略,它采用指数级增长间隔最多发送 4 次重试。 这些间隔的增幅为 7.5 秒,但范围限定在 5 到 45 秒之间。 多个操作使用不同的“默认”重试策略,例如固定间隔策略。 有关详细信息,请查看默认重试策略类型
不重新发送请求。 有关详细信息,请查看无 - 无重试策略
指数时间间隔 此策略在发送下一个请求之前等待一个随机时间间隔,该随机时间间隔选自指数级增长的范围。 有关详细信息,请查看指数间隔策略类型
固定时间间隔 此策略会等待指定的时间间隔,然后再发送下一个请求。 有关详细信息,请查看固定间隔策略类型

更改设计器中的重试策略类型

  1. Azure 门户中,打开你的逻辑应用资源。

  2. 在资源边栏上,按照以下步骤基于逻辑应用打开工作流设计器:

    • 消耗:在 “开发工具”下,选择设计器以打开工作流。

    • 标准

      1. “工作流”下,选择 “工作流”。

      2. 从“ 工作流 ”页中,选择工作流。

      3. “工具”下,选择设计器以打开工作流。

  3. 在要更改重试策略类型的触发器或作上,按照以下步骤打开设置:

    1. 在设计器中,选择操作。

    2. 在操作信息窗格中,选择“设置”

    3. “网络”下,在 “重试策略”下,选择所需的策略类型。

在代码视图编辑器中更改重试策略类型

  1. 通过完成设计器中之前的步骤,确认触发器或操作是否支持重试策略。

  2. 在代码视图编辑器中打开逻辑应用工作流。

  3. 在触发器或作定义中,将 retryPolicy JSON 对象添加到触发器或作 inputs 的对象。 如果不存在 retryPolicy 对象,触发器或作将使用 default 重试策略。

    "inputs": {
       <...>,
       "retryPolicy": {
          "type": "<retry-policy-type>",
          // The following properties apply to specific retry policies.
          "count": <retry-attempts>,
          "interval": "<retry-interval>",
          "maximumInterval": "<maximum-interval>",
          "minimumInterval": "<minimum-interval>"
       },
       <...>
    },
    "runAfter": {}
    

    必需

    properties 类型 说明
    type <retry-policy-type> 字符串 要使用的重试策略类型:defaultnonefixedexponential
    count <重试尝试> 整数 对于 fixedexponential 策略类型,重试次数是一个 1-90 之间的值。 有关详细信息,请查看固定时间间隔指数时间间隔
    interval <retry-interval> 字符串 对于 fixedexponential 策略类型,重试时间间隔值采用 ISO 8601 格式。 对于 exponential 策略,还可以指定可选的最大和最小时间间隔。 有关详细信息,请查看固定时间间隔指数时间间隔

    使用:5 秒 (PT5S) 到 1 天 (P1D)。
    标准:对于有状态工作流,5 秒 (PT5S) 到 1 天 (P1D)。 对于无状态工作流,1 秒 (PT1S) 到 1 分钟 (PT1M)。

    可选

    properties 类型 说明
    maximumInterval <最大间隔> 字符串 对于 exponential 策略,是指随机选定的时间间隔的最大时间间隔(采用 ISO 8601 格式)。 默认值为 1 天 (P1D)。 有关详细信息,请查看指数时间间隔
    minimumInterval <minimum-interval> 字符串 对于 exponential 策略,是指随机选定的时间间隔的最小时间间隔(采用 ISO 8601 格式)。 默认值为 5 秒 (PT5S)。 有关详细信息,请查看指数时间间隔

默认重试策略

支持重试策略的连接器操作使用“默认”策略,除非你选择其他重试策略。 对于大多数操作,“默认”重试策略是指数间隔策略,它采用指数级增长间隔最多发送 4 次重试。 这些间隔的增幅为 7.5 秒,但范围限定在 5 到 45 秒之间。 多个操作使用不同的“默认”重试策略,例如固定间隔策略。

在工作流定义中,触发器或操作定义不会显式定义默认策略,但以下示例显示了默认重试策略针对 HTTP 操作的行为方式:

"HTTP": {
   "type": "Http",
   "inputs": {
      "method": "GET",
      "uri": "http://myAPIendpoint/api/action",
      "retryPolicy" : {
         "type": "exponential",
         "interval": "PT7S",
         "count": 4,
         "minimumInterval": "PT5S",
         "maximumInterval": "PT1H"
      }
   },
   "runAfter": {}
}

None - 无重试策略

若要指定操作或触发器不重试失败的请求,请将 <retry-policy-type 设置为 >none

固定时间间隔重试策略

若要指定操作或触发器在等待指定的时间间隔后再发送下一个请求,请将 <retry-policy-type 设置为 >fixed

示例

该重试策略在首次请求失败后再尝试获取最新资讯两次,每次尝试之间延迟 30 秒:

"Get_latest_news": {
   "type": "Http",
   "inputs": {
      "method": "GET",
      "uri": "https://mynews.example.com/latest",
      "retryPolicy": {
         "type": "fixed",
         "interval": "PT30S",
         "count": 2
      }
   }
}

指数时间间隔重试策略

指数时间间隔重试策略指定触发器或操作在发送下一个请求之前等待随机时间间隔。 此随机时间间隔选自指数级增长范围。 或者,可以根据是否有使用或标准逻辑应用工作流指定自己的最小和最大时间间隔来替代默认的最小和最大间隔。

名称 使用限制 标准限制 说明
最大延迟 默认值:1 天 默认值:1 小时 若要更改使用逻辑应用工作流中的默认限制,请使用重试策略参数

若要更改标准逻辑应用工作流中的默认限制,请查看在单租户 Azure 逻辑应用中编辑逻辑应用的主机和应用设置

最小延迟 默认值:5 秒 默认值:5 秒 若要更改使用逻辑应用工作流中的默认限制,请使用重试策略参数

若要更改标准逻辑应用工作流中的默认限制,请查看在单租户 Azure 逻辑应用中编辑逻辑应用的主机和应用设置

随机变量范围

对于指数时间间隔重试策略,下表显示了 Azure 逻辑应用用于为每次重试生成指定范围内的统一随机变量的一般算法。 指定的范围最多可以包含重试次数。

重试次数 最小间隔 最大间隔
1 max(0, <minimum-interval>) min(interval, <maximum-interval>)
2 max(interval, <minimum-interval>) min(2 * interval, <maximum-interval>)
3 max(2 * interval, <minimum-interval>) min(4 * interval, <maximum-interval>)
4 max(4 * interval, <minimum-interval>) min(8 * interval, <maximum-interval>)
.... .... ....

管理“随后运行”行为

在工作流设计器中添加操作时,您会隐式声明运行这些操作的顺序。 某个操作完成运行后,该操作将标记为“成功”、“失败”、“跳过”或“超时”等状态。 换句话说,前置动作必须先完成任何允许的状态,然后才能运行后续作。

默认情况下,只有当前一个操作以“成功”状态完成时,您在设计器中添加的操作才会运行。 此 在之后运行 的行为精确指定工作流中动作的运行顺序。

在设计器中,可以通过编辑操作的“运行后”设置来更改操作的默认“运行后”行为。 此设置仅适用于工作流中第一个操作之后的后续操作。 工作流中的第一个作业始终在触发器成功运行后执行。 因此,“运行后”设置不可用,不适用于第一个动作。

在操作的基础 JSON 定义中,后运行 设置与 runAfter 属性相同。 此属性指定一个或多个前置作,这些作必须先完成特定允许的状态,然后才能运行后续作。 该 runAfter 属性是一个 JSON 对象,通过允许指定在后续作运行之前必须完成的所有前置作,从而提供灵活性。 此对象还定义可接受的状态数组。

例如,若要在操作 A 成功后,以及操作 B 成功或失败后执行某项操作,请在编写操作的 JSON 定义时设置以下 runAfter 属性:

{
   // Other parts in action definition
   "runAfter": {
      "Action A": ["Succeeded"],
      "Action B": ["Succeeded", "Failed"]
    }
}

错误处理的“运行后”行为

当某个操作引发了未经处理的错误或异常时,该操作将标记为“失败”,而任何后续操作将标记为“跳过”。 如果具有并行分支的操作发生此行为,Azure 逻辑应用引擎将跟踪其他分支来确定其完成状态。 例如,如果某个分支以“跳过”操作结束,该分支的完成状态基于该已跳过操作的前置操作的状态。 工作流运行完成后,引擎将通过评估所有分支的状态来确定整个运行的状态。 如果任何分支以失败结束,整个工作流运行将标记为“失败”

概念图,其中显示了如何评估运行状态的示例。

为了确保无论前置操作状态如何,某个操作都可运行,你可以更改操作的“随后运行”行为,用于处理前置操作的不成功状态。 这样,当前置操作的状态为“成功”、“失败”、“跳过”、“超时”或所有这些状态时,操作都会运行

例如,如果要在 Excel Online“为表添加一行”的前置操作被标记为“失败”而不是“成功”后运行 Office 365 Outlook 的“发送一封电子邮件”操作,请使用设计器或代码视图编辑器更改“随后运行”行为

更改设计器中的“随后运行”行为

  1. Azure 门户中,打开你的逻辑应用资源。

  2. 在资源边栏上,按照以下步骤基于逻辑应用打开工作流设计器:

    • 消耗:在 “开发工具”下,选择设计器以打开工作流。

    • 标准

      1. 在资源边栏的 “工作流”下,选择“ 工作流”。

      2. 从“ 工作流 ”页中,选择工作流。

      3. “工具”下,选择设计器以打开工作流。

  3. 在要更改“运行后”行为的触发器或操作上,按照以下步骤打开操作的设置:

    1. 在设计器中,选择操作。

    2. 在操作信息窗格中,选择“设置”

      运行后”部分包含“选择动作”列表,其中显示了当前所选操作的可用前置操作,例如:

      屏幕截图显示了具有前置操作的选择操作列表。

    3. 选择操作列表下,展开当前前置操作,在本示例中,这个操作是HTTP

      屏幕截图显示当前前置任务操作。

      默认情况下,“此后运行”状态设置为“成功”。 此值表示前置作必须先成功完成,然后才能运行当前作。

      状态设置为“成功”后,屏幕截图显示当前运行情况。

  4. 若要将“运行后”行为更改为所需的状态,请选择这些状态。

    以下示例选择了“已失败”

    显示行为设置为“已失败”后当前运行的屏幕截图。

  5. 若要指定当前作仅在前置任务完成且 “已失败”、“ 已跳过”或 “已超时 ”状态时运行,请选择这些状态,然后清除默认状态,例如:

    屏幕截图显示了当前操作,并选择了多个运行后的状态。

    注意

    在清除默认状态之前,请确保首先选择另一个状态。 您必须始终选择至少一个状态。

  6. 若要要求运行和完成多个前置任务作,每个作都有其自己的“运行后”状态,请执行以下步骤:

    1. 打开 “选择操作” 列表,然后选择所需的前置操作。

    2. 选择每个操作的“运行后”状态。

    屏幕截图显示了当前操作和可用的多个前置操作。

  7. 完成后,关闭操作信息窗格。


在代码视图编辑器中更改“随后运行”行为

  1. 在资源边栏上,按照以下步骤打开代码视图编辑器,具体取决于逻辑应用:

    • 消耗:在 “开发工具”下,选择代码视图以在 JSON 编辑器中打开工作流。

    • 标准

      1. “工作流”下,选择 “工作流”。

      2. 从“ 工作流 ”页中,选择工作流。

      3. “工具”下,选择代码视图以在 JSON 编辑器中打开工作流。

  2. 在操作的 JSON 定义中,编辑 runAfter 属性,该属性具有以下语法:

    "<action-name>": {
       "inputs": {
          "<action-specific-inputs>"
       },
       "runAfter": {
          "<preceding-action>": [
             "Succeeded"
          ]
       },
       "type": "<action-type>"
    }
    
  3. 对于本示例,请将 runAfter 属性从 Succeeded 更改为 Failed

    "Send_an_email_(V2)": {
       "inputs": {
          "body": {
             "Body": "<p>Failed to add row to table: @{body('Add_a_row_into_a_table')?['Terms']}</p>",
             "Subject": "Add row to table failed: @{body('Add_a_row_into_a_table')?['Terms']}",
             "To": "Sophia.Owen@fabrikam.com"
          },
          "host": {
             "connection": {
                "name": "@parameters('$connections')['office365']['connectionId']"
             }
          },
          "method": "post",
          "path": "/v2/Mail"
       },
       "runAfter": {
          "Add_a_row_into_a_table": [
             "Failed"
          ]
       },
       "type": "ApiConnection"
    }
    
  4. 若要将操作指定为在前置任务操作被标记为 FailedSkippedTimedOut 时都会运行,请添加其他状态:

    "runAfter": {
       "Add_a_row_into_a_table": [
          "Failed", "Skipped", "TimedOut"
       ]
    },
    

评估具有作用域的操作及其结果

与使用“此后运行”设置在单个操作之后运行步骤类似,可以将操作分组到某个范围内。 如果希望以逻辑方式将各个操作组合在一起,可以使用作用域,评估作用域的聚合状态,并基于该状态执行操作。 当某个作用域中的所有操作都完成运行后,该作用域本身也确定了其自己的状态。

若要检查作用域的状态,可以使用与用来检查工作流运行状态(例如“成功”、“失败”等)相同的条件

默认情况下,当作用域的所有操作都成功时,作用域的状态将被标记为 Succeeded。 如果作用域中最后一个操作的状态为“失败”或“中止”,那么作用域的状态标记为“失败”

若要捕获“失败”作用域中的异常并运行用来处理这些错误的操作,可以为“失败”的作用域使用“随后运行”设置。 这样,如果作用域中的“任何”操作失败并且为该作用域使用了“随后运行”设置,在可以创建单个操作来捕获失败

有关作用域的限制,请参阅限制和配置

为异常处理设置“运行后”的范围

  1. Azure 门户的设计器中,打开你的逻辑应用资源和工作流。

    工作流必须已有启动工作流的触发器。

  2. 在设计器中, 遵循以下通用步骤,将名为“范围”的“控件”操作添加到工作流

  3. 在“范围”操作中,按照以下通用步骤操作来运行,例如:

    屏幕截图显示了工作流设计器,其中操作分组在作用域内。

    以下列表显示了一些示例操作,你可以在“范围”操作中包含这些操作:

    • 从 API 获取数据。
    • 处理数据。
    • 将数据保存到数据库。
  4. 现在,定义用于在作用域中运行操作的“运行后”规则。

    1. 在设计器上,选择“范围”标题。 当作用域的信息窗格打开时,选择“设置”

    2. 如果工作流中有多个前面的操作,请在“选择操作”列表中选择要运行作用域操作的操作。

    3. 对于所选操作,请选择可以运行作用域操作的所有操作状态。

      换句话说,所选操作产生的任何所选状态都会导致作用域中的操作运行。

      在以下示例中,在 HTTP 操作完成并具有任何所选状态后运行作用域的操作:

      屏幕截图显示范围操作的“设置”选项卡、“在节后运行”和运行作用域操作的选定操作状态。

获取失败的上下文和结果

尽管从作用域中捕获失败非常有用,但可能还需要借助更多上下文来帮助你了解确切的失败操作以及任何错误或状态代码。 result() 函数返回作用域操作中顶级操作的结果。 此函数接受作用域名作为单个参数,并返回包含这些顶级操作结果的数组。 这些操作对象具有的特性(例如操作的开始时间、结束时间、状态、输入、相关 ID 和输出)与 actions() 函数返回的特性相同。

注意

result() 函数仅返回顶级操作的结果,而不从更深的嵌套操作(如切换或条件操作)返回结果

若要获取作用域中失败操作的上下文,可以使用具有作用域名和“随后运行”设置的 @result() 表达式。 若要从返回的数组中筛选出具有“失败”状态的操作,可以添加“筛选数组”操作。 若要为返回的失败操作运行操作,请获取返回的筛选数组,并使用 For each 循环

以下 JSON 示例发送一个 HTTP POST 请求,其中包含名为“My_Scope”作用域操作中失败的任何操作的响应正文。 示例后附详细说明。

"Filter_array": {
   "type": "Query",
   "inputs": {
      "from": "@result('My_Scope')",
      "where": "@equals(item()['status'], 'Failed')"
   },
   "runAfter": {
      "My_Scope": [
         "Failed"
      ]
    }
},
"For_each": {
   "type": "foreach",
   "actions": {
      "Log_exception": {
         "type": "Http",
         "inputs": {
            "method": "POST",
            "body": "@item()['outputs']['body']",
            "headers": {
               "x-failed-action-name": "@item()['name']",
               "x-failed-tracking-id": "@item()['clientTrackingId']"
            },
            "uri": "http://requestb.in/"
         },
         "runAfter": {}
      }
   },
   "foreach": "@body('Filter_array')",
   "runAfter": {
      "Filter_array": [
         "Succeeded"
      ]
   }
}

以下步骤描述了此示例中发生的情况:

  1. 若要获取“My_Scope”中所有操作的结果,“筛选数组”操作将使用筛选表达式@result('My_Scope')

  2. “筛选数组”的条件是状态等于 的任何 @result()Failed。 此条件将具有“My_Scope”中所有操作结果的数组筛选为仅包含失败操作结果的数组

  3. 对“筛选后的数组”输出执行 For_each 循环操作。 此步骤针对前面筛选的每个失败操作结果执行操作。

    如果作用域中只有一个操作失败,For_each 循环中的操作只运行一次。 如果存在多个失败的操作,则将对每个失败执行一次操作。

  4. 针对 For_each 项响应正文(即 @item()['outputs']['body'] 表达式)发送 HTTP POST。

    @result() 项的形状与 @actions() 形状相同,可按相同的方式进行分析。

  5. 包括两个自定义标头,其中包含失败操作的名称 (@item()['name']) 和失败的运行客户端跟踪 ID (@item()['clientTrackingId'])。

下面提供了单个 @result() 项的示例供参考,其中显示 namebodyclientTrackingId 属性已在前面的示例进行分析。 在 For_each 操作外部,@result() 会返回这些对象的数组。

{
   "name": "Example_Action_That_Failed",
   "inputs": {
      "uri": "https://myfailedaction.azurewebsites.net",
      "method": "POST"
   },
   "outputs": {
      "statusCode": 404,
      "headers": {
         "Date": "Thu, 11 Aug 2016 03:18:18 GMT",
         "Server": "Microsoft-IIS/8.0",
         "X-Powered-By": "ASP.NET",
         "Content-Length": "68",
         "Content-Type": "application/json"
      },
      "body": {
         "code": "ResourceNotFound",
         "message": "/docs/folder-name/resource-name does not exist"
      }
   },
   "startTime": "2016-08-11T03:18:19.7755341Z",
   "endTime": "2016-08-11T03:18:20.2598835Z",
   "trackingId": "bdd82e28-ba2c-4160-a700-e3a8f1a38e22",
   "clientTrackingId": "08587307213861835591296330354",
   "code": "NotFound",
   "status": "Failed"
}

若要执行不同的异常处理模式,可以使用本文中前面所述的表达式。 可以选择在范围外部执行单个异常处理操作,此操作接受经过筛选的整个失败数组,并删除 For_each 操作。 如前面所述,还可以包含 \@result() 响应中其他有用的属性。

设置 Azure Monitor 日志

上述模式非常适用于处理在运行中发生的错误和异常。 不过也可以标识和响应独立于运行而发生的错误。 要评估运行状态,可以监视运行的日志和指标,或将它们发布到你习惯使用的任何监视工具中。

例如,Azure Monitor 提供了一种简便的方式,可将所有工作流事件(包括所有运行和操作状态)发送到目标。 可以在 Azure Monitor 中为特定指标和阈值设置警报。 还可以将工作流事件发送到 Log Analytics 工作区Azure 存储帐户。 或者,可以通过 Azure 事件中心将所有事件流式传输到 Azure 流分析。 在流分析中,可以根据诊断日志中的任何异常、平均值或失败编写实时查询。 可以使用流分析将信息发送到其他数据源,例如队列、主题、SQL、Azure Cosmos DB 或 Power BI。

有关详细信息,请参阅为 Azure 逻辑应用设置 Azure Monitor 日志并收集诊断数据