{{< details >}}

  • Tier: 基础版,专业版,旗舰版
  • Offering: 私有化部署

{{< /details >}}

Sidekiq 是极狐GitLab 用来异步运行任务的后台作业处理器。当出现问题时,可能会很难进行故障排除。这些情况往往压力很大,因为生产系统的作业队列可能会填满。当这种情况发生时,用户会注意到,因为新分支可能不会出现,合并请求可能不会更新。以下是一些故障排除步骤,帮助您诊断瓶颈。

极狐GitLab 管理员/用户应考虑与极狐GitLab 支持团队一起处理这些调试步骤,以便我们的团队分析回溯。这可能会揭示极狐GitLab 中的一个错误或必要的改进。

在任何回溯中,要警惕每个线程似乎都在数据库、Redis 中等待或等待获取互斥锁的情况。这可能意味着数据库中存在争用,例如,但要寻找一个与其他线程不同的线程。这个其他线程可能正在使用所有可用的 CPU 或拥有 Ruby 全局解释器锁,从而阻止其他线程继续。

Sidekiq 作业日志参数

某些传递给 Sidekiq 作业的参数默认会被记录。为避免记录敏感信息(例如密码重置令牌),极狐GitLab 为所有工作人员记录数字参数,并对某些特定工作人员进行了覆盖,其中他们的参数不是敏感信息。

日志输出示例:

{"severity":"INFO","time":"2020-06-08T14:37:37.892Z","class":"AdminEmailsWorker","args":["[FILTERED]","[FILTERED]","[FILTERED]"],"retry":3,"queue":"admin_emails","backtrace":true,"jid":"9e35e2674ac7b12d123e13cc","created_at":"2020-06-08T14:37:37.373Z","meta.user":"root","meta.caller_id":"Admin::EmailsController#create","correlation_id":"37D3lArJmT1","uber-trace-id":"2d942cc98cc1b561:6dc94409cfdd4d77:9fbe19bdee865293:1","enqueued_at":"2020-06-08T14:37:37.410Z","pid":65011,"message":"AdminEmailsWorker JID-9e35e2674ac7b12d123e13cc: done: 0.48085 sec","job_status":"done","scheduling_latency_s":0.001012,"redis_calls":9,"redis_duration_s":0.004608,"redis_read_bytes":696,"redis_write_bytes":6141,"duration_s":0.48085,"cpu_s":0.308849,"completed_at":"2020-06-08T14:37:37.892Z","db_duration_s":0.010742}
{"severity":"INFO","time":"2020-06-08T14:37:37.894Z","class":"ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper","wrapped":"ActionMailer::MailDeliveryJob","queue":"mailers","args":["[FILTERED]"],"retry":3,"backtrace":true,"jid":"e47a4f6793d475378432e3c8","created_at":"2020-06-08T14:37:37.884Z","meta.user":"root","meta.caller_id":"AdminEmailsWorker","correlation_id":"37D3lArJmT1","uber-trace-id":"2d942cc98cc1b561:29344de0f966446d:5c3b0e0e1bef987b:1","enqueued_at":"2020-06-08T14:37:37.885Z","pid":65011,"message":"ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper JID-e47a4f6793d475378432e3c8: start","job_status":"start","scheduling_latency_s":0.009473}
{"severity":"INFO","time":"2020-06-08T14:39:50.648Z","class":"NewIssueWorker","args":["455","1"],"retry":3,"queue":"new_issue","backtrace":true,"jid":"a24af71f96fd129ec47f5d1e","created_at":"2020-06-08T14:39:50.643Z","meta.user":"root","meta.project":"h5bp/html5-boilerplate","meta.root_namespace":"h5bp","meta.caller_id":"Projects::IssuesController#create","correlation_id":"f9UCZHqhuP7","uber-trace-id":"28f65730f99f55a3:a5d2b62dec38dffc:48ddd092707fa1b7:1","enqueued_at":"2020-06-08T14:39:50.646Z","pid":65011,"message":"NewIssueWorker JID-a24af71f96fd129ec47f5d1e: start","job_status":"start","scheduling_latency_s":0.001144}

