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

在测试 GitLab 实例中生成混沌

正如亚马逊网络服务(AWS)CTO Werner Vogels 的名言所说,一切都会失败,时时刻刻都在失败

作为开发者,考虑软件可能出现的故障模式与考虑正常运行模式同样重要。这样做可能意味着,要么是少数用户遇到零散的 500 错误这种小故障,要么是影响所有用户长时间的网站完全瘫痪,两者之间有天壤之别。

套用 托尔斯泰 的说法,所有正常的服务器都一样,但所有故障的服务器各有各的故障方式。幸运的是,我们有办法尝试模拟这些故障模式,而混沌端点就是协助这一过程的工具。

目前,有四个端点用于模拟以下条件:

  • 慢速请求。
  • CPU 密集型请求。
  • 内存泄漏。
  • 意外的进程崩溃。

启用混沌端点

出于显而易见的原因,这些端点在 production 环境中默认不启用。 它们在 development 环境中默认启用。

您必须使用密钥令牌来保护对混沌端点的访问。 除非您完全清楚自己在做什么,否则不应在生产环境中启用它们。

可以通过 GITLAB_CHAOS_SECRET 环境变量设置密钥令牌。 例如,使用 GDK 时, 可以通过以下命令实现:

GITLAB_CHAOS_SECRET=secret gdk start

secret 替换为您自己的密钥令牌。

调用混沌

启用混沌端点并重启应用程序后,您就可以开始使用这些端点进行测试。

默认情况下,调用混沌端点时,接收请求的 web worker 进程会处理它。这意味着,例如,如果调用了 Kill 操作,处理请求的 Puma worker 进程就会被终止。要在 Sidekiq 中测试这些操作,可以将每个端点的 async 参数设置为 true。这会在 Sidekiq worker 中运行混沌进程。

内存泄漏

要模拟应用程序中的内存泄漏,请使用 /-/chaos/leakmem 端点。

请求完成后,内存不会被保留。请求完成后,Ruby 垃圾回收器会尝试回收这些内存。

GET /-/chaos/leakmem
GET /-/chaos/leakmem?memory_mb=1024
GET /-/chaos/leakmem?memory_mb=1024&duration_s=50
GET /-/chaos/leakmem?memory_mb=1024&duration_s=50&async=true
属性 类型 必需 描述
memory_mb integer 应泄漏多少内存,单位为 MB。默认为 100 MB。
duration_s integer 内存应保留的最小持续时间,单位为秒。默认为 30 秒。
async boolean 设置为 true 以在 Sidekiq 后台 worker 进程中泄漏内存
curl "http://localhost:3000/-/chaos/leakmem?memory_mb=1024&duration_s=10" \
     --header 'X-Chaos-Secret: secret'
curl "http://localhost:3000/-/chaos/leakmem?memory_mb=1024&duration_s=10&token=secret"

CPU 旋转

此端点尝试在给定时间内完全使用单个核心,使用率为 100%。

根据您的 rack 服务器设置,您的请求可能在预定时间后超时(通常为 60 秒)。

GET /-/chaos/cpu_spin
GET /-/chaos/cpu_spin?duration_s=50
GET /-/chaos/cpu_spin?duration_s=50&async=true
属性 类型 必需 描述
duration_s integer 核心被使用的持续时间,单位为秒。默认为 30 秒
async boolean 设置为 true 以在 Sidekiq 后台 worker 进程中消耗 CPU
curl "http://localhost:3000/-/chaos/cpu_spin?duration_s=60" \
     --header 'X-Chaos-Secret: secret'
curl "http://localhost:3000/-/chaos/cpu_spin?duration_s=60&token=secret"

DB 旋转

此端点尝试在给定时间内完全使用单个核心,并交错执行 DB 请求。 此端点可用于模拟并发运行时将执行权让渡给其他线程的情况。

根据您的 rack 服务器设置,您的请求可能在预定时间后超时(通常为 60 秒)。

