Computer >> 컴퓨터 >  >> 프로그래밍 >> Ruby

Solid Queue 마스터하기:Ruby on Rails를 위한 검증된 백그라운드 작업 솔루션

이 시리즈의 이전 기사에서는 백그라운드 작업 처리를 위한 시스템이 필요한 경우 Solid Queue가 탁월한 선택이라는 것을 확인했습니다. 외부 종속성을 최소화합니다. Redis가 필요하지 않습니다! — 모든 작업을 데이터베이스에 저장합니다. 그럼에도 불구하고 놀라운 성능을 발휘합니다.

그러나 단순히 성능을 높이는 것만으로는 프로덕션 준비가 완료된 백그라운드 작업 시스템에 충분하지 않습니다. Rails 개발자들은 수년 동안 많은 것을 기대해 왔습니다. 우리는 작업을 대기열에 추가하여 백그라운드에서 실행되기를 원하지 않습니다. 작업을 예약하고 반복 일정에 따라 실행하며 동시에 실행할 수 있는 작업 수를 제한하고 싶을 수도 있습니다. 우리는 더 많은 기능을 원합니다!

놀랍게도 Solid Queue는 이러한 모든 기능을 즉시 제공합니다. Solid Queue에 대해 더 자세히 알아보고 그것이 어떻게 가능한지 알아보세요!

Ruby on Rails용 Solid Queue를 사용하여 작업 예약

먼저, 간단한 요약을 할 시간입니다. Solid Queue는 데이터베이스와 데이터베이스만 사용하여 작업 데이터를 저장합니다. 그것이 수행하는 모든 것은 하나의 데이터베이스 테이블 또는 다른 데이터베이스 테이블에 의해 뒷받침됩니다. 작업 예약, 즉 미래의 특정 시점에 실행될 작업을 지정하는 것도 다르지 않습니다. 모든 예약된 작업은 solid_queue_scheduled_executions에 저장됩니다. .

 

이 표는 solid_queue_ready_executions과 거의 동일합니다. 테이블. 유일한 차이점은 scheduled_at를 추가한 것입니다. 예약된 작업이 언제 실행되어야 하는지 알려주는 열입니다. 작업을 예약할 때 어떤 일이 발생하는지 살펴봄으로써 이를 확인해 보겠습니다.

 
 

거기에는 놀라움이 없습니다. Solid Queue는 solid_queue_scheduled_executions에 새 행을 추가합니다. 우리가 기대하는 데이터가 포함된 테이블입니다. 하지만 그러한 기록이 존재하는 것에서 적시에 실제로 작업을 실행하게 하려면 어떻게 해야 할까요?

solid_queue_scheduled_executions을 지속적으로 폴링하는 프로세스가 필요합니다. 테이블. 해당 프로세스를 Dispatcher라고 하며 예약된 작업을 제 시간에 실행하는 역할을 담당합니다. Solid Queue가 시작되면 시작됩니다. 추가 구성이 필요하지 않습니다. 그러나 필요한 경우 특정 구성으로 Solid Queue를 실행하여 디스패처 프로세스만 시작할 수 있습니다.

 

Dispatcher 프로세스가 어떻게 감독되는지 궁금하신 경우, 이는 적절한 이름의 Supervisor의 책임입니다. . 작업자 프로세스 및 Dispatcher를 포함하여 Solid Queue 내에서 실행 중인 모든 프로세스를 추적합니다.

그렇다면 Dispatcher는 실제로 어떻게 작동합니까? poll를 정의합니다. 예약된 작업을 지속적으로 확인하기 위해 루프 내에서 호출되는 메서드입니다. 폴링 코드는 여러 클래스와 모듈에 분산되어 있지만 크게 단순화된 형태는 다음과 같습니다:

 

'준비된' 예약된 실행을 검색하는 쿼리는 간단합니다.

 

