Rails 请求 SLI(服务级别指标)
此 SLI 用于服务监控,但默认不用于阶段组的错误预算。
请求 Apdex SLI 和错误率 SLI 是在应用中定义的 SLIs。
请求 Apdex 将成功请求的持续时间作为应用性能的指标。这包括 REST 和 GraphQL API,以及常规的 controller 端点。
错误率将失败的请求作为服务器异常行为的指标。这包括 REST API,以及常规的 controller 端点。
-
gitlab_sli_rails_request_apdex_total: 这个计数器会在每个未返回5xx状态码响应的请求时递增。它确保慢速失败不会被重复计算,因为该请求已在错误 SLI 中被计入。 -
gitlab_sli_rails_request_apdex_success_total: 这个计数器会在每个成功且执行速度快于根据端点紧急程度定义的目标持续时间的请求时递增。 -
gitlab_sli_rails_request_error_total: 这个计数器会在每个返回5xx状态码响应的请求时递增。 -
gitlab_sli_rails_request_total: 这个计数器会在每个请求时递增。
这些计数器带有以下标签:
-
endpoint_id: Rails Controller 或 Grape-API 端点的标识。 -
feature_category: 为该 controller 或 API 端点指定的功能类别。
请求 Apdex SLO
这些计数器可以组合成成功率。该比率的目标在服务目录中按服务定义。要使此 SLI 满足 SLO,记录的比率必须高于:
例如:对于 web 服务,我们希望至少 99.8% 的请求快于其目标持续时间。
我们使用这些目标进行告警和服务监控。设置持续时间时要考虑这些目标,以免触发告警。然而,目标是设置一个能满足用户需求的紧急程度。
成功的测量和失败的测量都会影响阶段组的错误预算。
调整请求紧急程度
并非所有端点执行相同类型的工作,因此可以为不同端点定义不同的紧急程度。紧急程度较低的端点可以有比高紧急程度端点更长的请求持续时间。
长时间运行的请求对我们的基础设施成本更高。在处理一个请求时,线程会被该请求的持续时间占用。该线程无法处理其他任何请求。由于 Ruby 的全局 VM 锁,该线程可能会保持锁并阻塞由同一 Puma worker 进程处理的其他请求。事实上,该请求对于 worker 处理的其他请求来说是一个"吵闹的邻居"。因此,我们将目标持续时间的上限限制为 5 秒。
降低紧急程度(设置更高的目标持续时间)
您可以针对现有端点逐个降低紧急程度。请考虑以下几点:
-
Apdex 关注的是感知性能。如果用户正在主动等待请求结果,等待 5 秒可能不可接受。但是,如果端点被需要大量数据的自动化使用,5 秒可能是可接受的。
产品经理可以帮助识别端点的使用方式。
-
某些端点的工作量有时会根据调用者指定的参数而有很大差异。紧急程度需要适应这些差异。在某些情况下,您可以为端点执行的操作定义一个单独的应用 SLI。
当某些端点在某些情况下变为无操作时,使其变得非常快,我们在设置目标时应忽略这些快速请求。例如,如果每次查看合并请求都会触发
MergeRequests::DraftsController,但很少渲染任何内容,那么我们应该选择仍然能满足端点执行工作的目标。 -
考虑端点消耗的依赖资源。如果端点从 Gitaly 或数据库加载大量数据,导致性能不佳,请考虑优化数据加载方式,而不是通过降低紧急程度来增加目标持续时间。
在这些情况下,如果基础设施可以承受,可以暂时降低紧急程度以使端点满足 SLO。在这种情况下,创建一个链接到 issue 的代码注释。
如果端点消耗大量 CPU 时间,我们也应该考虑这一点:这类请求是我们应尽可能保持简短的"吵闹的邻居"类型。
-
还应考虑流量特征。如果端点的流量有时会突发,比如 CI 流量启动一批命中同一端点的大量作业,那么从基础设施的角度来看,这些端点耗时 5 秒是不可接受的。我们无法足够快地扩展集群规模来同时处理传入的慢速请求和常规流量。
在降低现有端点的紧急程度时,让可扩展性团队成员参与审查。我们可以使用日志中可用的请求率和持续时间来提出建议。您可以使用与提高紧急程度相同的过程来选择阈值,选择一个高于服务 SLO 的持续时间。
我们不应该在引入端点的合并请求中设置最长的持续时间,因为我们还没有数据来支持这个决定。
提高紧急程度(设置更低的目标持续时间)
在提高紧急程度时,我们必须确保端点仍然满足处理请求的集群的 SLO。您可以使用日志中的信息来检查:
-
表格默认加载最繁忙端点的信息。为了加快响应速度,请同时添加:
-
json.meta.caller_id.keyword的过滤器。 -
您感兴趣的标识符,例如:
Projects::RawController#show或:
GET /api/:version/projects/:id/snippets/:snippet_id/raw
-
-
检查处理该端点的服务的适当百分位持续时间。总体持续时间应低于您的目标。
-
如果总体持续时间低于目标,请检查 Kibana 中此图表随时间变化的峰值。这里,相关的百分位数不应超过我们要设置的目标持续时间。
由于降低阈值过多可能导致 Apdex 降级的告警,因此也让可扩展性团队成员参与合并请求。
如何调整紧急程度
您可以指定紧急程度,类似于端点获取功能类别的方式。没有特定目标的端点使用默认紧急程度:1 秒持续时间。这些配置可用:
| 紧急程度 | 持续时间(秒) | 说明 |
|---|---|---|
:high |
0.25s | |
:medium |
0.5s | |
:default |
1s | 未指定时的默认值。 |
:low |
5s |
Rails controller
可以为 controller 中的所有操作指定紧急程度:
class Boards::ListsController < ApplicationController
urgency :high
end还可以为 controller 中的某些操作指定紧急程度:
class Boards::ListsController < ApplicationController
urgency :high, [:index, :show]
end提供了一个自定义的 RSpec 匹配器,用于在 controller 规范中检查端点的请求紧急程度:
specify do
expect(get(:index, params: request_params)).to have_request_urgency(:medium)
endGrape endpoints
为整个 API 类指定紧急程度:
module API
class Issues < ::API::Base
urgency :low
end
end为 API 类中的某些操作指定紧急程度:
module API
class Issues < ::API::Base
urgency :medium, [
'/groups/:id/issues',
'/groups/:id/issues_statistics'
]
end
end或者,我们可以为每个端点指定紧急程度:
get 'client/features', urgency: :low do
# 端点逻辑
end自定义的 RSpec 匹配器也与 grape 端点的规范兼容:
specify do
expect(get(api('/avatar'), params: { email: 'public@example.com' })).to have_request_urgency(:medium)
end我们不能在命名空间级别指定紧急程度。这样做时该指令会被忽略。
错误预算归属和所有权
此 SLI 用于服务级别监控。它用于阶段组的错误预算。
更多信息,请阅读有关定义自定义 SLI 并将其纳入错误预算的 epic。SLI 的端点根据其上声明的功能类别纳入组的错误预算。
要了解哪些端点包含在您的组中,您可以查看 您组的组仪表板上的请求率。在预算归属行中,Puma Apdex 日志链接向您显示有多少请求未达到 1 秒或 5 秒的目标。
有关仪表板内容的更多信息,请参阅阶段组仪表板。有关我们对错误预算本身的探索的更多信息,请参阅issue 1365。