使用 Sidekiq JSON 日志 时,参数日志的最大大小限制为 10 KB 的文本;超过此限制的任何参数都会被丢弃,并替换为一个包含字符串 "..." 的单个参数。

您可以设置 SIDEKIQ_LOG_ARGUMENTS 环境变量0(false)以禁用参数日志记录。

示例:

gitlab_rails['env'] = {"SIDEKIQ_LOG_ARGUMENTS" => "0"}

调查 Sidekiq 队列积压或性能缓慢

慢速 Sidekiq 性能的症状包括合并请求状态更新问题,以及在 CI 流水线开始运行之前的延迟。

潜在原因包括:

  1. 极狐GitLab 实例可能需要更多的 Sidekiq 工作人员。默认情况下,单节点 Linux 软件包安装运行一个工作人员,限制 Sidekiq 作业执行到最多一个 CPU 核心。阅读更多关于运行多个 Sidekiq 工作人员的信息

  2. 实例配置了更多的 Sidekiq 工作人员,但大多数额外的工作人员没有配置运行任何排队的作业。当实例繁忙时,如果工作人员配置的几个月或几年后工作负载发生变化,或者由于极狐GitLab 产品变化,这可能会导致作业积压。

使用以下 Ruby 脚本收集 Sidekiq 工作人员状态的数据。

  1. 创建脚本:

    cat > /var/opt/gitlab/sidekiqcheck.rb <<EOF
    require 'sidekiq/monitor'
    Sidekiq::Monitor::Status.new.display('overview')
    Sidekiq::Monitor::Status.new.display('processes'); nil
    Sidekiq::Monitor::Status.new.display('queues'); nil
    puts "----------- workers ----------- "
    workers = Sidekiq::Workers.new
    workers.each do |_process_id, _thread_id, work|
      pp work
    end
    puts "----------- Queued Jobs ----------- "
    Sidekiq::Queue.all.each do |queue|
      queue.each do |job|
        pp job
      end
    end ;nil
    puts "----------- done! ----------- "
    EOF
    
  2. 执行并捕获输出:

    sudo gitlab-rails runner /var/opt/gitlab/sidekiqcheck.rb > /tmp/sidekiqcheck_$(date '+%Y%m%d-%H:%M').out
    

    如果性能问题是间歇性的:

    • 每五分钟在 cron 作业中运行此操作。将文件写入有足够空间的位置:每个文件至少允许 500 KB。

      cat > /etc/cron.d/sidekiqcheck <<EOF
      */5 * * * *  root  /opt/gitlab/bin/gitlab-rails runner /var/opt/gitlab/sidekiqcheck.rb > /tmp/sidekiqcheck_$(date '+\%Y\%m\%d-\%H:\%M').out 2>&1
      EOF
      
    • 回顾数据以查看问题所在。

  3. 分析输出。以下命令假定您有一个输出文件目录。

    1. grep 'Busy: ' * 显示正在运行多少作业。grep 'Enqueued: ' * 显示该时间的工作积压。

    2. 查看 Sidekiq 在负载下的样本中各个工作人员的繁忙线程数:

      ls | while read f ; do if grep -q 'Enqueued: 0' $f; then :
        else echo $f; egrep 'Busy:|Enqueued:|---- Processes' $f
        grep 'Threads:' $f ; fi
      done | more
      

      示例输出:

      sidekiqcheck_20221024-14:00.out
             Busy: 47
         Enqueued: 363
      ---- Processes (13) ----
        Threads: 30 (0 busy)
        Threads: 30 (0 busy)
        Threads: 30 (0 busy)
        Threads: 30 (0 busy)
        Threads: 23 (0 busy)
        Threads: 30 (0 busy)
        Threads: 30 (0 busy)
        Threads: 30 (0 busy)
        Threads: 30 (0 busy)
        Threads: 30 (0 busy)
        Threads: 30 (0 busy)
        Threads: 30 (24 busy)
        Threads: 30 (23 busy)
      
      • 在这个输出文件中,47 个线程繁忙,积压了 363 个作业。
      • 在 13 个工作进程中,只有两个繁忙。
      • 这表明其他工作人员配置过于具体。
      • 查看完整输出以找出哪个工作人员繁忙。与您的 sidekiq_queues 配置在 gitlab.rb 中进行关联。
      • 过载的单工作人员环境可能如下所示:

        sidekiqcheck_20221024-14:00.out
               Busy: 25
           Enqueued: 363
        ---- Processes (1) ----
          Threads: 25 (25 busy)
        
    3. 查看输出文件的 ---- Queues (xxx) ---- 部分以确定当时排队的作业。

    4. 文件还包括有关 Sidekiq 当时状态的低级详细信息。这可能对于识别工作负载峰值来源有用。

      • ----------- workers ----------- 部分详细介绍了总结中 Busy 计数构成的作业。
      • ----------- Queued Jobs ----------- 部分提供有关排队作业的详细信息。

