Probleemoverzicht
Bij het verzenden van een webhook POST-verzoek van de DRF-server naar de Django-appserver,
kwamen er tijdens het aanmaken van Post modelinstantie-s problemen voor.
- Webhook timeout
- Na het aanmaken van het Post-object, kostte het tijd om de
ManyToMany
veldencategories
,tags
te verwerken. -
Hierdoor werd de webhook-respons vertraagd en beschouwde DRF dit als een mislukking.
-
Geen waarborging van gegevensconsistentie
- Wanneer de Celery-taak direct na de follow-up wordt aangeroepen, wordt deze aangeroepen op een moment dat
tags.add(...)
,categories.add(...)
nog niet voltooid zijn. -
Hierdoor ontstaan er problemen waarbij Celery onvolledige gegevens verwerkt.
-
Ontvangst van lege gegevens in Celery, zelfs na on_commit()
- Na waarborging van de gegevensconsistentie met
on_commit()
, werd de Celery-taak gereserveerd, maar de resultaten van queries zoalstags.all()
bleven nog steeds een lege lijst. - Dit kwam omdat Celery leesbewerkingen naar de replica-DB stuurde en er een vertraging was in de synchronisatie van master naar replica.
Oplossingsstrategie
- Direct na het aanmaken van Post een antwoord retourneren
-
Door alleen de Post-instantie aan te maken en onmiddellijk een
202 Accepted
antwoord naar DRF te retourneren, kan het timeout-probleem worden omzeild. -
Volgwerkzaamheden in een aparte thread verwerken
- Gebruik van
threading.Thread()
om de relatieverwerking en Celery-aanroep van de hoofdflow te scheiden. -
Het ontwerp maakt het mogelijk dat de webhook-respons niet vertraagt.
-
Garantie van transactie binnen post_process
- Verpak de hele verwerking van de
ManyToMany
velden in een transactie mettransaction.atomic()
. - Reserveer de Celery-taak na voltooiing van de taak met
transaction.on_commit()
. -
Dit garandeert dat Celery wordt uitgevoerd nadat de relatieverwerking is voltooid.
-
Specificeer de master DB voor queries binnen Celery
- Om consistentieproblemen door vertragingen in de replica te voorkomen, gebruik expliciet
using('default')
binnen de Celery-taak.
post = Post.objects.using('default').get(id=post_id)
tags = post.tags.using('default').all()
categories = post.categories.using('default').all()
Of gebruik een DB-router om ervoor te zorgen dat Celery-verzoeken altijd de master-DB raadplegen.
Samenvatting van de eindstructuur
- DRF-server → Django webhook-verzoek
- Django:
- Antwoord onmiddellijk teruggeven na het aanmaken van een Post-object.
- Volgwerkzaamheden worden in een aparte thread uitgevoerd.
- Binnen de thread:
- Relaties beheren met
atomic()
. - Reserveer de Celery-taak met
on_commit()
.
- Relaties beheren met
- Celery:
- Data ophalen uit de master DB (
default
).
- Data ophalen uit de master DB (
Conclusie
Elke component functioneert individueel goed, maar om de latency en gegevensconsistentieproblemen die optreden in een gedistribueerde architectuurovergang op te lossen,
was er niet alleen een goede code-architectuur nodig, maar ook systeemontwerp dat rekening houdt met gegevensstromen, timing en vertragingen van de database-replicas.
댓글이 없습니다.