systemd를 사용하는 다중 대기열 아키텍처

systemd를 사용하는 다중 대기열 아키텍처

장기간 실행되는 파일 처리를 수행하는 서비스가 있는데, 이 서비스에는 한 번에 한 번만 사용할 수 있는 처리용 특정 리소스가 필요합니다.

사용자는 낮에는 리소스가 필요할 수 있지만 밤에는 그렇지 않을 수 있습니다. 낮 동안 그는 같은 일을 하거나 다른 일을 하는 데 그것을 사용할 수 있었습니다.

사용자는 또한 밤에 처리할 파일 목록을 가지고 있으며 언제든지 이러한 파일을 대기열 폴더에 추가할 수 있으며 밤에 처리됩니다.

이를 달성하기 위해 나는 다음을 수행합니다.

폴더 구조:

.
├── IN  # user add files to be processed here
├── QUEUE  # files that will be processed
├── PROCESSING  # queue of size <= 1, contains the file being processed
├── OUT  # when files have been processed, the service move them here

제공하다:

# sync QUEUE with IN (possibly with --delete or not)
sync.service  
# pick the oldest file from QUEUE and copy it to PROCESSING
pick_one.service  
# process the file in PROCESSING, 
# remove it from IN, QUEUE and PROCESSING when completed and move it to OUT
processing.service

경로 단위:

sync.path   # should trigger on each modification of IN folder
pick_one.path  # should trigger while QUEUE is not empty and only when PROCESSING is
processing.path  # should trigger whem a file is present in PROCESSING

시간제 노동자:

start.timer  # trigger sync.path and pick_one.path using a target ommitted here 
stop.timer  # stop sync.path and pick_one.path using a target ommitted here

IN이 시스템을 사용하면 사용자가 밤에 처리될 파일을 언제든지 작업할 수 있기를 바랍니다 . 나는 사용자가 파일을 삭제할 수 있는지 여부와 여전히 중개자를 사용하고 파일을 IN처리할 수 있는지 여부를 유연하게 선택할 수 있습니다 . 사용자가 원하는 파일을 폴더에 넣기만 하면 작업할 수 있도록 낮에도 계속 실행됩니다.QUEUEsync.serviceprocessing.pathPROCESSING

문제는 이를 달성하기 위해 경로 단위에서 필요한 옵션을 찾을 수 없다는 것입니다. 수정 사항을 모니터링할 수 없거나 IN완료를 기다리는 루프를 통해 일괄 처리를 피할 수 없는 것 같습니다. 내가 맞나요?QUEUEwhile QUEUE not emptytune.servicewhile PROCESSING not empty

나는 이 솔루션의 유연성을 좋아하지만 너무 복잡하게 만들 수도 있고, 내가 시도하는 것처럼 순수 시스템으로는 불가능할 수도 있습니다.

나보다 프로포즈하는 더 좋은 방법이 있는 사람이 있나요?

감사해요

추신: 필요하다고 생각하시면 유닛 파일의 내용을 게시할 수 있지만, 너무 길지 않게 최대한 명확하게 게시하려고 노력하고 있습니다.

답변1

여기서 첫 번째 언급은 "복사", "동기화"(rsync?) 및 "--delete"(이로 인해 rsync에 대해 더 생각하게 됨)라는 용어를 사용하는 것을 봤다는 것입니다. 반면에 대기열의 올바른 구현은 서비스입니다. 설명하는 것이 문제가 되어야 합니다원자성각 대기열의 파일 수입니다.

큐 프로세서에 의해 관리되는 IN, PROCESSING및 가 있다고 가정하면 원자 시스템 호출을 사용해야 합니다.OUT이름 바꾸기(2)그리고링크(2)(예: "하드 링크") 여러 대기열 간에 파일을 이동하거나 복사/복사합니다.

또 다른 문제는 파일을 대기열에 수집하는 것입니다. 대기열에 쓰는 프로세스는 작업이 IN완료된 후에만 디렉터리에 넣도록 해야 합니다. 그렇지 않으면 원자성 문제가 다시 발생하게 됩니다(큐 프로세서가 항목을 쓰는 프로세스보다 빠르면 비어 있는 파일을 찾을 수 있음). 작성자가 내용을 채울 시간을 가질 때까지).

TMP이 문제에 대한 해결책은 대기열 시스템에서 모니터링하지 않지만 작성자가 새 항목을 보관하는 데 사용하는 추가 디렉터리(예: )를 갖는 것입니다 . 작성자는 거기에 새 파일을 만들고 내용으로 채우고 파일을 닫은 다음 사용합니다.이름 바꾸기(2)또는링크(2)IN이를 대기열 로 이동 하고 대기열 프로세서에서 픽업할 수 있도록 합니다.

두 개의 별도 대기열을 원한다는 것을 잘 이해하지 못합니다 IN. QUEUE아마도 제가 언급한 것과 비슷한 아이디어일 것입니다 TMP. 하지만 두 대기열 간에 항목을 이동하는 백그라운드 서비스에 대해 이야기하셨는데, 초점은 TMP프로세스와 동기적으로 항목을 제출하는 데 있습니다. 이는 해결해야 할 원자성 문제이기 때문입니다.

