셀러리 작업 미리 가져 오기 이해


79

방금 구성 옵션 CELERYD_PREFETCH_MULTIPLIER( docs ) 에 대해 알아 냈습니다 . 기본값은 4이지만 (나는 믿습니다) 프리 페치를 해제하거나 가능한 한 낮게 설정하고 싶습니다. 나는 지금 그것을 1로 설정했는데, 그것은 내가 찾고있는 것에 충분히 가깝지만 여전히 내가 이해하지 못하는 것이 몇 가지있다.

  1. 프리 페치가 좋은 이유는 무엇입니까? 메시지 대기열과 작업자 사이에 대기 시간이 많지 않은 한 실제로 이유를 알 수 없습니다. 센터). 문서에는 단점 만 언급되어 있지만 장점이 무엇인지 설명하지 못합니다.

  2. 많은 사람들이 이것을 0으로 설정하는 것으로 보이며, 그런 식으로 프리 페치를 끌 수 있기를 기대합니다 (제 생각에는 합리적인 가정). 그러나 0은 무제한 프리 페치를 의미합니다. 누구든지 무제한 프리 페치를 원하는 이유는 무엇입니까? 처음에 작업 대기열을 도입 한 동시성 / 비동기 성을 완전히 제거하지 않습니까?

  3. 프리 페치를 끌 수없는 이유는 무엇입니까? 대부분의 경우 성능에 대해 해제하는 것이 좋지 않을 수 있지만 이것이 가능하지 않은 기술적 이유가 있습니까? 아니면 구현되지 않았습니까?

  4. 경우에 따라이 옵션은에 연결됩니다 CELERY_ACKS_LATE. 예를 들면. Roger Hu는 "[…] 종종 [사용자]가 정말로 원하는 것은 작업자가 자식 프로세스가있는만큼의 작업 만 예약하도록하는 것입니다. 그러나 이것은 늦은 승인을 활성화하지 않고는 불가능합니다. […]»이 두 옵션이 어떻게 연결되어 있고 다른 옵션 없이는 하나가 불가능한 이유를 이해할 수 없습니다. 연결에 대한 또 다른 언급은 여기 에서 찾을 수 있습니다 . 누군가 두 옵션이 연결된 이유를 설명 할 수 있습니까?

답변:


32
  1. 프리 페치는 성능을 향상시킬 수 있습니다. 작업자는 브로커의 다음 메시지가 처리 될 때까지 기다릴 필요가 없습니다. 브로커와 한 번 통신하고 많은 메시지를 처리하면 성능이 향상됩니다. 브로커 (로컬에서도)에서 메시지를 가져 오는 것은 로컬 메모리 액세스에 비해 비용이 많이 듭니다. 작업자는 일괄 적으로 메시지를 승인 할 수도 있습니다.

  2. 0으로 설정된 프리 페치는 무제한이 아닌 "특정 제한 없음"을 의미합니다.

  3. 프리 페치를 1로 설정하는 것은 해제하는 것과 동일한 것으로 문서화되어 있지만 항상 그런 것은 아닙니다 ( https://stackoverflow.com/a/33357180/71522 참조 ).

  4. 프리 페치는 메시지를 일괄 적으로 확인할 수 있습니다. CELERY_ACKS_LATE = True는 메시지가 작업자에게 도달 할 때 확인 메시지를 방지합니다.


감사. 2) 좋아, 그런데 왜 누군가 '특정 제한 없음'을 원할까요? 3) 현재 작업이 완료되기 전에 "브로커로부터 작업 가져 오기"메시지가 계속 표시됩니다.
Henrik Heimbuerger 2011

1
AFAIK, 프리 페치를 1로 설정 하는 것은 해제하는 것과 동일 하지 않습니다 . 프리 페치에 대해 가능한 가장 낮은 값 (소스 코드를 해킹하지 않음)이며, 이는 차례로 현재 시스템의 CPU / 코어 수입니다.
Ron Klein