GET /-/chaos/db_spin
GET /-/chaos/db_spin?duration_s=50
GET /-/chaos/db_spin?duration_s=50&async=true
属性 类型 必需 描述
interval_s float 每次 DB 请求的间隔时间,单位为秒。默认为 1 秒
duration_s integer 核心被使用的持续时间,单位为秒。默认为 30 秒
async boolean 设置为 true 以在 Sidekiq 后台 worker 进程中执行操作
curl "http://localhost:3000/-/chaos/db_spin?interval_s=1&duration_s=60" \
     --header 'X-Chaos-Secret: secret'
curl "http://localhost:3000/-/chaos/db_spin?interval_s=1&duration_s=60&token=secret"

休眠

此端点类似于 CPU Spin 端点,但模拟的是处理器外部的活动,例如对后端服务的网络调用。它会休眠指定的 duration_s 时间。

与 CPU Spin 端点一样,如果 duration_s 超过配置的限制,这可能导致您的请求超时。

GET /-/chaos/sleep
GET /-/chaos/sleep?duration_s=50
GET /-/chaos/sleep?duration_s=50&async=true
属性 类型 必需 描述
duration_s integer 请求休眠的持续时间,单位为秒。默认为 30 秒
async boolean 设置为 true 以在 Sidekiq 后台 worker 进程中休眠
curl "http://localhost:3000/-/chaos/sleep?duration_s=60" \
     --header 'X-Chaos-Secret: secret'
curl "http://localhost:3000/-/chaos/sleep?duration_s=60&token=secret"

终止

此端点使用 KILL 信号模拟 worker 进程的意外终止。

由于此端点使用 KILL 信号,进程没有机会进行清理或关闭。

GET /-/chaos/kill
GET /-/chaos/kill?async=true
属性 类型 必需 描述
async boolean 设置为 true 以向 Sidekiq 后台 worker 进程发送信号
curl "http://localhost:3000/-/chaos/kill" --header 'X-Chaos-Secret: secret'
curl "http://localhost:3000/-/chaos/kill?token=secret"

退出

此端点使用 QUIT 信号模拟 worker 进程的意外终止。 与 KILL 不同,QUIT 信号还会尝试写入核心转储。 更多信息请参见 core(5)

GET /-/chaos/quit
GET /-/chaos/quit?async=true
属性 类型 必需 描述
async boolean 设置为 true 以向 Sidekiq 后台 worker 进程发送信号
curl "http://localhost:3000/-/chaos/quit" --header 'X-Chaos-Secret: secret'
curl "http://localhost:3000/-/chaos/quit?token=secret"

运行垃圾回收器

此端点触发处理请求的 worker 上的 GC 运行,并返回其 worker ID 和 GC 统计信息作为 JSON。这在独立模式下运行 Puma 时特别有用,因为否则无法预先知道处理请求的 worker。

端点:

POST /-/chaos/gc

示例请求:

curl --request POST "http://localhost:3000/-/chaos/gc" \
     --header 'X-Chaos-Secret: secret'
curl --request POST "http://localhost:3000/-/chaos/gc?token=secret"

示例响应:

{
  "worker_id": "puma_1",
  "gc_stat": {
    "count": 94,
    "heap_allocated_pages": 9077,
    "heap_sorted_length": 9077,
    "heap_allocatable_pages": 0,
    "heap_available_slots": 3699720,
    "heap_live_slots": 2827510,
    "heap_free_slots": 872210,
    "heap_final_slots": 0,
    "heap_marked_slots": 2827509,
    "heap_eden_pages": 9077,
    "heap_tomb_pages": 0,
    "total_allocated_pages": 9077,
    "total_freed_pages": 0,
    "total_allocated_objects": 14229357,
    "total_freed_objects": 11401847,
    "malloc_increase_bytes": 8192,
    "malloc_increase_bytes_limit": 30949538,
    "minor_gc_count": 71,
    "major_gc_count": 23,
    "compact_count": 0,
    "remembered_wb_unprotected_objects": 41685,
    "remembered_wb_unprotected_objects_limit": 83370,
    "old_objects": 2617806,
    "old_objects_limit": 5235612,
    "oldmalloc_increase_bytes": 8192,
    "oldmalloc_increase_bytes_limit": 122713697
  }
}