따라서 scheduled_at가 포함된 모든 예약된 작업은 과거에는 파견될 준비가 되어 있었습니다. 이 시리즈의 1부에서 다룬 것처럼 Solid Queue가 작업을 전달하면 ReadyExecution가 생성됩니다. 해당 ScheduledExecution를 기록하고 파기합니다. 기록. ReadyExecution 그런 다음 일반 작업자 프로세스에서 레코드를 선택하고 해당 작업이 실행됩니다.

지금까지는 너무 좋았습니다. 예정된 작업은 실제로 그렇게 복잡하지 않습니다! 좀 더 복잡한 작업인 반복 작업을 살펴보겠습니다.

반복 작업

반복 작업은 백그라운드 작업 프로세서에 대해 자주 요청되는 기능입니다. 간단히 말해서 반복 일정에 따라 실행되어야 하는 백그라운드 작업입니다. 작업이 수행되어야 하는 일정(예:5분마다, 매일 정오 등)을 정의한다는 점에서 Cron 작업과 유사합니다.

Solid Queue에서는 config/recurring.yml를 사용하여 반복 작업을 구성합니다. 파일. 예를 들어 CleanupData를 실행하려는 경우 매일 정오에 일을 하면 이렇게 할 거예요.

 

Solid Queue는 Fugit을 사용하여 일정 표현식을 구문 분석하므로 '매일 정오'와 같이 사람이 읽을 수 있는 일정이 허용됩니다. 예약된 작업을 사용할 때 실행할 작업 클래스와 작업 인수를 정의합니다. 뛰어난 SolidQueue 반복 작업 ReadMe에 자세한 내용이 나와 있습니다. 우리는 이것이 어떻게 작동하는지 알아보기 위해 왔습니다. 이제 내부를 살펴보겠습니다.

반복되는 작업은 RecurringTask로 표시됩니다. 해당 solid_queue_recurring_tasks가 지원하는 모델 테이블. 그 열은 구성 파일에서 사용할 수 있는 필드에 해당합니다.

 

SolidQueue를 시작하면 반복 작업 구성 파일에 따라 반복 작업 기록이 생성됩니다. 적시에 작업을 생성하려면 다시 한 번 새로운 프로세스가 필요합니다. 이번에는 스케줄러라고 합니다. Scheduler는 우리가 이미 알고 있는 Dispatcher의 형제입니다. 거의 동일한 방식으로 작동합니다. Solid Queue가 시작되면 새 프로세스가 실행되고 이 프로세스는 무한 루프를 실행합니다. Scheduler와 Dispatcher의 차이점은 해당 루프 내에서 발생합니다. Dispatcher가 solid_queue_scheduled_executions를 쿼리하는 위치 테이블에서 스케줄러는 solid_queue_recurring_tasks을 쿼리합니다. — 적시에 작업을 예약합니다. 그렇다면 스케줄러는 적절한 시간과 적절한 작업 일정을 언제 예약해야 하는지 정확히 어떻게 알 수 있을까요?

이 질문에 대답하려면 구현을 면밀히 조사해야 합니다. 스케줄러 클래스는 새로운 RecurringSchedule를 생성합니다. schedule를 정의하는 객체 방법. 해당 메서드는 예약된 각 작업에 대해 반복적으로 호출됩니다. 단순화된 버전은 다음과 같습니다:

 

이 코드를 풀어보겠습니다. Solid Queue는 Concurrent::ScheduledTask를 사용합니다. (동시 Ruby 라이브러리에서) 새 스레드를 생성합니다. 해당 스레드는 반복 작업 일정에 지정된 시간에 실행되도록 예약되어 있습니다. 해당 스레드가 실행되면 먼저 다른 스레드를 재귀적으로 생성하여 다음 반복 작업을 예약합니다. 그런 다음 '현재' 예약된 작업을 대기열에 추가합니다.

일을 처리하기 위해 간단한 반복 작업의 예를 살펴보겠습니다.

 

Solid Queue를 8시 30분에 시작하면 스케줄 메소드 내의 변수에 다음 값이 할당됩니다. 말 그대로는 아닙니다. 여기서는 대폭 단순화하고 있습니다.

