主要速率限制
GraphQL API 为每个查询分配点数,并限制在特定时间内可使用的点数。此限制可防止滥用和拒绝服务攻击,并确保 API 对所有用户保持可用。
REST API 也有单独的主要速率限制。了解更多信息,请参阅REST API 的速率限制。
通常,您可以根据身份验证方式计算 GraphQL API 的主要速率限制。
- 对于用户:每位用户每小时 5,000 点。此计数包括使用个人访问令牌的请求以及 GitHub App 或 OAuth 应用代表已授权该应用的用户进行的请求。由 GitHub Enterprise Cloud 组织拥有的 GitHub App 代表用户发出的请求拥有更高的速率限制,为每小时 10,000 点。同样,如果您是该 GitHub Enterprise Cloud 组织的成员,由该组织拥有或批准的 OAuth 应用代表您发出的请求也拥有每小时 10,000 点的更高速率限制。
- 对于未在 GitHub Enterprise Cloud 组织中的 GitHub App 安装:每个安装每小时 5,000 点。拥有超过 20 个仓库的安装,每个仓库额外获得 50 点/小时。拥有超过 20 位用户的组织安装,每位用户额外获得 50 点/小时。速率限制最高不能超过每小时 12,500 点。用户访问令牌(相对于安装访问令牌)的速率限制受用户的主要速率限制控制。
- 对于在 GitHub Enterprise Cloud 组织中的 GitHub App 安装:每个安装每小时 10,000 点。用户访问令牌(相对于安装访问令牌)的速率限制受用户的主要速率限制控制。
- 对于 OAuth 应用:每小时 5,000 点;如果该应用归属于 GitHub Enterprise Cloud 组织,则为每小时 10,000 点。仅在应用使用其 client ID 和 client secret 请求公共数据时适用。OAuth 应用生成的访问令牌的速率限制受用户的主要速率限制控制。
- 对于 GitHub Actions 工作流中的
GITHUB_TOKEN:每个仓库每小时 1,000 点。对属于 GitHub.com 企业账户的资源发出的请求,每个仓库每小时上限为 15,000 点。
您可以检查查询的点数值,或按照下面章节所述计算预期的点数值。点数计算公式和速率限制可能会更改。
检查主要速率限制的状态
您可以使用每个响应随带的响应头来确定当前主要速率限制的状态。
| 请求头名称 | 描述 |
|---|---|
x-ratelimit-limit | 每小时可使用的最大点数 |
x-ratelimit-remaining | 当前速率限制窗口中剩余的点数 |
x-ratelimit-used | 当前速率限制窗口中已使用的点数 |
x-ratelimit-reset | 当前速率限制窗口重置的时间(UTC epoch 秒) |
x-ratelimit-resource | 计数请求时所使用的速率限制资源。对于 GraphQL 请求,此值始终为 graphql。 |
您也可以查询 rateLimit 对象来检查速率限制。若可能,请使用速率限制响应头而非查询 API 来检查速率限制。
query {
viewer {
login
}
rateLimit {
limit
remaining
used
resetAt
}
}
| 字段 | 描述 |
|---|---|
限制 | 每小时可使用的最大点数 |
剩余 | 当前速率限制窗口中剩余的点数 |
已使用 | 当前速率限制窗口中已使用的点数 |
resetAt | 当前速率限制窗口重置的时间(UTC epoch 秒) |
返回查询的点数值
您可以通过查询 rateLimit 对象上的 cost 字段来返回查询的点数值。
query {
viewer {
login
}
rateLimit {
cost
}
}
预测查询的点数值
您也可以在发起查询之前大致计算查询的点数值。
- 将调用中每个唯一连接所需的请求次数相加。假设每个请求都达到
first或last参数的上限。 - 将该数字除以 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 条 issue,但 API 必须对每个 **100** 个仓库连接一次以获取 issue 列表。所以,issue 请求数 = 100
- 虽然我们返回了 60 个标签,但 API 必须对每个可能的 **5,000** 条 issue 连接一次以获取标签列表。所以,标签请求数 = 5,000
- 总计 = 5,101
除以 100 并四舍五入后,得到查询的最终分数:51
次要速率限制
除了主要速率限制之外,GitHub 还实施次要速率限制,以防止滥用并保持 API 对所有用户可用。
如果满足以下情况,您可能会遇到次要速率限制:
- 发起过多并发请求。 不可超过 100 个并发请求。此限制在 REST API 与 GraphQL API 之间共享。
- 每分钟对单个端点发出过多请求。 对 REST API 端点每分钟不超过 900 点,对 GraphQL API 端点每分钟不超过 2,000 点。有关点数的更多信息,请参阅次要速率限制的点数计算。
- 每分钟发出过多请求。 每 60 秒真实时间内最多使用 90 秒的 CPU 时间。对 GraphQL API 的 CPU 时间最多不超过 60 秒。您可以通过测量 API 请求的总响应时间来大致估算 CPU 时间。
- 在短时间内发出大量消耗计算资源的请求。
- 在短时间内在 GitHub 上创建过多内容。 通常,每分钟不超过 80 次生成内容的请求,每小时不超过 500 次。某些端点的内容创建限制更低。内容创建限制包括通过 GitHub Web 界面以及 REST API 与 GraphQL API 所执行的操作。
- 在短时间内发出过多 OAuth 访问令牌请求。 对于 GitHub Apps 与 OAuth 应用,每小时不超过 2,000 次 OAuth 访问令牌请求。
这些次要速率限制可在不另行通知的情况下更改。您也可能因未公开的原因而遇到次要速率限制。
计算次要速率限制的点数
某些次要速率限制是根据请求的点数来决定的。对于 GraphQL 请求,这些点数与主要速率限制的点数计算是分开的。
| 请求 | 点数 |
|---|---|
| 无变更的 GraphQL 请求 | 1 |
| 带变更的 GraphQL 请求 | 5 |
大多数 REST API 的 GET、HEAD、OPTIONS 请求 | 1 |
大多数 REST API 的 POST、PATCH、PUT 或 DELETE 请求 | 5 |
某些 REST API 端点拥有不同的点数费用,且未对外公开。
超过速率限制
如果您超过了主要速率限制,响应状态仍为 200,但会收到错误信息,并且 x-ratelimit-remaining 头的值为 0。在 x-ratelimit-reset 头指定的时间之后才应重试请求。
如果您超过了次要速率限制,响应状态可能为 200 或 403,并会收到指示已触发次要速率限制的错误信息。如果响应头中出现 retry-after,则应在该秒数过去后再重试请求。如果 x-ratelimit-remaining 为 0,则应在 x-ratelimit-reset 头指定的 UTC epoch 秒时间之后才重试请求。否则,请至少等待一分钟后再重试。如果请求仍因次要速率限制而失败,请在重试之间逐渐延长间隔时间,并在达到特定重试次数后抛出错误。
在受到速率限制期间继续发出请求可能导致您的集成被封禁。
保持在速率限制以下
为避免超过速率限制,您应在变更请求之间至少暂停 1 秒,并避免并发请求。
您还应订阅 webhook 事件,而不是轮询 API 获取数据。了解更多,请参阅Webhook 文档。
您也可以流式传输审计日志以查看 API 请求。这有助于排查超过速率限制的集成。了解更多,请参阅企业审计日志流式传输。
节点限制
要通过模式验证,所有 GraphQL API 调用必须符合以下标准。
计算调用中的节点数
以下两个示例演示了如何计算一次调用中的总节点数。
-
简单查询
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
-
复杂查询
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 处理 API 请求的时间超过 10 秒,GitHub 将终止该请求并返回超时响应以及“我们未能及时响应您的请求”的提示信息。
GitHub 保留更改超时时间窗口的权利,以保障 API 的速度和可靠性。
您可以在githubstatus.com 查看 GraphQL API 的状态,以判断超时是否由 API 本身的问题导致。您也可以尝试简化请求或稍后再试。例如,如果一次请求中请求了大量对象,可尝试将对象拆分为多个查询请求。
如果您的任意 API 请求出现超时,将在接下来的一小时内从您的主要速率限制中额外扣除点数,以保护 API 的速度和可靠性。
其他资源限制
为保护 API 的速度和可靠性,GitHub 还实施了其他资源限制。如果您的 GraphQL 查询消耗了过多资源,GitHub 将终止请求并返回部分结果,同时返回资源限制已超出的错误信息。
可能超出资源限制的查询示例
- 在单个查询中请求数千个对象或深度嵌套的关系。
- 在多个连接中同时使用大的
first或last参数。 - 为每个对象获取大量详细信息,例如每个仓库的所有评论、响应和相关 issue。
查询优化策略
- 限制对象数量:对
first或last参数使用更小的值,并通过分页获取结果。 - 降低查询深度:除非必要,避免请求深度嵌套的对象。
- 过滤结果:使用参数过滤数据,仅返回所需内容。
- 拆分大查询:将复杂查询拆分为多个更简洁的查询。
- 仅请求所需字段:只选取需要的字段,而不是请求所有可用字段。
遵循这些策略,您可以降低触发资源限制的概率,并提升 API 请求的性能与可靠性。