3 حالات لاستخدام الكرفس في تطبيق Django

صورة

أقوم بإنشاء تطبيقات الويب على Django. في الأساس ، هذه هي خدمات ادارة العلاقات مع رجال الأعمال. كل هذه التطبيقات تتطلب مهام غير متزامنة. لتنفيذها يمكنني استخدام الكرفس. في المقال سوف أخبر عن المواقف التي أستخدم فيها الكرفس ، مع أمثلة الكود.

الكرفس هو نظام لإدارة قوائم الانتظار المهمة. قادر بشكل أساسي على أمرين: أخذ المهام من قائمة الانتظار وتنفيذ المهام على جدول زمني. وسيط قائمة الانتظار هو عادة RabbitMQ أو Redis. يتم وضع المهام في قائمة الانتظار ، ثم يأخذهم عمال الكرفس من هناك ويؤدونها.

بالنسبة إلى Celery ، يمكنك التفكير في أي تطبيق في أي تطبيق تقريبًا ، ولكن بعد ذلك سوف أصف فقط الحالات التي استخدمها بنفسي.

1. المهام المجدولة


غالبًا ما تكون هناك مهام تحتاج إلى إكمالها في تاريخ ووقت محددين: إرسال تذكير إلى المستخدم ، وإنهاء الفترة التجريبية للحساب ، ونشر منشور على الشبكات الاجتماعية.

في Celery ، من الممكن تحديد معلمة ETA عند استدعاء المهمة - الوقت الذي يجب أن تبدأ فيه المهمة. لكن إذا كنت تخطط للمهام بهذه الطريقة ، فقد تبين أنها غير موثوق بها للغاية: فقد لا تبدأ وقد تكون غير مريحة للإلغاء.

طريقة أكثر موثوقية هي استخدام جدول celerybeat. بمعنى ، قم بإنشاء جدول حيث ستكون هناك مهام تبدأ بتردد معين أو في وقت محدد. على سبيل المثال ، إذا كنت بحاجة إلى نشر منشور على شبكات التواصل الاجتماعي وفقًا لجدول زمني ، فستبدأ مهمة ذلك مرة واحدة في الدقيقة. إذا كنت بحاجة إلى إنهاء الفترة التجريبية لحسابك ، يمكنك تشغيل المهمة مرة واحدة يوميًا.

# schedule.py from datetime import timedelta from celery.schedules import crontab CELERYBEAT_SCHEDULE = { 'publish_post_starter': { 'task': 'publish_post_starter', 'schedule': timedelta(minutes=1), }, 'end_trial_starter': { 'task': 'end_trial_starter', 'schedule': crontab(hour=10, minute=21), }, } 

في بداية المهمة ، نحصل على جميع الحالات التي حان الوقت المخطط لها بالفعل. نذهب من خلال الحالات ولكل نسميه المهمة الرئيسية. كحجج ، نقوم بتمرير معرف المثيل فقط حتى لا تسد قائمة الانتظار بالبيانات غير الضرورية. يمكننا على الفور متابعة جميع الحالات وتنفيذ الإجراءات ، ولكن في أغلب الأحيان يكون من الأفضل استدعاء مهمة منفصلة لكل حالة. لذلك سنقوم بتسريع التنفيذ ، وإذا حدث خطأ ، فسوف يؤثر على واحدة فقط من المهام.

 # tasks.py @app.task(name='publish_post') def publish_post(post_id): ... @app.task(name='publish_post_starter') def publish_post_starter(): post_ids = list( Post.objects.filter( publish_dt__lte=timezone.now(), is_published=False ).values_list('id', flat=True) ) for post_id in post_ids: publish_post.delay(post_id) 

2. الحوسبة الطويلة ومكالمات API من WSGI


يشير WSGI إلى السياق الذي تتم فيه معالجة الطلبات من المستخدمين (دورة طلب الاستجابة). على النقيض من سياق المهام غير المتزامنة - الكرفس.

لإنشاء واجهة سريعة الاستجابة ، يجب أن تستجيب جميع الأزرار على الفور ويجب ألا تحظر بقية الواجهة. للقيام بذلك ، بعد الضغط على الزر تم حظره ، يتم وضع زر زيادة ونقصان وطلب إرسال اياكس إلى الخادم. إذا استغرقت معالجة الطلب وقتًا أطول من ثانيتين ، فيمكنك نقل الحساب إلى مهمة الكرفس.

في WSGI ، نسمي المهمة ونرجع استجابة. في المقدمة ، قم بإلغاء قفل الزر وإزالة الدوار. نعرض للمستخدم رسالة مفادها أن الإجراء قيد التشغيل. بالتوازي ، يتم تنفيذ مهمة الكرفس ، والتي ، عند الانتهاء ، تُرجع استجابة على مقبس الويب. بعد استلام النتيجة في المقدمة ، نعرضها على المستخدم.

 # rest_views.py from rest_framework import status from rest_framework.views import APIView from rest_framework.response import Response from tasks import send_emails class SendEmailView(APIView): def post(self, request): # this id will be used to send response with websocket request_uuid = request.data.get('request_uuid') if not request_uuid: return Response(status=status.HTTP_400_BAD_REQUEST) send_emails.delay(request.user.id, request_uuid) return Response(status=status.HTTP_200_OK) 

بشكل منفصل ، يمكنك تمييز مكالمات API الخارجية من WSGI. في هذه الحالة ، يتم إطلاق جميع المكالمات ، بغض النظر عن مدة تنفيذها ، من خلال مهمة الكرفس. هذه هي الحماية من الخداع. لا ينبغي أن يكون هناك موقف ، بسبب عدم إمكانية الوصول إلى واجهة برمجة تطبيقات خارجية ، تتجمد واجهة المستخدم.

3. تحديات من تورنادو


عند الدمج مع شبكة اجتماعية أو Telegram أو خدمة دفع ، فأنت بحاجة إلى عنوان urhook الإلكتروني الذي ستأتي إليه الإخطارات. لا يمكن دائمًا حساب عدد الطلبات مقدمًا ، ولكن على الأرجح سيتجاوز عدد الطلبات طلبات المستخدمين. سيتم استلام هذه الطلبات حتى يتلقوا ردًا برمز 200.

لمعالجة مثل هذه الطلبات ، فإن إطار Tornado غير المتزامن مناسب. لكي لا تتحول المعالجة إلى متزامن في تورنادو ، يجب ألا تكون هناك عمليات حظر. هذا هو المكان المطلوب الكرفس. يتلقى معالج Tornado الطلب ، ويقوم بالتحقق من صحة البيانات ، ويستدعي مهمة Celery ، ويقوم بإرجاع استجابة ناجحة.

 # tornado_handlers.py from tornado import gen, escape from tornado.web import RequestHandler from tasks import handle_vk_callback class VkCallbackHandler(RequestHandler): @gen.coroutine def post(self, *args, **kwargs): try: data = escape.json_decode(self.request.body) except ValueError: self.set_status(status_code=400, reason='Invalid data') return handle_vk_callback.delay(data) self.write('ok') return 

Source: https://habr.com/ru/post/ar461775/


All Articles