线程转储

向 Sidekiq 进程 ID 发送 TTIN 信号以在日志文件中输出线程回溯。

kill -TTIN <sidekiq_pid>

/var/log/gitlab/sidekiq/current$GITLAB_HOME/log/sidekiq.log 中查看回溯输出。回溯很长,通常以多个 WARN 级别消息开头。以下是单个线程回溯的示例:

2016-04-13T06:21:20.022Z 31517 TID-orn4urby0 WARN: ActiveRecord::RecordNotFound: Couldn't find Note with 'id'=3375386
2016-04-13T06:21:20.022Z 31517 TID-orn4urby0 WARN: /opt/gitlab/embedded/service/gem/ruby/2.1.0/gems/activerecord-4.2.5.2/lib/active_record/core.rb:155:in `find'
/opt/gitlab/embedded/service/gitlab-rails/app/workers/new_note_worker.rb:7:in `perform'
/opt/gitlab/embedded/service/gem/ruby/2.1.0/gems/sidekiq-4.0.1/lib/sidekiq/processor.rb:150:in `execute_job'
/opt/gitlab/embedded/service/gem/ruby/2.1.0/gems/sidekiq-4.0.1/lib/sidekiq/processor.rb:132:in `block (2 levels) in process'
/opt/gitlab/embedded/service/gem/ruby/2.1.0/gems/sidekiq-4.0.1/lib/sidekiq/middleware/chain.rb:127:in `block in invoke'
/opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/sidekiq_middleware/memory_killer.rb:17:in `call'
/opt/gitlab/embedded/service/gem/ruby/2.1.0/gems/sidekiq-4.0.1/lib/sidekiq/middleware/chain.rb:129:in `block in invoke'
/opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/sidekiq_middleware/arguments_logger.rb:6:in `call'
...

在某些情况下,Sidekiq 可能会挂起并无法响应 TTIN 信号。如果发生这种情况,请转向其他故障排除方法。

使用 rbspy 进行 Ruby 性能分析

rbspy 是一个易于使用且开销低的 Ruby 分析器,可用于创建 Ruby 进程 CPU 使用情况的火焰图风格图表。

使用它无需更改极狐GitLab,并且没有依赖关系。要安装它:

  1. rbspy 发布页面 下载二进制文件。
  2. 使二进制文件可执行。

要对 Sidekiq 工作人员进行一分钟的分析,请运行:

sudo ./rbspy record --pid <sidekiq_pid> --duration 60 --file /tmp/sidekiq_profile.svg

Example rbspy flamegraph

在这个由 rbspy 生成的火焰图示例中,几乎所有 Sidekiq 进程的时间都用于 rev_parse,这是 Rugged 中的一个原生 C 函数。在堆栈中,我们可以看到 rev_parseExpirePipelineCacheWorker 调用。

