2016-04-01 21 views
2

'u kullanarak birden çok Kereviz görevini çalıştırın Ben, bazı ev yapımı kodları Celery ile değiştiriyorum, ancak geçerli davranışı çoğaltmada zor bir zaman geçiriyorum.Bir konu değişimi

  • yeni bir kullanıcı oluşturarak, bir mesaj user.created yönlendirme anahtarla tasks değişimi yayınlanmalıdır şu şekildedir: Benim olanı da budur.
  • İki Kereviz görevleri Bu mesajın, yani send_user_activate_email ve check_spam trigged edilmelidir.

Ben ignore_result=True argümanı ile user_created görevi tanımlayarak bu uygulamaya çalıştı artı send_user_activate_email ve check_spam için bir görev.

Yapılandırmamda aşağıdaki yolları ve sıra tanımlarını ekledim. İleti user_created sırasına teslim edilirken, diğer iki sıraya teslim edilmez.

İdeal olarak, ileti yalnızca send_user_activate_email ve check_spam kuyruklarına teslim edilir. Vanilla RabbitMQ kullanıldığında, mesajlar sıraların bağlanabileceği bir exchange'e yayınlanır, ancak Kereviz doğrudan bir sıraya mesaj gönderir gibi görünür.

Kereviz'de yukarıda belirtilen davranışları nasıl uygularım?

sen tetiklemek için tek bir mesaj bekliyoruz gibi geliyor
CELERY_QUEUES = { 
    'user_created': {'binding_key':'user.created', 'exchange': 'tasks', 'exchange_type': 'topic'}, 
    'send_user_activate_email': {'binding_key':'user.created', 'exchange': 'tasks', 'exchange_type': 'topic'}, 
    'check_spam': {'binding_key':'user.created', 'exchange': 'tasks', 'exchange_type': 'topic'}, 
} 

CELERY_ROUTES = { 
    'user_created': { 
     'queue': 'user_created', 
     'routing_key': 'user.created', 
     'exchange': 'tasks', 
     'exchange_type': 'topic', 
    }, 
    'send_user_activate_email': { 
     'queue': 'user_created', 
     'routing_key': 'user.created', 
     'exchange': 'tasks', 
     'exchange_type': 'topic', 
    }, 
    'check_spam': { 
     'queue': 'user_created', 
     'routing_key': 'user.created', 
     'exchange': 'tasks', 
     'exchange_type': 'topic', 
    }, 
} 

cevap

0

/iki kuyruklar tarafından tüketilen ama bu nasıl Kereviz eserler değildir edilecek. Bir Exchange, uygun sıralara görev gönderir, ancak bir kez tüketildiğinde, diğer Kuyruklar iletiyi yok sayar. Tetiklemek istediğiniz Görev başına bir mesaja ihtiyacınız var. Bu sistemde "Kuyruğu" iki kullanımı vardır çünkü yeni Kereviz kullanıcılarla karışıklık genellikle yoktur

; Queue() ve belgelerin başvurduğu Kombu Kuyrukları ve iletileri doğrudan tutan ve işçiler tarafından tüketilen AMQP Kuyrukları. Sıralara yayın yaptığımızda, yanlış olan AMQP'leri düşünüyoruz. (Aşağıdaki linke teşekkürler). Ben doğru anlamak ediyorsam user_created tüketildiğinde Geri sorununuzla

, yazın, bunu iki görevleri yumurtlamaya istiyorum; send_user_activate_email ve check_spam. Dahası, bunlar birbirine bağımlı olmamalıdır; Ayrı makinelerde paralel olarak koşabilirler ve birbirlerinin durumunu bilmelerine gerek yoktur. Bu durumda

, sen user_created için "apply_async" bu iki yeni Görevler ve getiri istiyorum. Bu doğrudan yapılabilir veya bunu elde etmek için check_spam ve send_user_activate_email içeren bir Kereviz "Grubu" kullanabilirsiniz. Grup bazı kestirme işler yapar ve görevlerinize biraz yapı kazandırır, böylece kişisel olarak sizi bu yöne doğru sürüklerim.

#pseudocode 
group(check_spam.s(... checkspam kwargs ...), send_user_activate_email.s(... active email kwargs ...)).apply_async() 