따라서 백그라운드 스레드는 지금부터 30분(9시) 실행되도록 예약되어 있습니다. 해당 시간이 지나면 백그라운드 스레드가 실행됩니다. thread_task.enqueue(at: 9:00)을 실행합니다. — CleanupData의 인스턴스 실행 대기 중입니다. 또한 thread_schedule.schedule을 통해 자신을 재귀적으로 호출합니다. . 지금은 9시이므로 이 호출에 대한 변수가 변경되었습니다.

따라서 백그라운드 스레드는 10시에 다시 실행되도록 예약되어 있으며 주기가 계속됩니다. 예를 들어 재배포 또는 시스템 충돌 중에 예약 스레드가 종료되면 어떻게 되는지 궁금할 수 있습니다. 그게 당신의 일정을 방해하지 않을까요? 다행히도 대답은 '아니요'입니다. 크론 일정은 정적입니다. 'Every Hour'와 같은 표현식은 Solid Queue가 시작되는 시간에 관계없이 항상 10:00, 11:00, 12:00 등으로 해석됩니다. 일정 스레드가 중단되더라도 변경되지는 않습니다.

다음은 알아야 할 몇 가지 다른 구현 세부 사항입니다. 첫째, 반복 작업을 실행하기 전에 다음 발생을 예약하는 패턴은 GoodJob에서 영감을 받았습니다. 두 번째, RecurringTask.enqueue 새로운 Job를 생성하지 않습니다. 및 ReadyExecution 예상대로 녹음하세요. 대신 RecurringExecution라는 또 다른 레코드를 생성합니다. .

 

이 기록은 반복 작업이 여러 번 실행되는 것을 방지하기 위한 것입니다. task_key에 색인이 있습니다. 및 run_at 해당 목적을 달성하기 위한 고유한 제약 조건이 있습니다. RecurringTask 이전 RecurringExecution가 없는 경우에만 대기열에 추가됩니다. 같은 시간, 같은 일을 합니다.

 

주의 깊은 독자라면 이 코드 조각이 Solid Queue의 제한 사항을 가리킨다는 것을 알게 될 것입니다. 즉, cron 스타일 작업을 실행하기 위한 백엔드로 Solid Queue를 사용하지 않는 경우(예, 그렇게 할 수 있습니다) Solid Queue는 반복 작업이 한 번만 대기열에 추가되도록 보장할 수 없습니다. 만약 이러한 상황에 처해 계시다면 그 점을 인지하셔야 합니다.

예를 들어 배포 중에 Scheduler 프로세스가 종료되거나 종료되면 어떻게 되는지 궁금할 수도 있습니다. 반복이 스레드에 의해 관리되므로 스레드 중단 일정이 종료되지 않습니까? 다행히도 이에 대한 대답은 '아니오'입니다.

동시성 제어

Solid Queue의 마지막 기능 중 하나인 동시성 제어를 살펴보겠습니다. 때로는 특정 종류의 작업이 동시에 실행될 수 있는 수를 제한하고 싶을 때가 있습니다. limits_concurrency와 함께 Solid Queue를 사용하면 그렇게 할 수 있습니다. .

 

여기서는 SolidQueue에 MyJob의 인스턴스를 최대 1개 실행하도록 지시합니다. 각 사용자마다. 구성을 좀 더 자세히 살펴보겠습니다.

  • to :동시에 실행하려는 최대 작업 수.
  • key :함께 제한해야 하는 작업을 지정하는 필수 인수입니다. 이 예에서 동일한 사용자 ID를 가진 작업은 단일 동시 실행으로 제한됩니다. 모든 작업 인수를 key으로 사용할 수 있습니다. , 그러나 문자열이나 기호와 같은 상수도 허용됩니다.
  • duration :작업이 대기열에 추가된 후 Solid Queue가 동시성을 보장할 수 있는 최대 시간입니다. 작업이 그보다 오래 실행되면 동시성 제어가 적용되지 않고 작업이 겹칠 수 있습니다. 그 이유는 나중에 알아보겠습니다!
  • group :이 옵션을 사용하면 다양한 작업 클래스에 걸쳐 동시성을 제한할 수 있습니다.