1
@RonKlein CPU / 코어 수가 아니라 사용자가 정의한 셀러리 작업자의 수입니다 (일부 경우 동일 할 수 있지만 일반적으로 그렇지 않음). 또한 각 작업자가 단일 작업을 미리 가져오고 실행 한 다음 다른 작업을 미리 가져 오는 경우 이는 미리 가져 오기를 해제하는 것과 동일하므로 IMHO 문이 올바르지 않습니다. (모든 작업자에게 작업을 계속 제공하려면 시스템에서 작업자 수만큼 작업을 미리
가져와야

3
CELERYD_PREFETCH_MULTIPLIER를 1로 설정하면 기본적으로 '가져 오기'를 의미한다고 생각합니다. 값이> 1로 설정되면 프리 페치가 내포됩니다. 따라서 사실상 1 이상의 작업은 '프리 페치'됩니다.
tigeronk2

3
몇 가지 실험을 실행했으며 (적어도 Redis 브로커에서는) 설정 CELERYD_PREFETCH_MULTIPLIER = 1이 프리 페치를 비활성화 하지 않습니다 . 이름에서 알 수 있듯이 한 번에 하나의 작업 만 프리 페치합니다.
David Wolever 2015 년

28

오래된 질문이지만 누군가에게 도움이 될 경우를 대비하여 여전히 내 대답을 추가합니다. 일부 초기 테스트에서 얻은 이해는 David Wolever의 답변과 동일했습니다. 나는 셀러리 3.1.19에서 이것을 더 테스트했고 -Ofair작동합니다. 작업자 노드 수준에서 프리 페치를 사용하지 않도록 설정하는 것은 아닙니다. 그것은 계속 될 것입니다. 사용 -Ofair하면 풀 작업자 수준에서 다른 효과가 있습니다. 요약하면 프리 페치를 완전히 비활성화하려면 다음과 같이하십시오.

  1. 세트 CELERYD_PREFETCH_MULTIPLIER = 1
  2. CELERY_ACKS_LATE = True글로벌 수준 또는 작업 수준에서 설정
  3. -Ofair작업자를 시작하는 동안 사용
  4. 동시성을 1로 설정하면 3 단계가 필요하지 않습니다. 더 높은 동시성을 원하면 3 단계는 작업이 오래 실행되는 작업을 실행할 수있는 노드에 백업되지 않도록하는 데 필수적입니다.

더 많은 세부 사항 추가 :

작업자 노드는 항상 기본적으로 프리 페치됩니다. 을 사용하여 미리 가져 오는 작업 수만 제어 할 수 있습니다 CELERYD_PREFETCH_MULTIPLIER. 1로 설정하면 노드의 풀 작업자 (동시성) 수만큼의 작업 만 프리 페치합니다. 따라서 동시성이 n 인 경우 노드가 미리 가져 오는 최대 작업은 n이됩니다.

-Ofair옵션이 없으면 풀 작업자 프로세스 중 하나가 장기 실행 작업을 실행하는 경우 노드의 다른 작업자도 노드에서 이미 프리 페치 한 작업의 처리를 중지하게됩니다. 를 사용 -Ofair하면 변경되었습니다. 노드의 작업자 중 하나가 장기 실행 작업을 실행하고 있었지만 다른 작업자는 처리를 중지하지 않고 노드에서 미리 가져온 작업을 계속 처리합니다. 그래서 두 가지 수준의 프리 페칭이 보입니다. 작업자 노드 수준에서 하나. 다른 하나는 개별 작업자 수준입니다. 사용 -Ofair나를 위해하는 것은 작업자 수준에서 비활성화 것 같았다.

어떤 ACKS_LATE관련이 있습니까? ACKS_LATE = True작업이 성공한 경우에만 작업이 승인됨을 의미합니다. 그렇지 않다면 작업자가받을 때 일어날 것이라고 생각합니다. 프리 페치의 경우 작업은 작업자가 먼저 수신하지만 (로그에서 확인) 나중에 실행됩니다 . 방금 미리 가져온 메시지가 rabbitmq의 "확인되지 않은 메시지"아래에 표시된다는 것을 깨달았습니다. 따라서 설정 True이 절대적으로 필요한지 확실하지 않습니다 . 우리는 어쨌든 다른 이유로 우리의 작업을 그렇게 (늦게 확인) 설정했습니다.


이 질문에 여전히 기여해 주셔서 감사합니다! 좀 더 자세히 설명해 주시겠습니까? 예를 들어, 당신이 쓰고 -Ofair있는 것은 "다른 효과"가 있지만 그 효과가 어떻게 다른지는 아닙니다. 또한 CELERY_ACKS_LATE다른 사람들이 이전에했던 것처럼을 가져 오지만 지금까지 아무도 그 속성이 프리 페치를 비활성화하는 것과 어떤 관련이 있는지 설명하지 못했습니다.
Henrik Heimbuerger 2016-06-08

redis 백엔드로 실행되는 동일한 문제가 발생했습니다. 4 개의 동시 작업이 실행 중이고 하나가 매달리기 시작하면 다른 작업이 완료 될 때까지 기다릴 것입니다 (그렇지 않습니다). 그 작업자를 죽이면 다른 작업이 재개 될 수 있습니다. 나는 이미 가지고 있었고 prefetch=1, celery_acks=True그것을 추가했을 때 -Ofair그들이 매달린 작업자를 기다리고 있던 문제를 해결했습니다. 불행히도 중단 된 작업자 문제는 여전히 저에게 해결되지 않았으므로 결국 모든 작업자가 중단되지만 적어도 더 이상 정확히 동시에 수행하지 않습니다.
JiminyCricket

18

경고 : redis broker + Celery 3.1.15를 사용한 테스트에서 CELERYD_PREFETCH_MULTIPLIER = 1프리 페치 비활성화와 관련하여 제가 읽은 모든 조언 은 명백히 거짓입니다.

이를 증명하려면 :

  1. 세트 CELERYD_PREFETCH_MULTIPLIER = 1
  2. (예를 각각 몇 초를 취할 것 (5 개) 작업을 대기열 time.sleep(5))
  3. Redis에서 작업 대기열의 길이를 확인하십시오. watch redis-cli -c llen default

  4. 스타트 celery worker -c 1

  5. Redis의 대기열 길이는에서 다음 5으로 즉시 감소 합니다.3

CELERYD_PREFETCH_MULTIPLIER = 1 프리 페치를 방지하지 않고 큐당 작업 1 개로 프리 페치를 제한합니다.

-Ofair, 문서의 말씀에도 불구하고 , 또한 프리 페치 방지하지 않습니다 .

소스 코드를 수정하지 않고 프리 페치를 완전히 비활성화하는 방법을 찾지 못했습니다.


1
다른 답변에서 언급했듯이 또한 설정 CELERY_ACKS_LATE = 1하면 미리 가져 오기를 효과적으로 비활성화합니다.
jodag

11

내 stackcred가 충분히 높지 않기 때문에 David Wolever의 답변에 대해 언급 할 수 없습니다. 따라서 Celery 3.1.18 및 Mongodb 브로커와의 경험을 공유하고 싶기 때문에 내 의견을 답으로 구성했습니다. 다음을 사용하여 미리 가져 오기를 중지했습니다.

  1. CELERYD_PREFETCH_MULTIPLIER = 1셀러리 구성에 추가
  2. CELERY_ACKS_LATE = True셀러리 구성에 추가
  3. 옵션으로 셀러리 작업자를 시작하십시오. --concurrency=1 -Ofair

CELERY_ACKS_LATE를 기본값으로 두더라도 작업자는 여전히 프리 페치합니다. OP와 마찬가지로 프리 페치와 레이트 액크 사이의 링크를 완전히 파악하지 못합니다. David가 "CELERY_ACKS_LATE = True는 메시지가 작업자에게 도달 할 때 메시지를 확인하는 것을 방지합니다."라고 말한 것을 이해합니다. 그러나 늦은 액세스가 프리 페치와 호환되지 않는 이유를 이해하지 못합니다. 이론적으로 프리 페치는 셀러리로 코딩되지 않은 경우에도 여전히 늦게 늦게 확인할 수 있습니다.


2

나는 브로커로서 SQS와 약간 다른 것을 경험했습니다.

설정은 다음과 같습니다.

CELERYD_PREFETCH_MULTIPLIER = 1
ACKS_ON_FAILURE_OR_TIMEOUT=False
CELERY_ACKS_LATE = True
CONCURRENCY=1

작업 실패 후 (예외 발생), 로컬 및 원격 대기열 모두에서 메시지가 확인되지 않았으므로 작업자를 사용할 수 없게되었습니다.

작업자가 계속 작업을 소비하게하는 솔루션은

CELERYD_PREFETCH_MULTIPLIER = 0

SQS 전송을 작성할 때 acks_late가 고려되지 않았다고 추측 할 수 있습니다.


이 사례를 처리하는 PR을 만들었습니다. celery == 4.4.0 github.com/celery/celery/pull/5843
gCoh
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.