Muszę uruchamiać zadania na około 150k obiektów Django. Jaki jest najlepszy sposób na zrobienie tego? Używam Django ORM jako Broker. Bazą danych bazy danych jest MySQL oraz dławiki i matryce podczas task.delay() wszystkich zadań. Podobne, chciałem również oderwać to od złożenia formularza, ale wynikowe żądanie wygenerowało długi czas odpowiedzi, który upłynął.django/seler: Najlepsze praktyki do uruchamiania zadań na obiektach Django 150k?
Odpowiedz
Chciałbym również rozważyć użycie czegoś innego niż z wykorzystaniem bazy danych jako „pośrednik”. Naprawdę nie nadaje się do tego rodzaju pracy.
Choć można przenieść część tego narzutu z cyklu żądania/odpowiedzi poprzez uruchomienie zadanie stworzyć inne zadania:
from celery.task import TaskSet, task
from myapp.models import MyModel
@task
def process_object(pk):
obj = MyModel.objects.get(pk)
# do something with obj
@task
def process_lots_of_items(ids_to_process):
return TaskSet(process_object.subtask((id,))
for id in ids_to_process).apply_async()
Ponadto, ponieważ prawdopodobnie nie ma 15000 procesorów do przetwarzania wszystkie z tych obiektów równolegle, można podzielić obiektów kawałkami powiedzieć, 100 lub 1000:
from itertools import islice
from celery.task import TaskSet, task
from myapp.models import MyModel
def chunks(it, n):
for first in it:
yield [first] + list(islice(it, n - 1))
@task
def process_chunk(pks):
objs = MyModel.objects.filter(pk__in=pks)
for obj in objs:
# do something with obj
@task
def process_lots_of_items(ids_to_process):
return TaskSet(process_chunk.subtask((chunk,))
for chunk in chunks(iter(ids_to_process),
1000)).apply_async()
Dzięki pytaj! Dzięki @ApPeL i Twojej sugestii przeszedłem do brokera RabbitMQ i zobaczyłem natychmiastowe zyski. Ponadto, włączenie tych zadań ustaliło to, co próbowałem osiągnąć !! –
Czy możesz skomentować, jak działa ten kod i ile zadań jest tworzonych? Próbowałem go przez ostatnie 4 dni i ciągle obniża moją bazę danych. Używam tylko 80% procesora, gdy jest uruchomiony, ale otrzymuję "MySQL zniknął" i łączę błędy po uruchomieniu przez chwilę. –
Wygląda na to, że przeciążasz bazę danych? Czy przechowujesz wyniki w bazie danych? Jest to ustawienie domyślne dla django-selera. Jeśli ich nie potrzebujesz, powinieneś ustawić '@task (ignore_result = True)' lub wyłączyć je globalnie używając 'CELERY_IGNORE_RESULT = True' – asksol
Spróbuj użyć RabbitMQ zamiast tego.
RabbitMQ jest używany w wielu większych firmach i ludzie naprawdę na nim polegają, ponieważ jest to świetny pośrednik.
używam beanstalkd (http://kr.github.com/beanstalkd/) jako silnika. Dodanie pracownika i zadania jest bardzo proste dla Django, jeśli użyjesz django-beanstalkd: https://github.com/jonasvp/django-beanstalkd/
Jest to bardzo niezawodny sposób użycia.
Przykład pracownika:
import os
import time
from django_beanstalkd import beanstalk_job
@beanstalk_job
def background_counting(arg):
"""
Do some incredibly useful counting to the value of arg
"""
value = int(arg)
pid = os.getpid()
print "[%s] Counting from 1 to %d." % (pid, value)
for i in range(1, value+1):
print '[%s] %d' % (pid, i)
time.sleep(1)
Aby uruchomić zadania/pracownika/zadania:
from django_beanstalkd import BeanstalkClient
client = BeanstalkClient()
client.call('beanstalk_example.background_counting', '5')
(źródło pochodzących z np app Django beanstalkd)
Enjoy!
To jest ** dokładnie ** pytanie, które było mi potrzebne. Bardzo doceniane. – mlissner