Sidekiq 문제 해결

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

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

GitLab 관리자/사용자는 GitLab 지원팀과 함께 이러한 디버그 단계를 진행하여 백트레이스를 분석할 수 있도록 고려해야 합니다. 이는 GitLab의 버그나 필요한 개선 사항을 발견할 수 있습니다.

모든 백트레이스에서 모든 스레드가 데이터베이스, Redis에서 대기 중이거나 뮤텍스를 확보하기 위해 대기 중인 경우 의심스러운 상황을 경계해야 합니다. 이는 데이터베이스의 경합을 의미할 수 있지만, 나머지와 다른 하나의 스레드를 찾아보세요. 이 다른 스레드는 모든 사용 가능한 CPU를 사용하는 중이거나 Ruby Global Interpreter Lock을 가지고 있어 다른 스레드가 계속 진행되는 것을 방지할 수 있습니다.

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킬로바이트의 텍스트로 제한됩니다. 이 한도를 초과하는 인수는 폐기되며 단일 인수로 문자열 "..."로 대체됩니다.

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

예제:

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

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분마다 cron 작업으로 이 명령을 실행합니다. 파일을 충분한 공간이 있는 위치에 쓰십시오: 파일당 최소 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명만 바빴습니다.
      • 이는 다른 작업자들이 너무 구체적으로 구성되었음을 나타냅니다.
      • 어떤 작업자가 바빴는지 전체 출력을 살펴보십시오. GitLab의 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 상태인 작업에 대한 세부정보가 제공됩니다.

스레드 덤프

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: 'id'=3375386인 Note를 찾을 수 없습니다
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 신호에 반응하지 않을 수 있습니다. 이런 경우에는 다른 문제 해결 방법으로 넘어가세요.

Ruby 프로파일링 with rbspy

rbspy는 Ruby 프로세스에 의해 CPU 사용량의 플레임 그래프 스타일 다이어그램을 생성하는 데 사용할 수 있는 사용하기 쉬운 저오버헤드 Ruby 프로파일러입니다.

사용하기 위해 GitLab에 변경할 필요가 없으며 의존성도 없습니다. 설치하려면:

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

Sidekiq 작업자를 1분 동안 프로파일링 하려면 다음을 실행하세요:

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

rbspy 플레임 그래프 예제

rbspy에 의해 생성된 플레임 그래프의 예에서, 거의 모든 Sidekiq 프로세스의 시간은 Rugged의 네이티브 C 함수인 rev_parse에서 소비됩니다. 스택에서 rev_parseExpirePipelineCacheWorker에 의해 호출되는 것을 볼 수 있습니다.

rbspy컨테이너화된 환경에서 추가 능력을 요구합니다. 최소한 SYS_PTRACE 권한이 필요하며, 그렇지 않으면 permission denied 오류로 종료됩니다.

::: TabTitle Kubernetes

securityContext:
  capabilities:
    add:
      - SYS_PTRACE
Docker
docker run --cap-add SYS_PTRACE [...]
Docker Compose
services:
  ruby_container_name:
    ...
    cap_add:
      - SYS_PTRACE

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 보고서의 샘플 출력을 확인할 수 있습니다. Nokogiri와 xmlXPathNodeSetMergeAndClear 내부에서 CPU의 97%가 소비되고 있음을 보여줍니다. 이렇게 분명한 경우 GitLab에서 Nokogiri 및 XPath를 사용하는 작업이 무엇인지 조사해야 합니다. TTIN 또는 gdb 출력을 결합하여 이와 관련된 Ruby 코드를 보여주세요.

GNU 프로젝트 디버거 (gdb)

gdb는 Sidekiq 디버깅을 위한 또 다른 효과적인 도구입니다. 각 스레드를 살펴보고 문제를 일으키는 원인을 알아보는 좀 더 대화형 방식입니다.

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 Signals 문서를 참조하세요.

차단 쿼리 확인

때때로 Sidekiq가 작업을 처리하는 속도가 매우 빨라서

데이터베이스 contention을 유발할 수 있습니다.