在容器化环境中,rbspy 需要额外的能力。它至少需要 SYS_PTRACE 能力,否则会因权限被拒绝错误而终止。

{{< tabs >}}

::: TabTitle Kubernetes

securityContext:
  capabilities:
    add:
      - SYS_PTRACE

{{< tab title=”Docker” >}}

docker run --cap-add SYS_PTRACE [...]

{{< /tab >}}

{{< tab title=”Docker Compose” >}}

services:
  ruby_container_name:
    # ...
    cap_add:
      - SYS_PTRACE

{{< /tab >}}

{{< /tabs >}}

使用 perf 进行进程分析

Linux 有一个进程分析工具 perf,当某个进程占用大量 CPU 时非常有帮助。如果您看到高 CPU 使用率并且 Sidekiq 没有响应 TTIN 信号,这是一个不错的下一步。

如果您的系统上没有安装 perf,请使用 apt-getyum 安装它:

# Debian
sudo apt-get install linux-tools

# Ubuntu(可能需要这些额外的内核包)
sudo apt-get install linux-tools-common linux-tools-generic linux-tools-`uname -r`

# Red Hat/CentOS
sudo yum install perf

对 Sidekiq PID 运行 perf

sudo perf record -p <sidekiq_pid>

让它运行 30-60 秒,然后按 Ctrl-C。然后查看 perf 报告:

$ sudo perf report

# 示例输出
Samples: 348K of event 'cycles', Event count (approx.): 280908431073
 97.69%            ruby  nokogiri.so         [.] xmlXPathNodeSetMergeAndClear
  0.18%            ruby  libruby.so.2.1.0    [.] objspace_malloc_increase
  0.12%            ruby  libc-2.12.so        [.] _int_malloc
  0.10%            ruby  libc-2.12.so        [.] _int_free

上面您看到 perf 报告的示例输出。它显示了 97% 的 CPU 花费在 Nokogiri 和 xmlXPathNodeSetMergeAndClear 上。对于这种明显的情况,您应该调查极狐GitLab 中使用 Nokogiri 和 XPath 的作业。结合 TTINgdb 输出以显示发生此情况的相应 Ruby 代码。

GNU 项目调试器 (gdb)

gdb 可以成为调试 Sidekiq 的另一种有效工具。它为您提供了一种更交互的方式来查看每个线程并找出问题所在。

使用 gdb 附加到进程会暂停进程的标准操作(在附加 gdb 时,Sidekiq 不会处理作业)。

首先附加到 Sidekiq PID:

gdb -p <sidekiq_pid>

然后收集所有线程的信息:

info threads

# 示例输出
30 Thread 0x7fe5fbd63700 (LWP 26060) 0x0000003f7cadf113 in poll () from /lib64/libc.so.6
29 Thread 0x7fe5f2b3b700 (LWP 26533) 0x0000003f7ce0b68c in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
28 Thread 0x7fe5f2a3a700 (LWP 26534) 0x0000003f7ce0ba5e in pthread_cond_timedwait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
27 Thread 0x7fe5f2939700 (LWP 26535) 0x0000003f7ce0b68c in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
26 Thread 0x7fe5f2838700 (LWP 26537) 0x0000003f7ce0b68c in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
25 Thread 0x7fe5f2737700 (LWP 26538) 0x0000003f7ce0b68c in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
24 Thread 0x7fe5f2535700 (LWP 26540) 0x0000003f7ce0b68c in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
23 Thread 0x7fe5f2434700 (LWP 26541) 0x0000003f7ce0b68c in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
22 Thread 0x7fe5f2232700 (LWP 26543) 0x0000003f7ce0b68c in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
21 Thread 0x7fe5f2131700 (LWP 26544) 0x00007fe5f7b570f0 in xmlXPathNodeSetMergeAndClear ()
from /opt/gitlab/embedded/service/gem/ruby/2.1.0/gems/nokogiri-1.6.7.2/lib/nokogiri/nokogiri.so
...

如果您看到可疑线程,例如上面的 Nokogiri 线程,您可能希望获取更多信息:

