Thanks to visit codestin.com
Credit goes to docs.github.com

Skip to main content

GraphQL API 的速率限制和查询限制

GitHub GraphQL API 利用限制防止过度或胡乱调用 GitHub 的服务器。

主要速率限制

GraphQL API 为每个查询分配了点数,并且限制了可在特定时间内使用的点数。 此限制有助于防止滥用和拒绝服务攻击,并确保 API 仍可供所有用户使用。

REST API 还具有单独的主要速率限制。 有关详细信息,请参阅“REST API 的速率限制”。

通常,可以根据身份验证方法计算 GraphQL API 的主要速率限制:

  • 对于用户__:每用户每小时 5,000 点。 这包括使用 personal access token 发出的请求,以及由 GitHub App 或 OAuth app 代表授权应用的用户发出的请求。 对于由 GitHub Enterprise Cloud 组织所有的 GitHub App 代表用户发出的请求,速率限制更高,为每小时 10,000 点。 同样,如果你是 GitHub Enterprise Cloud 组织的成员,则对于由 GitHub Enterprise Cloud 组织拥有或批准的 OAuth app 代表你发出的请求,速率限制也更高,为每小时 10,000 点。
  • 对于不在 GitHub Enterprise Cloud 组织上的 GitHub App 安装:每个安装每小时 5,000 点。__ 如果安装的仓库数量超过 20 个,则每仓库每小时另外 50 点。 如果安装仓库的组织拥有超过 20 位用户,则每用户每小时另加 50 点。 速率限制上调的上限为每小时 12,500 点。 用户访问令牌(而不是安装访问令牌)的速率限制由用户的主要速率限制决定。
  • 对于在 GitHub Enterprise Cloud 组织上的 GitHub App 安装:每个安装每小时 10,000 点。__ 用户访问令牌(而不是安装访问令牌)的速率限制由用户的主要速率限制决定。
  • 对于 OAuth apps__:每小时 5,000 点,如果应用由 GitHub Enterprise Cloud 组织拥有,则为每小时 10,000 点。 这仅适用于应用使用其客户端 ID 和客户端密码来请求公开数据时。 对于由 OAuth app 生成的 OAuth 访问令牌,主要速率限制由用户的主要速率限制决定。
  • 对于 GitHub Actions 工作流 中的GITHUB_TOKEN __:每仓库每小时 1,000 点。 对于 GitHub.com 上的企业帐户所属资源的请求,限制为每仓库每小时 15,000 点。

可以按以下章节所述来检查查询的点数值,或计算预期的点数值。 计算点数的公式和速率限制可能随时更改。

检查主要速率限制的状态

可以使用随每个响应一起发送的标头来确定主要速率限制的当前状态。

标头名称说明
x-ratelimit-limit每小时可以使用的最大点数
x-ratelimit-remaining当前速率限制窗口中剩余的点数
x-ratelimit-used当前速率限制窗口中已经使用的点数
x-ratelimit-reset当前速率限制窗口重置的时间,单位为 UTC 纪元秒
x-ratelimit-resource请求计数的速率限制资源。 对于 GraphQL 请求,这将始终为 graphql

还还可以通过查询 rateLimit 对象来检查速率限制。 情况允许时应使用速率限制响应头,而不是使用查询 API 来检查速率限制。

query {
  viewer {
    login
  }
  rateLimit {
    limit
    remaining
    used
    resetAt
  }
}
字段说明
limit每小时可以使用的最大点数
remaining当前速率限制窗口中剩余的点数
used当前速率限制窗口中已经使用的点数
resetAt当前速率限制窗口重置的时间,单位为 UTC 纪元秒

返回查询的点数值

可以通过查询 cost 对象上的 rateLimit 字段来返回查询的点数值:

query {
  viewer {
    login
  }
  rateLimit {
    cost
  }
}

预测查询的点数值