위의 백트레이스에서 여러 스레드가 데이터베이스 어댑터에

갇혀 있음을 보여주면 차단 쿼리를 확인하세요.

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는 Sidekiq 프로세스당 고유 식별자입니다.
  # thread_id는 스레드당 고유 식별자입니다.
  # work는 다음과 같은 Hash입니다.
  # {"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_requestsproject_id, user_id, oldrev, newrev, ref를 사용합니다.

인수는 job.args[<id>]를 사용하여 순서 ID로 참조해야 합니다. job.args는 Sidekiq 작업에 제공된 모든 인수의 목록이기 때문입니다.

다음은 몇 가지 예입니다:

queue = Sidekiq::Queue.new('update_merge_requests')
# 이 예에서는 Project ID 125에 대한 update_merge_requests 작업을 제거하려고 합니다.
# ref는 `ref/heads/my_branch`입니다.
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::SidekiqDaemon::Monitor.cancel_job('job-id')

이를 수행하려면 SIDEKIQ_MONITOR_WORKER=1 환경 변수를 설정하여 Sidekiq를 실행해야 합니다.

중단을 수행하기 위해 Thread.raise를 사용하며, 이는 여러 가지 단점이 있습니다. Why Ruby’s Timeout is dangerous (and Thread.raise is terrifying)에서 언급된 바와 같습니다:

여기서 상황의 의미가 흥미롭고 무섭게 됩니다. 즉, 다음과 같이 예외가 발생할 수 있습니다:

  • 네트워크 요청 중에 (괜찮습니다. 주변 코드가 Timeout::Error를 잡을 준비가 되어 있는 한)
  • 네트워크 요청을 정리하는 중에
  • rescue 블록에서
  • 이후 데이터베이스에 저장할 객체를 생성하는 중에
  • 당신의 코드에서, 예외가 발생할 수 있는지를 막론하고

아마도 누구도 문자 그대로 모든 줄에서 예외가 발생하는 것을 방어하는 코드를 작성하지 않습니다. 이는 불가능한 일입니다. 따라서 Thread.raise는 코드에 대한 기습 공격과 같아 거의 모든 것을 초래할 수 있습니다. 순수-함수적 코드는 상태를 수정하지 않는 경우 괜찮을 수 있지만, Ruby에서는 그럴 가능성이 낮습니다 :)

수동으로 크론 작업 트리거하기

/admin/background_jobs를 방문하면 인스턴스에서 예약/실행/대기 중인 작업을 확인할 수 있습니다.

UI에서 “Enqueue Now” 버튼을 선택하여 크론 작업을 트리거할 수 있습니다. 프로그램적으로 크론 작업을 트리거하려면 먼저 Rails 콘솔을 엽니다.

테스트할 크론 작업을 찾으려면:

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

# 작업 상태 확인:
job.status

# 지금 바로 작업을 실행!
job.enque!

예를 들어, 저장소 미러를 업데이트하는 update_all_mirrors_worker 크론 작업을 트리거하려면:

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 문서를 참조하세요.

크론 작업 비활성화

관리자 영역의 모니터링 섹션을 방문하여 어떤 Sidekiq 크론 작업도 비활성화할 수 있습니다. 또한 명령줄과 Rails Runner를 사용하여 동일한 작업을 수행할 수 있습니다.

모든 크론 작업을 비활성화하려면:

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

모든 크론 작업을 활성화하려면:

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 작업 중복 제거 아이도포텐시 키 지우기

가끔 크론 작업과 같은 실행될 것으로 예상되는 작업이 전혀 실행되지 않는 경우가 있습니다. 로그를 확인할 때 작업이 "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!
    

Redis의 Sidekiq BRPOP 호출로 인한 CPU 포화

Sidekiq BROP 호출은 Redis에서 CPU 사용량을 증가시킬 수 있습니다.

Redis의 CPU 사용량을 개선하려면 SIDEKIQ_SEMI_RELIABLE_FETCH_TIMEOUT 환경 변수를 증가시키세요.

오류: 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 노드로 복사했는지 확인하세요.

관련 주제