thread 21
bt

# 示例输出
#0  0x00007ff0d6afe111 in xmlXPathNodeSetMergeAndClear () from /opt/gitlab/embedded/service/gem/ruby/2.1.0/gems/nokogiri-1.6.7.2/lib/nokogiri/nokogiri.so
#1  0x00007ff0d6b0b836 in xmlXPathNodeCollectAndTest () from /opt/gitlab/embedded/service/gem/ruby/2.1.0/gems/nokogiri-1.6.7.2/lib/nokogiri/nokogiri.so
#2  0x00007ff0d6b09037 in xmlXPathCompOpEval () from /opt/gitlab/embedded/service/gem/ruby/2.1.0/gems/nokogiri-1.6.7.2/lib/nokogiri/nokogiri.so
#3  0x00007ff0d6b09017 in xmlXPathCompOpEval () from /opt/gitlab/embedded/service/gem/ruby/2.1.0/gems/nokogiri-1.6.7.2/lib/nokogiri/nokogiri.so
#4  0x00007ff0d6b092e0 in xmlXPathCompOpEval () from /opt/gitlab/embedded/service/gem/ruby/2.1.0/gems/nokogiri-1.6.7.2/lib/nokogiri/nokogiri.so
#5  0x00007ff0d6b0bc37 in xmlXPathRunEval () from /opt/gitlab/embedded/service/gem/ruby/2.1.0/gems/nokogiri-1.6.7.2/lib/nokogiri/nokogiri.so
#6  0x00007ff0d6b0be5f in xmlXPathEvalExpression () from /opt/gitlab/embedded/service/gem/ruby/2.1.0/gems/nokogiri-1.6.7.2/lib/nokogiri/nokogiri.so
#7  0x00007ff0d6a97dc3 in evaluate (argc=2, argv=0x1022d058, self=<value optimized out>) at xml_xpath_context.c:221
#8  0x00007ff0daeab0ea in vm_call_cfunc_with_frame (th=0x1022a4f0, reg_cfp=0x1032b810, ci=<value optimized out>) at vm_insnhelper.c:1510

要一次输出所有线程的回溯:

set pagination off
thread apply all bt

完成 gdb 调试后,请确保从进程中分离并退出:

detach
exit

Sidekiq 终止信号

TTIN 在上面被描述为打印回溯以进行日志记录的信号,但 Sidekiq 也响应其他信号。

检查阻塞查询

有时 Sidekiq 处理作业的速度可能会快到导致数据库争用。当回溯显示许多线程卡在数据库适配器中时,请检查阻塞查询。

PostgreSQL 维基提供了您可以运行以查看阻塞查询的查询详细信息。查询因 PostgreSQL 版本而异。

管理 Sidekiq 队列

可以使用 Sidekiq API 在 Sidekiq 上执行许多故障排除步骤。

这些是管理命令,仅在当前管理界面由于安装规模不适合时使用。

所有这些命令都应使用 gitlab-rails console 运行。

查看队列大小

Sidekiq::Queue.new("pipeline_processing:build_queue").size

枚举所有排队的作业

queue = Sidekiq::Queue.new("chaos:chaos_sleep")
queue.each do |job|
  # job.klass # => 'MyWorker'
  # job.args # => [1, 2, 3]
  # job.jid # => jid
  # job.queue # => chaos:chaos_sleep
  # job["retry"] # => 3
  # job.item # => {
  #   "class"=>"Chaos::SleepWorker",
  #   "args"=>[1000],
  #   "retry"=>3,
  #   "queue"=>"chaos:chaos_sleep",
  #   "backtrace"=>true,
  #   "queue_namespace"=>"chaos",
  #   "jid"=>"39bc482b823cceaf07213523",
  #   "created_at"=>1566317076.266069,
  #   "correlation_id"=>"c323b832-a857-4858-b695-672de6f0e1af",
  #   "enqueued_at"=>1566317076.26761},
  # }

  # job.delete if job.jid == 'abcdef1234567890'