INsystemd 서비스와 관련하여 전체 대기열을 실행하고, 그 안에 있는 항목을 선택하고 , 일시적으로 여기로 이동하고, PROCESSING작업이 완료되면 최종적으로 덤프하는 단일 systemd 서비스로 작업을 수행할 수 있는 것 같습니다 .OUT

대기열 작업의 처리 시간과 작업을 시작할 수 있는 속도에 따라(대기 시간에 전혀 신경을 쓰는 경우) IN대기열 프로세서가 유휴 상태일 때 디렉터리를 주기적으로 폴링하는 것과 같은 매우 간단한 작업으로 시작하는 것만으로도 충분할 수 있습니다. 대기열이 비어 있을 때 5초 또는 60초마다 폴링한 다음 작업이 완료되자마자 다시 폴링을 시작할 수 있습니다. 따라서 대기열이 사용 중인 경우 작업은 계속 실행됩니다.

예, 다음과 같은 것을 사용하세요inotify더 효율적일 수 있지만 실제로는 대기열이 비어 있을 때만 가능합니다. 대기열이 가득 차면 작업이 계속해서 실행되기 때문입니다. 작업이 완료된 후 거기에서 새 작업을 선택하기 위해 디렉터리를 다시 검색하게 되기 때문입니다(inotify는 실제로는 할 수 없습니다) 도와주세요.)

inotify를 사용하기로 결정한 경우 데몬 자체에서 구현할 수 있으며 계속 실행될 수 있지만 대기열이 비어 있으면 inotify를 등록하고 항목이 배치되면 절전 모드로 전환됩니다. 대기열에서 깨어납니다. 아니면 당신은 사용할 수 있습니다시스템 경로 단위, 이 경우 대기열이 비어 있을 때 서비스를 종료하고 처리할 항목이 있을 때만 systemd에서 서비스를 시작하도록 할 수 있습니다.

어느 쪽이든 inotify를 사용하면 잠재적인 경쟁 조건이 있습니다. 대기열을 스캔하여 비어 있는 것을 발견하고 잠에 들기로 결정했다면 어떻게 될까요? 하지만 이 작업을 수행하기 직전에 새 작업이 대기열에 추가되어 알림이 트리거됩니다. 하지만 잠들기로 결정하기 전에 알림이 도착하므로 여전히 대기열 걷기 모드이므로 알림이 필요하지 않다고 가정하고 무시하시겠습니까? 이로 인해 큐에 항목이 있는 동안 프로세스가 잠자기 상태가 되고 다른 항목이 큐에 들어갈 때까지(또는 경우) 실제로 깨어나지 않습니다.

따라서 inotify를 그림으로 가져오는 것에 대해 두 번 생각해 보십시오(직접 또는 시스템 경로 단위를 통해). 이는 상당한 추가 복잡성을 가져오고 상당히 큰 간격의 쿼리로 수행할 수 있다면 반드시 처리할 필요는 없습니다. .

이 지침이 유용하길 바랍니다!

답변2

다음은 이 문제를 어떻게 해결했는지에 대한 개요입니다. IN 디렉토리의 경로를 사용하여 활성화되고 타이머(밤)로 시작되는 서비스 프로그램을 작성하겠습니다. 서비스 프로그램의 작업은 IN 디렉터리에서 파일을 찾고 발견된 모든 파일을 QUEUE 디렉터리로 이동하는 것입니다.그리고(시간이 맞는다면) 파일 작업을 하나씩 시작하세요. 프로그램은 이 두 작업을 번갈아 수행하거나 별도의 스레드에서 병렬로 완료할 수 있습니다.

이 시스템의 핵심 원칙은 프로그램이 사용 가능한 모든 작업을 수행하고 종료되며, 더 많은 작업(새 파일)이 있을 때 systemd에 의해 시작된다는 것입니다. systemd의 기능은 알람 시계 역할을 하여 수행할 작업이 있을 때 서비스를 깨우는 것입니다. 서비스 자체는 남은 작업량을 확인하고 종료하기 전에 다시 확인해야 합니다.

이 파일 기반 시스템의 한 가지 복잡한 문제를 언급해야 합니다. 파일이 IN 디렉터리에 복사될 때 파일은 여전히 ​​쓰기용으로 열려 있을 수 있으며 심지어 그럴 수도 있습니다. 파일이 디렉터리에 나타나지만 복사 프로세스에서 쓰기가 완료되지 않은 경우 경로 단위가 실행됩니다. 이로 인해 데이터가 손상될 수 있습니다. 파일을 IN 디렉터리로 이동하거나 원자적으로 연결해야 합니다. 그렇지 않으면 복사 프로세스에 의해 파일이 닫힐 때까지 다른 메커니즘을 사용하여 폴링해야 합니다.

관련 정보