Sidekiq 문제 해결

Tier: Free, Premium, Ultimate Offering: Self-Managed

Sidekiq는 GitLab이 비동기적으로 작업을 실행하는 데 사용하는 백그라운드 작업 프로세서입니다. 문제가 발생하면 문제를 해결하기 어려울 수 있습니다. 또한 이러한 상황은 프로덕션 시스템 작업 대기열이 채워지고 있을 수 있기 때문에 고압적일 수 있습니다. 사용자는 새로운 브랜치가 나타나지 않거나 병합 요청이 업데이트되지 않는 것을 알 수 있습니다. 다음은 병목 현상을 진단하는 데 도움이 되는 몇 가지 문제 해결 단계입니다.

GitLab 관리자/사용자는 GitLab 지원팀과 함께 이러한 디버깅 단계를 거칠 것을 고려해야 합니다. 이를 통해 백트레이스를 분석할 수 있습니다. 이는 GitLab에서 버그나 필요한 개선 사항을 파악할 수 있습니다.

백트레이스 중 어떤 경우에서든 데이터베이스, 레디스에서 대기하거나 뮤텍스를 획들하려고 기다리는 경우에 의심해야 합니다. 이 경우 데이터베이스에서 경합이 발생했을 수 있지만, 나머지와 다른 한 스레드를 찾아야 합니다. 다른 이 스레드는 사용 가능한 모든 CPU를 사용하고 있을 수 있으며 루비 전역 인터프리터 락을 가지고 있어 다른 스레드가 계속되지 못하게 할 수 있습니다.

Sidekiq 작업의 인수 로그

GitLab 13.6 및 이후에서 일부 Sidekiq 작업에 전달된 인수가 기본적으로 로그에 기록됩니다. 민감한 정보(예: 비밀번호 재설정 토큰)를 기록하지 않도록하기 위해 일부 특정한 작업자에 대한 숫자 인수가 로깅됩니다.

예시 로그 출력:

{"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 킬로바이트의 텍스트 크기로 제한됩니다. 이 제한을 초과하는 인수는 폐기되고 “…” 문자열을 포함하는 단일 인수로 대체됩니다.

SIDEKIQ_LOG_ARGUMENTS 환경 변수0(거짓)으로 설정하여 인수 로깅을 비활성화할 수 있습니다.

예시:

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

GitLab 13.5 이전의 경우, Sidekiq에 전달된 인수를 로깅하려면 SIDEKIQ_LOG_ARGUMENTS1로 설정합니다.

Sidekiq 대기열 지연 또는 성능 저하 조사

Sidekiq 성능이 느린 경우에는 병합 요청 상태 업데이트 문제 및 CI 파이프라인이 실행되기 전의 지연이 발생합니다.

잠재적인 원인은 다음과 같습니다:

  • GitLab 인스턴스에서 Sidekiq 워커가 더 필요할 수 있습니다. 기본적으로 단일 노드 Linux 패키지 설치는 하나의 워커를 실행하며, Sidekiq 작업을 최대 하나의 CPU 코어에서 실행합니다. 여러 개의 Sidekiq 워커를 실행하는 방법에 대해 더 알아보기.

  • 인스턴스가 더 많은 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
    

    성능 문제가 간헐적으로 발생하는 경우:

    • 이를 5분마다 크론 작업으로 실행합니다. 파일을 충분한 공간이 있는 위치에 작성하세요. 파일당 최소 500KB의 공간을 확보하세요.

      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개의 워커 프로세스 중 2개만 바쁜 상황입니다.
      • 다른 워커가 너무 구체적으로 구성되어 있는 것을 나타냅니다.
      • sidekiq_queues 구성 파일에서 바쁜 워커를 확인하세요.
      • 과부하된 단일 워커 환경은 다음과 같을 수 있습니다:

        sidekiqcheck_20221024-14:00.out
               Busy: 25
           Enqueued: 363
        ---- Processes (1) ----
          Threads: 25 (25 busy)
        
    3. 출력 파일의 ---- Queues (xxx) ---- 섹션을 살펴보고 해당 시기에 대기 중인 작업을 확인하세요.

    4. 파일에는 그 시기의 Sidekiq 상태에 대한 세부 정보도 포함되어 있습니다. 이는 작업 부하가 어디서 발생하는지 식별하는 데 유용할 수 있습니다.

      • ----------- workers ----------- 섹션은 요약에서 Busy 수를 구성하는 작업에 대한 세부 정보를 제공합니다.
      • ----------- Queued Jobs ----------- 섹션은 Enqueued된 작업에 대한 세부 정보를 제공합니다.

스레드 덤프

TTIN 시그널을 Sidekiq 프로세스 ID에 보내 스레드 백트레이스를 로그 파일에 출력합니다.

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를 사용한 루비 프로파일링

rbspy는 사용하기 쉽고 오버헤드가 낮은 루비 프로파일러로, 루비 프로세스의 CPU 사용량을 flamegraph 스타일 다이어그램으로 만들 수 있습니다.

GitLab에 대한 변경 사항 없이 사용할 수 있으며 의존성이 없습니다. 다음과 같이 설치합니다.

  1. rbspy 릴리스 페이지에서 바이너리를 다운로드합니다.
  2. 바이너리를 실행 가능하도록 만듭니다.

한 분 동안 Sidekiq 워커를 프로파일링하려면 다음을 실행합니다.

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

rbspy flamegraph 예시

rbspy에 의해 생성된 flamegraph 예시에서 거의 모든 Sidekiq 프로세스의 시간이 Rugged의 네이티브 C 함수인 rev_parse에 사용되었습니다. 스택에서 rev_parseExpirePipelineCacheWorker에 의해 호출되는 것을 볼 수 있습니다.

perf를 사용한 프로세스 프로파일링

Linux에는 특정 프로세스가 많은 CPU를 사용할 때 도움이 되는 perf라는 프로세스 프로파일링 도구가 있습니다. 높은 CPU 사용량이 보고되고 Sidekiq가 TTIN 시그널에 응답하지 않는 경우, 이 단계를 진행하세요.

시스템에 perf가 설치되어 있지 않은 경우 apt-get 또는 yum을 사용하여 설치합니다.

# 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 리포트의 샘플 출력입니다. 이를 보면 CPU의 97%가 Nokogiri 및 xmlXPathNodeSetMergeAndClear 내부에서 사용되고 있음을 보여줍니다. 이 정도만큼 명백한 경우 GitLab 작업 중에 Nokogiri 및 XPath를 사용하는 부분을 조사해야 합니다. 이것을 TTIN 또는 gdb 출력과 결합하여 해당하는 루비 코드를 확인하세요.

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 kill signals

TTIN는 백트레이스를 기록하기 위한 신호로 설명되었지만, Sidekiq는 다른 신호에도 응답합니다. 예를 들어 TSTP와 TERM은 Sidekiq를 안전하게 종료하는 데 사용할 수 있습니다. 자세한 내용은 Sidekiq 신호 문서를 참조하십시오.

블로킹 쿼리 확인

가끔 Sidekiq 작업을 처리하는 속도가 너무 빨라 데이터베이스 경합을 일으킬 수 있습니다. 위의 백트레이스에서 많은 스레드가 데이터베이스 어댑터에 갇혀 있는 것으로 나타나면 블로킹 쿼리를 확인하십시오.

PostgreSQL 위키에는 블로킹 쿼리를 확인할 수 있는 쿼리에 대한 세부 정보가 나와 있습니다. 쿼리는 PostgreSQL 버전에 따라 다릅니다. 쿼리 세부 정보는 Lock Monitoring를 참조하십시오.

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 is a unique identifier per Sidekiq process
  # thread_id is a unique identifier per thread
  # work is a Hash which looks like:
  # {"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>은 해당 작업 유형에 따라 달라지는 작업 인수를 참조합니다. 특정 대기열의 인수를 찾으려면 관련된 worker 파일의 perform 함수를 확인할 수 있습니다. 이 파일은 일반적으로 /app/workers/<queue-name>_worker.rb에서 찾을 수 있습니다.

예를 들어, repository_import 작업에는 project_id가 작업 인수로 존재하며, update_merge_requestsproject_id, user_id, oldrev, newrev, ref를 인수로 사용합니다.

인수는 Sidekiq 작업에 제공된 모든 인수 목록인 job.args를 사용하여 순서 ID로 참조해야 합니다.

다음은 몇 가지 예시입니다:

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

실행 중인 작업 취소 (파괴적)

  • GitLab 12.3에서 도입되었습니다.

이것은 매우 위험한 작업이며 최후의 수단으로 사용하십시오. 그것을 수행하는 것은 작업이 실행 중에 중단되어 적절한 트랜잭션 롤백이 구현되지 않을 수 있기 때문에 데이터 손상으로 이어질 수 있습니다.

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

이것은 SIDEKIQ_MONITOR_WORKER=1 환경 변수로 Sidekiq를 실행해야 합니다.

우리는 Thread.raise를 사용하여 중단을 수행합니다. 그러나 이 방법에는 몇 가지 단점이 있습니다. 자세한 내용은 Why Ruby’s Timeout is dangerous (and Thread.raise is terrifying)에서 확인할 수 있습니다.

수동으로 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 디렉토리에서 찾을 수 있습니다.

Sidekiq 작업에 대한 자세한 내용은 Sidekiq-cron 문서를 참조하십시오.

cron 작업 비활성화하기

Sudo gitlab-rails runner와 명령줄을 사용하여 모든 Sidekiq cron 작업을 비활성화할 수 있습니다.

모든 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 로그에서 작업의 worker 클래스 및 args를 찾습니다:
  { ... "class":"Geo::VerificationBatchWorker","args":["container_repository"] ... }
  1. Rails 콘솔 세션을 시작합니다.
  2. 다음 조각을 실행합니다:
  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!

GitLab 14.0 이후: sidekiq-cluster 서비스 제거 (Linux 패키지 설치)

GitLab 14.0 이전에 sidekiq-cluster를 실행하도록 구성된 Linux 패키지 인스턴스는 나중의 릴리스에서sidekiq와 함께 동시에 실행되고 있을 수 있습니다.

sidekiq-cluster를 관리하는 코드는 GitLab 14.0에서 제거되었습니다. 구성 파일은 디스크에 남아 있기 때문에 sidekiq-cluster 프로세스는 계속해서 GitLab systemd 서비스에 의해 시작됩니다.

추가 서비스는 다음과 같이 실행 중인 것으로 확인할 수 있습니다:

  • gitlab-ctl status 명령을 통해 두 서비스를 확인할 수 있습니다.

    run: sidekiq: (pid 1386) 445s; run: log: (pid 1385) 445s
    run: sidekiq-cluster: (pid 1388) 445s; run: log: (pid 1381) 445s
    
  • ps -ef | grep 'runsv sidekiq' 명령을 통해 두 프로세스를 확인할 수 있습니다.

    root     31047 31045  0 13:54 ?        00:00:00 runsv sidekiq-cluster
    root     31054 31045  0 13:54 ?        00:00:00 runsv sidekiq
    

GitLab 14.0 이후를 실행 중인 서버에서 sidekiq-cluster 서비스를 제거하려면:

  1. GitLab과 systemd 서비스를 중지합니다:

    sudo gitlab-ctl stop
    sudo systemctl stop gitlab-runsvdir.service
    
  2. runsv 서비스 정의를 제거합니다:

    sudo rm -rf /opt/gitlab/sv/sidekiq-cluster
    
  3. GitLab을 다시 시작합니다:

    sudo systemctl start gitlab-runsvdir.service
    
  4. 모든 서비스가 실행 중이고 sidekiq-cluster 서비스가 목록에 없는지 확인합니다:

    sudo gitlab-ctl status
    

이 변경으로 Sidekiq가 할 수 있는 작업을 줄일 수 있습니다. 파이프라인을 생성하는 데 지연이 발생하는 증상은 추가 Sidekiq 프로세스가 유익할 수 있음을 나타냅니다. sidekiq-cluster 서비스를 제거하는 대신 추가 Sidekiq 프로세스 추가를 고려하세요.

Sidekiq BRPOP 호출에 의한 Redis CPU 포화

Sidekiq의 BRPOP 호출은 Redis의 CPU 사용량 증가를 유발할 수 있습니다. Redis의 CPU 사용량을 개선하려면 SIDEKIQ_SEMI_RELIABLE_FETCH_TIMEOUT 환경 변수를 늘리세요.

관련 주제