end

枚举当前运行的作业

workers = Sidekiq::Workers.new
workers.each do |process_id, thread_id, work|
  # process_id 是每个 Sidekiq 进程的唯一标识符
  # thread_id 是每个线程的唯一标识符
  # work 是一个哈希,类似于:
  # {"queue"=>"chaos:chaos_sleep",
  #  "payload"=>
  #  { "class"=>"Chaos::SleepWorker",
  #    "args"=>[1000],
  #    "retry"=>3,
  #    "queue"=>"chaos:chaos_sleep",
  #    "backtrace"=>true,
  #    "queue_namespace"=>"chaos",
  #    "jid"=>"b2a31e3eac7b1a99ff235869",
  #    "created_at"=>1566316974.9215662,
  #    "correlation_id"=>"e484fb26-7576-45f9-bf21-b99389e1c53c",
  #    "enqueued_at"=>1566316974.9229589},
  #  "run_at"=>1566316974}],
end

删除给定参数的 Sidekiq 作业(破坏性操作)

删除作业的常规方法是以下命令,该命令删除排队但未启动的作业。无法删除正在运行的作业。

queue = Sidekiq::Queue.new('<queue name>')
queue.each { |job| job.delete if <condition>}

查看下面的部分以取消正在运行的作业。

在上述方法中,<queue-name> 是包含您要删除的作业的队列名称,<condition> 决定哪些作业被删除。

通常,<condition> 引用作业参数,具体取决于作业类型。要查找特定队列的参数,可以查看相关工作文件的 perform 函数,通常位于 /app/workers/<queue-name>_worker.rb

例如,repository_import 具有 project_id 作为作业参数,而 update_merge_requests 具有 project_id, user_id, oldrev, newrev, ref

参数需要使用 job.args[<id>] 引用其序列 ID,因为 job.args 是提供给 Sidekiq 作业的所有参数的列表。

以下是一些示例:

queue = Sidekiq::Queue.new('update_merge_requests')
# 在此示例中,我们希望删除项目 ID 为 125 且 ref 为 `ref/heads/my_branch` 的任何 update_merge_requests 作业
queue.each { |job| job.delete if job.args[0] == 125 and job.args[4] == 'ref/heads/my_branch' }
# 取消作业,例如:`RepositoryImportWorker.new.perform_async(100)`
id_list = [100]

queue = Sidekiq::Queue.new('repository_import')
queue.each do |job|
  job.delete if id_list.include?(job.args[0])
end

删除特定作业 ID(破坏性操作)

queue = Sidekiq::Queue.new('repository_import')
queue.each do |job|
  job.delete if job.jid == 'my-job-id'
end

删除特定工作人员的 Sidekiq 作业(破坏性操作)

queue = Sidekiq::Queue.new("default")

queue.each do |job|
  if job.klass == "TodosDestroyer::PrivateFeaturesWorker"
    # 取消注释下面的行以实际删除作业
    #job.delete
    puts "Deleted job ID #{job.jid}"
  end
end

取消正在运行的作业(破坏性操作)

这是一个高风险操作,请作为最后手段使用。这样做可能会导致数据损坏,因为作业在执行过程中被中断,并且无法保证正确回滚事务已实现。

Gitlab::SidekiqDaemon::Monitor.cancel_job('job-id')

这需要 Sidekiq 以 SIDEKIQ_MONITOR_WORKER=1 环境变量运行。

为了执行中断,我们使用 Thread.raise,它有许多缺点,如为什么 Ruby 的 Timeout 是危险的(以及 Thread.raise 是可怕的) 中所述:

这就是影响变得有趣和可怕的地方。这意味着异常可能会在以下情况下引发:

  • 在网络请求期间(可以,只要周围代码准备好捕获 Timeout::Error)
  • 在网络请求的清理过程中
  • 在救援块中
  • 在之后创建对象以保存到数据库
  • 在您的任何代码中,无论之前是否可能引发异常