Bu kurulum dört mesaj oluşturabilir; Yürütmek istediğiniz her Görev için bir artı, bunun bir sonucu olacak olan Grup() için bir tane. Senin durumunda

, ben Değişim emin değilim ya ignore_result gereklidir, ama Görev kodu görmek ve bu yargılama yapmak sistemi daha iyi anlamak gerekiyordu.

http://celery.readthedocs.org/en/v2.2.6/userguide/routing.html#exchanges-queues-and-routing-keys Why do CELERY_ROUTES have both a "queue" and a "routing_key"?

http://docs.celeryproject.org/en/latest/userguide/canvas.html#groups (Ben kapalı yol ı sileceğiz isem/... cevabı kaldırmak)

+0

Ayrıntılı açıklamanız için teşekkür ederiz. Cevabınızdan ve belgelerinizden toplanan Kerecik, tek bir iletiye birden çok görev yanıtı vermek yerine, görevler arasında görev dağıtmak için routing_key'i kullanır. Bu, temel olarak, bir görevi tetikleyen ve görevi işleyen kodu sıkı bir şekilde birleştirmeye zorlar. Bu doğru mu? – joelcox

+0

@joelcox, bence bu harika bir özet. Bu kuralın istisnaları, her bir öğe için bir sıradaki bir görevi yürüteceğine inandığım Map() ve Starmap() 'tır, ancak yalnızca tek bir ileti gönderir. Görevlerin birbirlerine yanıt vermesini istiyorsanız (devam etmek için metadata gerekecek şekilde bir başkasının başarılı olmasını beklemek gibi), ayrıca Chain(), Chord() 'a da bakabilirsiniz. –

0

sorununuzu dessign ve çözmek için kolay bir yol usign Kereviz iş akışları olduğunu.
Ama her şeyden önce sıra tanımınızı değiştirip, görev başına benzersiz bir yönlendirme anahtarı ve "doğrudan" değere sahip exchange_type ayarlayabilirim. celery documentation ile göre

, Doğrudan borsaları kesin yönlendirme tuşları tarafından örtüşmesi nedeniyle tüm özel görevleri ve tüketici sıralara aynı alışverişi kurmak ve bir sonraki pasajı gibi (sıralar için) ve binding_key (görevler için) routing_key map:

CELERY_QUEUES = { 
    'user_created': {'binding_key':'user_created', 'exchange': 'tasks', 'exchange_type': 'direct'}, 
    'send_user_activate_email': {'binding_key':'send_user_activate_email', 'exchange': 'tasks', 'exchange_type': 'direct'}, 
    'check_spam': {'binding_key':'check_spam', 'exchange': 'tasks', 'exchange_type': 'direct'}, 
} 

CELERY_ROUTES = { 
    'user_created': { 
     'queue': 'user_created', 
     'routing_key': 'user_created', 
     'exchange': 'tasks', 
     'exchange_type': 'direct', 
    }, 
    'send_user_activate_email': { 
     'queue': 'send_user_activate_email', 
     'routing_key': 'send_user_activate_email', 
     'exchange': 'tasks', 
     'exchange_type': 'direct', 
    }, 
    'check_spam': { 
     'queue': 'check_spam', 
     'routing_key': 'check_spam', 
     'exchange': 'tasks', 
     'exchange_type': 'direct', 
    }, 
} 

Bu değişiklik bittiğinde, kullanılabilir liste için uygun iş akışını kullanmanız gerekir (http://docs.celeryproject.org/en/latest/userguide/canvas.html#the-primitives). Sorunu okurken bir zincire ihtiyacın olduğunu düşünüyorum, çünkü siparişin korunması gerekiyor.

sequential_tasks = [] 
sequential_tasks.append(user_created.s(**user_created_kwargs)) 
sequential_tasks.append(send_user_activate_email.s(**send_user_activate_email_kwargs)) 
sequential_tasks.append(check_spam.s(**check_spam_kwargs)) 
#you can add more tasks to the chain 
chain(*sequential_tasks)() 

Kereviz, sırayla ilgili işi şeffaf olarak ele alacaktır.

+0

Her bir görev için neden ayrı exchange'e ihtiyacım olduğunu açıklar mısınız? Send_user_activate_email ve check_spam görevleri, önemliyse, paralel olarak çalışabilir. – joelcox

+0

Son düzenlememe bir göz atın – xecgr