处理 Azure 逻辑应用中的限制问题(429 -“请求过多”错误)Handle throttling problems (429 - "Too many requests" errors) in Azure Logic Apps

Azure 逻辑应用中,当遇到限制问题时,逻辑应用会返回“HTTP 429 请求过多”错误。如果在特定的时间内,请求数超过了目标可以处理的速率,则会发生此错误。In Azure Logic Apps, your logic app returns an "HTTP 429 Too many requests" error when experiencing throttling, which happens when the number of requests exceed the rate at which the destination can handle over a specific amount of time. 限制可能会造成各种问题,例如,数据处理延迟、性能速度下降,以及超过指定的重试策略等错误。Throttling can create problems such as delayed data processing, reduced performance speed, and errors such as exceeding the specified retry policy.

SQL Server 连接器中的限制

下面是逻辑应用可能会遇到的一些常见限制类型:Here are some common types of throttling that your logic app might experience:

逻辑应用限制Logic app throttling

Azure 逻辑应用服务具有自身的吞吐量限制The Azure Logic Apps service has its own throughput limits. 因此,如果逻辑应用超过这些限制,则逻辑应用资源(而不仅仅是特定的实例或运行)将受到限制。So, if your logic app exceeds these limits, your logic app resource gets throttled, not just a specific instance or run.

若要在此级别查找限制事件,请在 Azure 门户中检查逻辑应用的“指标”窗格。To find throttling events at this level, check your logic app's Metrics pane in the Azure portal.

  1. Azure 门户的逻辑应用设计器中打开逻辑应用。In the Azure portal, open your logic app in the Logic App Designer.

  2. 在逻辑应用菜单中,在“监视”下,选择“指标”。 On the logic app menu, under Monitoring, select Metrics.

  3. 在“图表标题”下,选择“添加指标”,以便向现有指标中添加另一个指标。 Under Chart Title, select Add Metric so that you add another metric to the existing.

  4. 在第一个指标栏中,从“指标”列表中选择“操作受限制事件”。 In the first metric bar, from the METRIC list, select Action Throttled Events. 在第二个指标栏中,从“指标”列表中选择“触发器受限制事件”。 In the second metric bar, from the METRIC list, select Trigger Throttled Events.