더 자세히 알고 싶다면 동시성 제어 문서를 참조하세요. 동시성 제어는 Solid Queue의 가장 정교한 기능입니다. 예약된 작업이 아직 머리를 어지럽히지 않았다면 이 기능이 어떻게 작동하는지 확실히 배우십시오.

기본부터 시작해 보겠습니다. 다른 Solid Queue 기능과 마찬가지로 동시성 제어는 다양한 모델과 해당 데이터베이스 테이블을 통해 지원됩니다. 특히 주의해야 할 두 가지는 Semaphore입니다. 그리고 BlockedExecution .

 

Semaphore를 살펴보겠습니다. 먼저. 이름에서 알 수 있듯이 이는 카운팅 세마포어 패턴을 구현한 것입니다. Solid Queue가 limits_concurrency로 작업을 대기열에 추가할 때마다 , 먼저 동시성 키를 기반으로 세마포어 잠금을 획득하려고 시도합니다. 이 동시성 키는 limits_concurrency에 전달된 인수를 기반으로 합니다. , 즉 작업 클래스, 키 및 그룹 이름(제공된 경우)입니다. 세마포어를 사용할 수 있으면 작업이 대기열에 추가됩니다. 그렇지 않은 경우 BlockedExecution 대신 기록이 생성됩니다.

세마포에는 value이 있습니다. 여러 동시 작업을 지원합니다. 세마포어의 남은 용량이라고 생각하시면 됩니다. 세마포어를 획득한다는 것은 해당 값을 감소시키는 것을 의미하고, 해제한다는 것은 값을 증가시키는 것을 의미합니다. 값이 0이면 세마포어를 사용할 수 없는 것으로 간주됩니다. 간단한 작업에서 잠금 메커니즘이 어떻게 작동하는지 예를 살펴보겠습니다.

 

이 작업을 연속해서 여러 번 대기열에 추가하려고 하면 어떤 일이 발생하는지 살펴보겠습니다.

  1. MyJob의 첫 번째 인스턴스 대기열에 추가됩니다. 아직 세마포어가 없으므로 생성됩니다. 초기값은 limit - 1입니다. . 제한이 3이므로 세마포어의 초기 값은 2입니다.
  2. MyJob의 두 번째 인스턴스 대기열에 추가됩니다. Solid Queue는 해당 작업에 대한 잠금을 획득하려고 시도합니다. 값이 0보다 큰 2이므로 작업이 대기열에 포함될 수 있습니다. 세마포어의 값은 1로 감소합니다.
  3. 작업의 세 번째 인스턴스가 대기열에 추가되었습니다. 이전과 동일한 절차를 반복합니다. 이제 세마포어의 값은 0입니다.
  4. MyJob의 네 번째 인스턴스 대기열에 추가됩니다. 이제 해당 값이 0이므로 세마포어 획득이 실패합니다. BlockedExecution 해당 작업에 대한 기록이 생성됩니다.
  5. 작업의 첫 번째 인스턴스가 완료됩니다. 완료되면 세마포어를 해제하므로 세마포어 값은 다시 한번 1이 됩니다.
  6. 완료 시 첫 번째 작업 인스턴스는 차단된 작업을 해제하는 메서드도 호출합니다.
  7. MyJob의 네 번째 인스턴스 해제되고 다시 잠금을 획득하려고 시도합니다. 세마포어 값은 1이므로 잠금을 획득하고 차단된 작업을 대기열에 넣을 수 있습니다. 이제 세마포어 값은 0입니다.

작업이 완료되면 세마포어를 해제하는 코드는 간단합니다.

 

아직 다루지 않은 세부 사항이 하나 더 있습니다. 세마포어에 만료 날짜가 있는 이유는 무엇이며 limits_concurrency를 사용할 때 기간을 설정해야 하는 이유는 무엇입니까? ?