没有人编写代码来防御在任何行上引发异常。这甚至是不可能的。因此,Thread.raise 基本上就像对您的代码的偷袭,可能会导致几乎任何事情。如果是纯函数代码,没有修改任何状态,那可能还好。但这是 Ruby,因此不太可能 :)

手动触发 cron 作业

通过访问 /admin/background_jobs,您可以查看实例上计划/运行/待处理的作业。

您可以通过选择“立即排队”按钮从 UI 触发 cron 作业。要以编程方式触发 cron 作业,请首先打开 Rails 控制台

要找到您想要测试的 cron 作业:

job = Sidekiq::Cron::Job.find('job-name')

# 获取作业状态:
job.status

# 立即排队作业!
job.enque!

例如,要触发更新存储库镜像的 update_all_mirrors_worker cron 作业:

irb(main):001:0> job = Sidekiq::Cron::Job.find('update_all_mirrors_worker')
=>
#<Sidekiq::Cron::Job:0x00007f147f84a1d0
...
irb(main):002:0> job.status
=> "enabled"
irb(main):003:0> job.enque!
=> 257

可用作业列表可以在 workers 目录中找到。

禁用 cron 作业

您可以通过访问 管理员 区域中的监控部分禁用任何 Sidekiq cron 作业。您也可以使用命令行和 Rails Runner 执行相同的操作。

要禁用所有 cron 作业:

sudo gitlab-rails runner 'Sidekiq::Cron::Job.all.map(&:disable!)'

要启用所有 cron 作业:

sudo gitlab-rails runner 'Sidekiq::Cron::Job.all.map(&:enable!)'

如果您希望一次仅启用一部分作业,可以使用名称匹配。例如,仅启用名称中包含 geo 的作业:

 sudo gitlab-rails runner 'Sidekiq::Cron::Job.all.select{ |j| j.name.match("geo") }.map(&:disable!)'

清除 Sidekiq 作业重复数据消除幂等键

偶尔,预期运行的作业(例如 cron 作业)被观察到根本没有运行。检查日志时,可能会看到作业未运行,状态为 "job_status": "deduplicated"

这可能发生在作业失败且幂等键未正确清除时。例如,停止 Sidekiq 在 25 秒后终止任何剩余作业

默认情况下,键在 6 小时后过期,但如果您想立即清除幂等键,请按照以下步骤(示例提供的是 Geo::VerificationBatchWorker):

  1. 在 Sidekiq 日志中找到作业的工作人员类和 args

    { ... "class":"Geo::VerificationBatchWorker","args":["container_repository"] ... }
    
  2. 启动 Rails 控制台会话
  3. 运行以下代码片段:

    worker_class = Geo::VerificationBatchWorker
    args = ["container_repository"]
    dj = Gitlab::SidekiqMiddleware::DuplicateJobs::DuplicateJob.new({ 'class' => worker_class.name, 'args' => args }, worker_class.queue)
    dj.send(:idempotency_key)
    dj.delete!
    

Sidekiq BRPOP 调用导致的 Redis CPU 饱和

Sidekiq BROP 调用可能导致 Redis 上的 CPU 使用率增加。增加 SIDEKIQ_SEMI_RELIABLE_FETCH_TIMEOUT 环境变量 以改善 Redis 上的 CPU 使用率。

错误:OpenSSL::Cipher::CipherError

如果您收到类似以下的错误消息:

"OpenSSL::Cipher::CipherError","exception.message":"","exception.backtrace":["encryptor (3.0.0) lib/encryptor.rb:98:in `final'","encryptor (3.0.0) lib/encryptor.rb:98:in `crypt'","encryptor (3.0.0) lib/encryptor.rb:49:in `decrypt'"

此错误表示进程无法解密存储在极狐GitLab 数据库中的加密数据。这表明您的 /etc/gitlab/gitlab-secrets.json 文件存在问题,请确保您已将文件从主极狐GitLab 节点复制到 Sidekiq 节点。

相关主题