若要处理在此级别发生的限制,可以使用以下选项:To handle throttling at this level, you have these options:

  • 限制可以同时运行的逻辑应用实例数。Limit the number of logic app instances that can run at the same time.

    默认情况下,如果同时满足逻辑应用的触发条件多次,则会并发或并行运行逻辑应用的多个触发器实例。By default, if your logic app's trigger condition is met more than once at the same time, multiple trigger instances for your logic app run concurrently or in parallel. 此行为意味着,每个触发器实例会在上一个工作流实例完成运行之前激发。This behavior means that each trigger instance fires before the preceding workflow instance finishes running.

    尽管可以并发运行的默认触发器实例数没有限制,但可以通过启用触发器的并发性设置来限制此数目;如果需要,可选择一个不同于默认值的限制。Although the default number of trigger instances that can concurrently run is unlimited, you can limit this number by turning on the trigger's concurrency setting, and if necessary, select a limit other than the default value.

  • 启用高吞吐量模式。Enable high throughput mode.

    逻辑应用在 5 分钟滚动时间间隔内可运行的操作数目存在默认限制A logic app has a default limit for the number of actions that can run over a 5-minute rolling interval. 若要将此限制提高到最大操作数目,请在逻辑应用中启用高吞吐量模式To raise this limit to the maximum number of actions, turn on high throughput mode on your logic app.

  • 在触发器中禁用数组解批(“拆分”)行为。Disable array debatching ("split on") behavior in triggers.

    如果触发器返回了要处理的剩余工作流操作数组,则触发器的拆分设置会拆分数组项,并针对每个数组项启动一个工作流实例,从而有效触发多个并发运行(不超过拆分限制)。If a trigger returns an array for the remaining workflow actions to process, the trigger's Split On setting splits up the array items and starts a workflow instance for each array item, effectively triggering multiple concurrent runs up to the Split On limit. 若要控制限制,请禁用拆分行为,让逻辑应用通过单个调用处理整个数组,而不是每个调用处理一个项。To control throttling, turn off the Split On behavior and have your logic app process the entire array with a single call, rather than handle a single item per call.

  • 将操作重构为更小的逻辑应用。Refactor actions into smaller logic apps.

    如前所述,逻辑应用在 5 分钟期限内可运行的操作数目存在默认限制As mentioned earlier, a logic app is limited to a default number of actions that can run over a 5-minute period. 虽然可以通过启用高吞吐量模式来提高此限制,但也可以考虑是否要将逻辑应用的操作分解为更小的逻辑应用,使每个逻辑应用中运行的操作数目不会超过限制。Although you can increase this limit by enabling high throughput mode, you might also consider whether you want to break down your logic app's actions into smaller logic apps so that the number of actions that run in each logic app remains under the limit. 这样,便可以减轻单个逻辑应用的资源负担,并跨多个逻辑应用分配负载。That way, you reduce the burden on a single logic app resource and distribute the load across multiple logic apps. 此解决方案更适合那些处理大型数据集的操作,或者那些启动了许多并发运行操作、循环迭代或每个循环迭代中的操作以至于超出操作执行限制的操作。This solution works better for actions that handle large data sets or spin up so many concurrently running actions, loop iterations, or actions inside each loop iteration that they exceed action execution limit.

    例如,此逻辑应用会执行从 SQL Server 数据库中获取表所需的所有工作,并会从每个表中获取行。For example, this logic app does all the work to get tables from a SQL Server database and gets the rows from each table. For each 循环以并发方式遍历每个表,使 Get rows 操作返回每个表的行。The For each loop concurrently iterates through each table so that the Get rows action returns the rows for each table. 这些操作可能会超出操作执行限制,具体取决于这些表中的数据量。Based on the amounts of data in those tables, these actions might exceed the limit on action executions.

    重构前的逻辑应用

    重构之后,该逻辑应用现在成了一个父子逻辑应用。After refactoring, the logic app is now a parent and child logic app. 父级从 SQL Server 中获取表,然后针对每个表调用子逻辑应用来获取行:The parent gets the tables from SQL Server and then calls a child logic app for each table to get the rows:

    为一个操作创建逻辑应用

    下面是父逻辑应用调用的用以获取每个表的行的子逻辑应用:Here's the child logic app that's called by the parent logic app to get the rows for each table:

    为另一个操作创建另一个逻辑应用

连接器限制Connector throttling

每个连接器具有自身的限制,可以在连接器的技术参考页上找到这些限制。Each connector has its own throttling limits, which you can find on the connector's technical reference page. 例如,Azure 服务总线连接器的限制为每分钟最多允许 6000 次调用,而 SQL Server 连接器的限制因操作类型而异For example, the Azure Service Bus connector has a throttling limit that permits up to 6,000 calls per minute, while the SQL Server connector has throttling limits that vary based on the operation type.

某些触发器和操作(例如 HTTP)具有“重试策略”,可以根据重试策略限制对该策略进行自定义以实现异常处理。Some triggers and actions, such as HTTP, have a "retry policy" that you can customize based on the retry policy limits to implement exception handling. 此策略指定当原始请求失败或超时并生成 408、429 或 5xx 响应时,触发器或操作是否以及以何频率重试请求。This policy specifies whether and how often a trigger or action retries a request when the original request fails or times out and results in a 408, 429, or 5xx response. 因此,当限制开始并返回了 429 错误时,逻辑应用在受支持的情况下将遵循重试策略。So, when throttling starts and returns a 429 error, Logic Apps follows the retry policy where supported.