작업이 세마포어를 해제하지 않고 충돌할 때 어떤 일이 발생하는지 생각해 보겠습니다. 예를 들어 해당 작업을 처리하는 작업자가 종료되는 경우입니다. 세마포어를 정리하는 메커니즘을 추가하지 않는 한 해당 작업이 보유한 잠금은 영원히 유지됩니다. 최악의 경우 다른 작업이 영원히 처리되지 못하게 됩니다.

세마포에는 해당 상황을 피하기 위해 작업 정의에 지정된 기간에 해당하는 만료가 있습니다. 대기열에 추가된 작업이 없는 경우 세마포어가 만료되면 세마포어가 삭제됩니다. 우리는 이를 담당하는 프로세스를 이미 알고 있습니다. 바로 우리의 친구인 Dispatcher입니다. . ConcurrencyMaintenance를 인스턴스화합니다. 두 가지 작업을 수행하는 클래스:

  • 먼저 만료된 세마포어를 제거합니다.
  • 두 번째로 차단된 작업이 있는지 확인하고 해제합니다.

작업은 하나씩 해제되므로 동시성 제한은 계속 유지됩니다. 그러나 작업이 지정된 기간보다 오래 실행되면 어떻게 되는지 생각해 보세요. 이 경우 작업은 계속 실행되지만 세마포어는 정리됩니다. 그런 다음 다른 작업이 대기열에 추가되면 해당 작업이 중복됩니다.

AppSignal을 사용하여 Rails용 Solid Queue 모니터링

우리가 확립한 대로 Solid Queue는 많은 일을 할 수 있습니다. 그러나 이러한 모든 움직이는 부품으로 인해 모니터링이 중요해집니다. 다행히 AppSignal은 작업 실행 시간, 처리량 및 실패율에 대한 기성 대시보드와 함께 Solid Queue에 대한 기본 지원을 제공합니다. Rails 애플리케이션에 AppSignal을 설치하기만 하면 됩니다.

AppSignal은 Solid Queue의 사용량을 자동으로 감지하고 오류율 및 처리량과 같은 중요한 지표에 대한 그래프가 포함된 활성 작업 대시보드를 생성합니다.

Solid Queue 마스터하기:Ruby on Rails를 위한 검증된 백그라운드 작업 솔루션

느리게 실행되거나 오류가 너무 많아 오작동하는 작업을 발견한 경우 해당 작업에 상태와 담당자를 할당하여 문제를 효과적으로 해결하세요.

Solid Queue 마스터하기:Ruby on Rails를 위한 검증된 백그라운드 작업 솔루션

분명히, 문제가 있는지 파악하기 위해 하루 종일 대시보드를 볼 필요는 없습니다. AppSignal Alerts가 여러분을 도와드립니다. 실패율, 작업 기간 등 작업 지표에 대한 새 알림을 만들기만 하면 모든 준비가 완료됩니다.

Solid Queue 마스터하기:Ruby on Rails를 위한 검증된 백그라운드 작업 솔루션

Solid Queue는 번거로움 없이 애플리케이션에 강력한 작업 처리 기능을 추가하는 놀라운 도구입니다. AppSignal은 모니터링에 있어서도 동일한 작업을 수행합니다!

마무리

우리는 Solid Queue의 고급 기능을 탐색하면서 많은 내용을 다루었습니다. 예약된 작업부터 복잡한 종속성 체인에 이르기까지 각 기능은 1부에서 논의한 견고한 기반을 기반으로 구축됩니다. 지금까지 살펴본 것처럼 작업 처리 백엔드를 구축하는 것은 쉽지 않습니다. 하지만 Solid Queue 소스 코드와 그 작동 방식을 자세히 살펴봄으로써 우리는 관련된 과제에 대해 어느 정도 이해하고 감사하게 되었습니다.

어떤 경우든 Solid Queue는 탁월한 데이터베이스 설계 및 프로세스 조정으로 인해 Rails 생태계에 추가된 훌륭한 제품입니다. 외부 종속성 없이 단순성과 안정성이라는 핵심 약속을 유지하면서 필요한 도구를 제공합니다.

즐거운 코딩 되세요!