在进行查询之前,还可以大致计算查询的点数值。

  1. 将完成调用中每个独有连接所需的请求数加起来。 假设每个请求都将达到 firstlast 参数限制。
  2. 将计算所得的数字除以 100****,然后将结果四舍五入为最接近的整数,即可获取最终加总点数值。 这一步可使大数字规范化。

注意

对 GraphQL API 的调用的最小点数值为 1****。

下面是一个查询和分数计算示例:

query {
  viewer {
    login
    repositories(first: 100) {
      edges {
        node {
          id

          issues(first: 50) {
            edges {
              node {
                id

                labels(first: 60) {
                  edges {
                    node {
                      id
                      name
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

此查询需要 5,101 个请求才能完成:

  • 虽然我们要返回 100 个存储库,但 API 必须连接到查看器的帐户一次才能获取存储库列表。 因此,存储库的请求 = 1
  • 虽然我们要返回 50 个问题,但 API 必须与 100 个存储库的每个库相连接,才能获取问题列表。 因此,问题请求 = 100
  • 虽然我们要返回 60 个标签,但 API 必须与 5,000 个潜在总问题中的每个问题相连接,才能获取标签列表。 因此,标签请求 = 5,000
  • 总计 = 5,101

除以100,然后四舍五入就得到了查询的最终分数:51

二级费率限制

除了主要速率限制以外,GitHub 还强制执行次要速率限制以阻止滥用,让 API 可供所有用户所使用。

以下情况下可能会遇到次要速率限制:

  • 发出的并发请求过多。 并发请求数量不能超过 100 个。 REST API 和 GraphQL API 都应用此限制。
  • 每分钟向单个终结点发出的请求数过多。 REST API 终结点每分钟允许发出的请求数不超过 900 点,GraphQL API 终结点每分钟允许发出的请求数不过超 2,000 点。 有关点的详细信息,请参阅“计算次要速率限制的点数”。
  • 每分钟发出的请求数过多。 实时每 60 秒允许的 CPU 时间不超过 90 秒。 此 CPU 时间的 60 秒不能超过 GraphQL API。 可以通过衡量 API 请求的总响应时间来大致估算出 CPU 时间。
  • 发出过多的请求,它们在短时间内会消耗过多的计算资源。
  • 短时间内在 GitHub 上创建的内容过多。 一般情况下,每分钟不超过 80 个内容生成请求,允许每小时不超过 500 个内容生成请求。 某些终结点的内容创建限制较低。 内容创建限制包括对 GitHub Web 界面以及 REST API 和 GraphQL API 执行的操作。

上述次要速率限制可能随时更改,恕不另行通知。 可能还会因未公开的原因而遇到次要速率限制。

计算次要速率限制的点数

某些次要速率限制由请求的点值确定。 对于 GraphQL 请求,这些点值与主要速率限制的点值分开来进行计算。

请求
不具有突变的 GraphQL 请求1
具有突变的 GraphQL 请求5
大多数 REST API GETHEADOPTIONS 请求1
大多数 REST API POSTPATCHPUTDELETE 请求5

某些 REST API 终结点具有不公开共享的不同点成本。

超出速率限制

如果超出主要速率限制,响应状态仍将是 200,但会收到错误消息,并且 x-ratelimit-remaining 标头的值将为 0。 应在 x-ratelimit-reset 标头所指定的时间之后,再尝试发出请求。

如果超出次要速率限制,则响应状态将为 200403,并显示一条错误消息,表明超出了了次要速率限制。 如果有 retry-after 响应头,则应先等待数秒,然后再尝试请求。 如果 x-ratelimit-remaining 标头为 0,应在 x-ratelimit-reset 标头所指定的时间(以 UTC 新纪元时间秒为单位)之后,再尝试发出请求。 否则,请在重试之前等待至少一分钟。 如果请求由于次要速率限制而继续失败,请等待呈指数级增加的重试间隔秒数,当达到特定的重试次数之后,将会抛出错误。

如果在受到速率限制的情况下继续发出请求,可能会导致禁止集成。

保持在速率限制范围内

要避免超出速率限制,应在可变请求之间至少暂停 1 秒,并且不要发出并发请求。

此外还应订阅 Webhook 事件,而不是通过轮询 API 来获取数据。 有关详细信息,请参阅“Webhook 文档”。

还可以流式传输审核日志来查看 API 请求。 这有助于排查超出速率限制的集成问题。 有关详细信息,请参阅“流式处理企业审核日志”。

节点限制

若要通过架构验证,所有 GraphQL API 调用都必须满足以下标准:

  • 客户端必须在任何连接上提供 firstlast 参数。
  • firstlast 的值必须在 1-100 以内。
  • 单个调用请求的节点总数不能超过 500,000。

计算调用中的节点

下面两个示例显示如何计算调用中的节点总数。

  1. 简单查询:

    query {
      viewer {
        repositories(first: 50) {
          edges {
            repository:node {
              name
    
              issues(first: 10) {
                totalCount
                edges {
                  node {
                    title
                    bodyHTML
                  }
                }
              }
            }
          }
        }
      }
    }

    计算:

    50         = 50 repositories
     +
    50 x 10  = 500 repository issues
    
                = 550 total nodes
  2. 复杂查询:

    query {
      viewer {
        repositories(first: 50) {
          edges {
            repository:node {
              name
    
              pullRequests(first: 20) {
                edges {
                  pullRequest:node {
                    title
    
                    comments(first: 10) {
                      edges {
                        comment:node {
                          bodyHTML
                        }
                      }
                    }
                  }
                }
              }
    
              issues(first: 20) {
                totalCount
                edges {
                  issue:node {
                    title
                    bodyHTML
    
                    comments(first: 10) {
                      edges {
                        comment:node {
                          bodyHTML
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
    
        followers(first: 10) {
          edges {
            follower:node {
              login
            }
          }
        }
      }
    }

    计算:

    50              = 50 repositories
     +
    50 x 20       = 1,000 pullRequests
     +
    50 x 20 x 10 = 10,000 pullRequest comments
     +
    50 x 20       = 1,000 issues
     +
    50 x 20 x 10 = 10,000 issue comments
     +
    10              = 10 followers
    
                     = 22,060 total nodes

超时

如果 GitHub 花费 10 秒以上的时间处理一个 API 请求,GitHub 将会终止此请求,你将收到一个超时响应和一条报告“We couldn't respond to your request in time”的消息。

GitHub 保留更改超时窗口的权利,以保护 API 的速度和可靠性。

可以在 githubstatus.com 上检查 GraphQL API 的状态,以确定超时是否是由于 API 出现问题而造成的。 也可以尝试简化请求,或者稍后尝试发出请求。 例如,如果要在单个请求中请求大量对象,则可以尝试在多个查询中拆分请求较少的对象。

如果任何 API 请求发生超时,则在接下来的一小时内将从主要速率限制中扣除额外积分,以保护 API 的速度和可靠性。

其他资源限制

为了保护 API 的速度和可靠性,GitHub 还强制实施其他资源限制。 如果 GraphQL 查询占用的资源过多,GitHub 将终止请求并返回部分结果以及指示超出资源限制的错误。

可能超过资源限制的查询示例:

  • 在单个查询中请求数千个对象或深层嵌套关系。
  • 同时在多个连接中使用大型 firstlast 参数。
  • 获取每个对象的大量详细信息,例如每个存储库的所有备注、回应和相关议题。

查询优化策略

  • 限制对象数量:对 firstlast 参数使用较小值,并对结果分页。
  • 减少查询深度:除非必要,否则请避免请求深度嵌套对象。
  • 筛选结果:使用参数筛选数据并仅返回所需内容。
  • 拆分大型查询:将复杂查询拆分为多个更简单的查询。
  • 仅请求必填字段:仅选择所需字段,而不是请求所有可用字段。

通过遵循这些策略,可以降低达到资源限制的可能性,并提高 API 请求的性能和可靠性。