若要了解触发器或操作是否支持重试策略,请检查该触发器或操作的设置。To learn whether a trigger or action supports retry policies, check the trigger or action's settings. 若要查看触发器或操作的重试尝试,请转到逻辑应用的运行历史记录,选择要查看的运行,然后展开该触发器或操作以查看有关输入、输出和任何重试的详细信息,例如:To view a trigger or action's retry attempts, go to your logic app's runs history, select the run that you want to review, and expand that trigger or action to view details about inputs, outputs, and any retries, for example:

查看操作的运行历史记录、重试、输入和输出

尽管重试历史记录提供了有关错误的信息,但在区分连接器限制和目标限制时可能会遇到麻烦。Although the retry history provides error information, you might have trouble differentiating between connector throttling and destination throttling. 在这种情况下,可能必须查看响应的详细信息,或执行一些限制间隔计算来确定来源。In this case, you might have to review the response's details or perform some throttling interval calculations to identify the source.

对于全局多租户 Azure 逻辑应用服务中的逻辑应用,限制是在连接级别发生的。For logic apps in the global, multi-tenant Azure Logic Apps service, throttling happens at the connection level.

若要处理在此级别发生的限制,可以使用以下选项:To handle throttling at this level, you have these options:

  • 为单个操作设置多个连接,使逻辑应用对要处理的数据进行分区。Set up multiple connections for a single action so that the logic app partitions the data for processing.

    对于此选项,请考虑是否可以通过以下方式来分配工作负荷:使用相同的凭据将操作的请求划分到与同一目标建立的多个连接。For this option, consider whether you can distribute the workload by dividing an action's requests across multiple connections to the same destination using the same credentials.

    例如,假设逻辑应用从某个 SQL Server 数据库中获取表,然后从每个表中获取行。For example, suppose that your logic app gets tables from a SQL Server database and then gets the rows from each table. 根据需要处理的行数,可以使用多个连接和多个 For each 循环将总行数划分为较小的集进行处理。Based on the number of rows that you have to process, you can use multiple connections and multiple For each loops to divide the total number of rows into smaller sets for processing. 此方案使用两个 For each 循环将总行数划分为两半。This scenario uses two For each loops to split the total number of rows in half. 第一个 For each 循环使用一个表达式来获取前半部分。The first For each loop uses an expression that gets the first half. 另一个 For each 循环使用另一个表达式获取后半部分,例如:The other For each loop uses a different expression that gets the second half, for example:

    • 表达式 1:take() 函数获取集合开头的项。Expression 1: The take() function gets the front of a collection. 有关详细信息,请参阅 take() 函数For more information, see the take() function.

      @take(collection-or-array-name, div(length(collection-or-array-name), 2))

    • 表达式 2:skip() 函数删除集合开头的项并返回所有其他项。Expression 2: The skip() function removes the front of a collection and returns all the other items. 有关详细信息,请参阅 skip() 函数For more information, see the skip() function.

      @skip(collection-or-array-name, div(length(collection-or-array-name), 2))

    下面是一个演示如何使用这些表达式的直观示例:Here's a visual example that shows how you can use these expressions:

    为单个操作创建和使用多个连接

  • 为每个操作设置不同的连接。Set up a different connection for each action.

    对于此选项,请考虑是否可以通过以下方式分配工作负荷:通过每个操作的请求自身的连接来分散这些请求,即使操作连接到同一服务或系统并使用相同的凭据。For this option, consider whether you can distribute the workload by spreading each action's requests over their own connection, even when actions connect to the same service or system and use the same credentials.

    例如,假设逻辑应用从某个 SQL Server 数据库中获取表,并获取每个表中的行。For example, suppose that your logic app gets the tables from a SQL Server database and gets each row in each table. 可以使用不同的连接,以便在获取表时使用一个连接,获取每个行时使用另一个连接。You can use separate connections so that the getting the tables use one connection, while the getting each row uses another connection.

    为每个操作创建并使用不同的连接

  • 更改“For each”循环中的并发度或并行度。Change the concurrency or parallelism on a "For each" loop.

    默认情况下,“For each”循环迭代会同时运行,但不超过并发限制By default, "For each" loop iterations run at the same time up to the concurrency limit. 如果连接器在“For each”循环内部受到限制,你可以减少并行运行的循环迭代数。If you have a connector that's getting throttled inside a "For each" loop, you can reduce the number of loop iterations that run in parallel. 有关详细信息,请参阅以下主题:For more information, see these topics:

