Help us learn about your current experience with the documentation. Take the survey.

分布式追踪开发指南

GitLab 已配置分布式追踪功能。GitLab 的分布式追踪目前仍被视为实验性功能,因为它尚未在 GitLab.com 上进行大规模测试。

根据 Open Tracing

分布式追踪(也称为分布式请求追踪)是一种用于分析和监控应用程序的方法,特别是那些使用微服务架构构建的应用程序。分布式追踪有助于精确定位故障发生的位置以及导致性能不佳的原因。

分布式追踪对于理解请求在 GitLab 应用程序不同组件间传递的生命周期特别有帮助。目前,Workhorse、Rails、Sidekiq 和 Gitaly 支持追踪 instrumentation。

分布式追踪在禁用时几乎不产生开销,启用时也只会带来很小的开销,因此在任何环境中都能胜任,包括生产环境。因此,它可以用于诊断生产环境中的问题,特别是性能问题。

不同服务对分布式追踪的支持程度不同。除了为最常用的库提供预构建的 instrumentation 外,还必须在应用程序层添加自定义的 instrumentation 代码。

有关特定服务的信息,请参阅:

使用关联 ID 调查分布式请求

GitLab 应用程序在请求的各个组件之间传递关联 ID。关联 ID 是一个令牌,对单个请求唯一,用于在不同 GitLab 子系统(例如 Rails、Workhorse)之间关联单个请求。由于关联 ID 包含在日志输出中,工程师可以使用关联 ID 来关联来自不同子系统的日志,并更好地理解请求通过系统的端到端路径。当请求跨越进程边界时,关联 ID 会被注入到传出请求中。这使得关联 ID 能够传播到每个下游子系统。

关联 ID 通常在 Rails 应用程序中响应某些 Web 请求时生成。一些面向用户的系统不会在响应用户请求时生成关联 ID(例如通过 SSH 的 Git 推送)。

处理关联 ID 的开发者指南

在将追踪集成到新系统时,开发者应避免对关联 ID 做出某些假设。以下指南适用于 GitLab 的所有子系统:

  • 关联 ID 始终是可选的。
    • 切勿让非追踪功能依赖于上游系统提供的关联 ID 的存在。
  • 关联 ID 始终是自由文本。
    • 关联 ID 永远不应用于传递上下文(例如用户名或 IP 地址)。
    • 关联 ID 永远不应被解析或以其他方式操作(例如分割)。

LabKit 库 为在 Go 编程语言中处理 GitLab 关联 ID 提供了标准化接口。LabKit 可作为开发者在非 Go GitLab 子系统中处理追踪和关联 ID 的参考实现。

启用分布式追踪

GitLab 使用 GITLAB_TRACING 环境变量来配置分布式追踪。所有组件(例如 Workhorse、Rails 等)使用相同的配置。

当未设置 GITLAB_TRACING 时,应用程序不会被 instrumented,这意味着完全没有开销。

要启用 GITLAB_TRACING,应设置一个有效的_“configuration-string”_值,其格式类似于 URL:

GITLAB_TRACING=opentracing://<driver>?<param_name>=<param_value>&<param_name_2>=<param_value_2>

在此示例中,我们有以下假设值:

  • driver:驱动程序,例如 Jaeger。
  • param_name, param_value:这些是驱动程序特定的配置值。Jaeger 的配置参数在本文档的后续部分中有文档说明,它们应该进行 URL 编码。多个值应像 URL 一样用 & 字符分隔。

GitLab Rails 为常见类型的操作提供了预实现的 instrumentations,这些操作提供了请求的详细视图。然而,详细信息是有代价的。生成的追踪记录很长,可能难以处理,这使得识别更大的潜在问题变得困难。为了解决这个问题,一些 instrumentations 默认被禁用。要启用这些被禁用的 instrumentations,请设置以下环境变量:

  • GITLAB_TRACING_TRACK_CACHES:启用缓存操作跟踪,例如缓存读取、写入或删除。
  • GITLAB_TRACING_TRACK_REDIS:启用 Redis 操作跟踪。不过,大多数 Redis 操作都是用于缓存的。

在 GitLab Development Kit 中使用 Jaeger

GitLab 支持的第一个追踪实现是 Jaeger,GitLab Development Kit 开箱即用地支持使用 Jaeger 进行分布式追踪。GDK 会自动添加 GITLAB_TRACING 环境变量来添加服务。

通过编辑 gdk.yml 文件并添加以下设置来为 GDK 配置 Jaeger:

tracer:
  build_tags: tracer_static tracer_static_jaeger
  jaeger:
    enabled: true
    listen_address: 127.0.0.1
    version: 1.66.0

修改 gdk.yml 文件后,通过运行 gdk reconfigure 命令重新配置您的 GDK。这确保您的 GDK 已正确配置并可以投入使用。

上述配置在首次重建用 Go 编写的服务时设置 tracer_statictracer_static_jaeger build tags。之后所做的任何更改都需要使用这些 build tags 重新构建它们。您可以:

  • 将这些 build tags 添加到默认的 build tags 集合中。
  • 手动将它们附加到构建命令中。例如,Gitaly 开箱即用地支持添加 build tag。您可以运行 make all WITH_BUNDLED_GIT=YesPlease BUILD_TAGS="tracer_static tracer_static_jaeger"