目标服务或系统限制Destination service or system throttling

连接器存在自身的限制,同时,该连接器调用的目标服务或系统也可能存在限制。While a connector has its own throttling limits, the destination service or system that's called by the connector might also have throttling limits. 例如,Microsoft Exchange Server 中某些 API 的限制比 Office 365 Outlook 连接器的限制更严格。For example, some APIs in Microsoft Exchange Server have stricter throttling limits than the Office 365 Outlook connector.

默认情况下,逻辑应用的实例以及这些实例中的任何循环或分支将会并行运行。By default, a logic app's instances and any loops or branches inside those instances, run in parallel. 此行为意味着,多个实例可以同时调用同一个终结点。This behavior means that multiple instances can call the same endpoint at the same time. 每个实例不知道其他实例是否存在,因此重试失败的操作可能会造成争用状况,在这种情况下,多个调用尝试会同时运行,但若要成功,这些调用必须在开始发生限制之前抵达目标服务或系统。Each instance doesn't know about the other's existence, so attempts to retry failed actions can create race conditions where multiple calls try to run at same time, but to succeed, those calls must arrive at the destination service or system before throttling starts to happen.

例如,假设你的某个数组包含 100 个项。For example, suppose you have an array that has 100 items. 你使用“for each”循环来迭代该数组并启用循环的并发控制,以便可以将并行迭代数限制为 20 或当前默认限制You use a "for each" loop to iterate through the array and turn on the loop's concurrency control so that you can restrict the number of parallel iterations to 20 or the current default limit. 在该循环中,某个操作将数组中的某个项插入 SQL Server 数据库,此时每秒只允许 15 次调用。Inside that loop, an action inserts an item from the array into a SQL Server database, which permits only 15 calls per second. 这种情况会导致限制问题,因为重试会不断积压,而永远不会运行。This scenario results in a throttling problem because a backlog of retries build up and never get to run.

下表描述了当操作的重试间隔为 1 秒时,循环中发生的情况的时间线:This table describes the timeline for what happens in the loop when the action's retry interval is 1 second:

时间点Point in time 运行的操作数目Number of actions that run 失败的操作数目Number of actions that fail 等待的重试次数Number of retries waiting
T + 0 秒T + 0 seconds 20 次插入20 inserts 5 个操作由于 SQL 限制而失败5 fail, due to SQL limit 5 次重试5 retries
T + 0.5 秒T + 0.5 seconds 由于前 5 次重试处于等待状态而产生了 15 次插入15 inserts, due to previous 5 retries waiting 所有 15 个操作由于前面的 SQL 限制保持生效 0.5 秒而失败All 15 fail, due to previous SQL limit still in effect for another 0.5 seconds 20 次重试20 retries
(前 5 次 + 15 次新重试)(previous 5 + 15 new)
T + 1 秒T + 1 second 20 次插入20 inserts 5 次加上前 20 次重试由于 SQL 限制而失败5 fail plus previous 20 retries, due to SQL limit 25 次重试(前 20 次 + 5 次新重试)25 retries (previous 20 + 5 new)

若要处理在此级别发生的限制,可以使用以下选项:To handle throttling at this level, you have these options:

  • 创建逻辑应用,让每个逻辑应用处理一个操作。Create logic apps so that each handles a single operation.

    • 沿用本部分中的示例 SQL Server 方案。可以创建一个逻辑应用,用于将数组项放入队列(例如 Azure 服务总线队列)。Continuing with the example SQL Server scenario in this section, you can create a logic app that puts array items into a queue, such as an Azure Service Bus queue. 然后,创建另一个逻辑应用,用于仅对该队列中的每个项执行插入操作。You then create another logic app that performs only the insert operation for each item in that queue. 这样,在任意特定时间只会运行一个逻辑应用实例,该实例完成插入操作并转到队列中的下一项;或者,该实例会收到 429 错误,但不会毫无意义地进行重试。That way, only one logic app instance runs at any specific time, which either completes the insert operation and moves on to the next item in the queue, or the instance gets 429 errors but doesn't attempt unproductive retries.

    • 创建一个父逻辑应用,用于对每个操作调用子逻辑应用或嵌套的逻辑应用。Create a parent logic app that calls a child or nested logic app for each action. 如果父级需要根据其结果调用不同的子应用,则你可以使用条件操作或开关操作来确定要调用哪个子应用。If the parent needs to call different child apps based on the parent's outcome, you can use a condition action or switch action that determines which child app to call. 此模式可帮助减少调用或操作的数目。This pattern can help you reduce the number of calls or operations.

      例如,假设你有两个逻辑应用,每个应用通过一个轮询触发器每隔一分钟检查电子邮件帐户中的特定主题(例如“成功”或“失败”)。For example, suppose that you have two logic apps, each with a polling trigger that checks your email account every minute for specific subject, such as "Success" or "Failure". 此设置会导致每小时发出 120 次调用。This setup results in 120 calls per hour. 如果创建单个父逻辑应用,该应用每隔一分钟轮询一次,但会调用根据主题是“成功”还是“失败”运行的子逻辑应用,则你可以将轮询检查次数减少一半(在本例中为 60 次)。Instead, if you create a single parent logic app that polls every minute but calls a child logic app that runs based whether the subject is "Success" or "Failure", you cut the number of polling checks to half, or 60 in this case.

  • 设置批处理。Set up batch processing.

    如果目标服务支持批处理操作,则你可以通过按组或按批对各个项进行处理(而不是逐个处理)来解决限制。If the destination service supports batch operations, you can address throttling by processing items in groups or batches, rather than individually. 若要实现批处理解决方案,请创建一个“批接收器”逻辑应用和一个“批发送器”逻辑应用。To implement the batch processing solution, you create a "batch receiver" logic app and a "batch sender" logic app. 批发送器不断收集消息或项,直到满足指定的条件,然后将这些消息或项发送到单个组中。The batch sender collects messages or items until your specified criteria is met, and then sends those messages or items in a single group. 批接收器接受该组,并处理这些消息或项。The batch receiver accepts that group and processes those messages or items. 有关详细信息,请参阅按组对消息进行批处理For more information, see Batch process messages in groups.

  • 请使用触发器和操作的 Webhook 版本,而不是轮询版本。Use the webhook versions for triggers and actions, rather than the polling versions.

    为什么?Why? 轮询触发器按特定的间隔持续检查目标服务或系统。A polling trigger continues to check the destination service or system at specific intervals. 非常频繁的间隔(例如每秒)可能会造成限制问题。A very frequent interval, such as every second, can create throttling problems. 但是,Webhook 触发器或操作(例如 HTTP Webhook)只会针对目标服务或系统创建单个调用,该调用是在订阅时发生的,并请求目标仅在发生事件时才通知触发器或操作。However, a webhook trigger or action, such as HTTP Webhook, creates only a single call to the destination service or system, which happens at subscription time and requests that the destination notifies the trigger or action only when an event happens. 这样,触发器或操作就没有必要持续检查目标。That way, the trigger or action doesn't have to continually check the destination.

    因此,如果目标服务或系统支持 Webhook 或提供了使用 Webhook 版本的连接器,则此选项比使用轮询版本更好。So, if the destination service or system supports webhooks or provides a connector that has a webhook version, this option is better than using the polling version. 可以通过以下方法识别 Webhook 触发器和操作:它们具有 ApiConnectionWebhook 类型,它们也不要求指定重复周期。To identify webhook triggers and actions, confirm that they have the ApiConnectionWebhook type or that they don't require that you specify a recurrence. 有关详细信息,请参阅 APIConnectionWebhook 触发器APIConnectionWebhook 操作For more information, see APIConnectionWebhook trigger and APIConnectionWebhook action.

后续步骤Next steps