重新配置后,Jaeger 仪表板可在 http://localhost:16686 访问。从 GDK 环境访问追踪的另一种方式是通过 performance-bar。在浏览器窗口中键入 p b 即可显示它。

启用性能栏后,在性能栏中选择 Trace 即可进入 Jaeger UI。

Jaeger 搜索 UI 返回对当前请求的 Correlation-ID 的查询。此搜索应返回单个追踪结果。选择此结果会以分层时间线的形式显示追踪的详细信息。

Jaeger Search UI

不使用 GitLab Developer Kit 使用 Jaeger

分布式追踪可以在非 GDK 开发环境以及生产或暂存环境中启用,用于故障排除。目前,此功能是实验性的,目前不支持在生产环境中使用。在第一个版本中,它仅计划用于开发环境中的调试。

Jaeger 追踪可以通过三步过程启用:

  1. 启动 Jaeger
  2. 配置 GITLAB_TRACING 环境变量
  3. 启动 GitLab 应用程序
  4. 在浏览器中访问 Jaeger 搜索 UI

1. 启动 Jaeger

Jaeger 有许多配置选项,但在"all-in-one"模式下启动非常容易,该模式使用内存进行追踪存储(因此是非持久化的)。“all-in-one"模式的主要优势是易于使用。

有关更详细的配置选项,请参阅 Jaeger 文档

使用 Docker

如果您有 Docker,运行 Jaeger all-in-one 的更简单方法是通过 Docker,使用以下命令:

$ docker run \
  --rm \
  -e COLLECTOR_ZIPKIN_HTTP_PORT=9411  \
  -p 5775:5775/udp \
  -p 6831:6831/udp \
  -p 6832:6832/udp \
  -p 5778:5778 \
  -p 16686:16686 \
  -p 14268:14268 \
  -p 9411:9411 \
  jaegertracing/all-in-one:latest

使用 Jaeger 进程

如果没有 Docker,all-in-one 进程仍然很容易设置。

  1. 为您的平台下载 最新的 Jaeger 版本
  2. 解压归档文件并运行 bin/all-in-one 进程。

这应该会以默认的监听端口启动进程。

2. 配置 GITLAB_TRACING 环境变量

Jaeger 运行后,使用适当的配置字符串配置 GITLAB_TRACING 变量。

如果您在同一台主机上运行所有内容,请使用以下值:

export GITLAB_TRACING="opentracing://jaeger?http_endpoint=http%3A%2F%2Flocalhost%3A14268%2Fapi%2Ftraces&sampler=const&sampler_param=1"

此配置字符串使用 Jaeger 驱动程序 opentracing://jaeger,并具有以下选项:

Name Value Description
http_endpoint http://localhost:14268/api/traces 配置 Jaeger 将追踪信息发送到运行在 http://localhost:14268/ 上的 HTTP 端点。或者,可以使用 upd_endpoint
sampler const 配置 Jaeger 使用常量采样器(开启或关闭)。
sampler_param 1 配置 const 采样器对所有追踪进行采样。使用 0 则不采样任何追踪。

其他参数值也是可能的

Name Example Description
udp_endpoint localhost:6831 这是默认值。配置 Jaeger 使用紧凑的 thrift 协议将追踪信息发送到端口 6831 上的 UDP 监听器。使用此协议时,我们在 Jaeger Client for Ruby 中遇到了一些问题。
sampler probabilistic 配置 Jaeger 使用概率随机采样器。采样率由 sampler_param 值配置。
sampler_param 0.01 使用 0.01 的比例配置 probabilistic 采样器随机采样 1% 的追踪。
service_name api 覆盖 Jaeger 后端使用的服务名称。此参数优先于应用程序提供的值。

所有 GitLab 进程的环境变量中都应配置相同的 GITLAB_TRACING 值,包括 Workhorse、Gitaly、Rails 和 Sidekiq。

3. 启动 GitLab 应用程序

GITLAB_TRACING 环境变量导出到所有 GitLab 服务后,启动应用程序。

GITLAB_TRACING 配置正确时,应用程序在启动时会记录以下内容:

13:41:53 gitlab-workhorse.1      | 2019/02/12 13:41:53 Tracing enabled
...
13:41:54 gitaly.1                | 2019/02/12 13:41:54 Tracing enabled
...

如果 GITLAB_TRACING 配置不正确,则会记录以下问题:

13:43:45 gitaly.1                | 2019/02/12 13:43:45 skipping tracing configuration step: tracer: unable to load driver mytracer

默认情况下,GitLab 附带了 Jaeger tracer,但可以在编译时包含其他 tracer。有关如何执行此操作的详细信息包含在 LabKit 追踪文档 中。

如果没有发出任何关于追踪的日志消息,则可能未设置 GITLAB_TRACING 环境变量。

4. 打开 Jaeger 搜索 UI

默认情况下,Jaeger 搜索 UI 可在 http://localhost:16686/search 访问。

不要忘记,您必须通过使用应用程序生成追踪,然后它们才会出现在 Jaeger UI 中。