بيثون تورنادو - إرجاع ما بعد العودة على الفور بينما تستمر وظيفة Async في العمل

StackOverflow https://stackoverflow.com/questions/3869421

  •  28-09-2019
  •  | 
  •  

سؤال

لذلك لدي معالج أدناه:

class PublishHandler(BaseHandler):

    def post(self):
        message = self.get_argument("message")
        some_function(message)
        self.write("success")

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

أنا أستخدم Berkeley DB كقاعدة بيانات وما أحاول فعله بسيط نسبيًا.

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

هل كانت مفيدة؟

المحلول

قد تكون قادرًا على تحقيق ذلك باستخدام الخاص بك IOLoopadd_callback طريقة مثل ذلك:

loop.add_callback(lambda: some_function(message))

سوف يقوم Tornado بتنفيذ رد الاتصال في ممر Ioloop التالي ، الذي مايو (يجب أن أحفر في الشجاعة في Tornado لأعرفه بالتأكيد ، أو اختباره بدلاً من ذلك) ، السماح للطلب بإكمال قبل تنفيذ هذا الرمز.

العيب هو أن هذا الرمز طويل الأمد الذي كتبته سيستغرق وقتًا لتنفيذه ، وقد ينتهي هذا الأمر بمنع طلب آخر. هذا ليس مثاليًا إذا كان لديك الكثير من هذه الطلبات في وقت واحد.

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

إذا كنت تسير في المسار الخيطي ، فيمكنك إنشاء وحدة نمطية لطيفة "Async Executor" مع Mutex وموضوع وقائمة انتظار. تفحص ال multiprocessing الوحدة النمطية إذا كنت تريد الذهاب إلى طريق استخدام عملية منفصلة.

نصائح أخرى

لقد جربت هذا ، وأعتقد أن الطلب لا يكتمل قبل استدعاء عمليات الاسترجاعات.

أعتقد أن الاختراق القذر هو استدعاء مستويين من add_callback ، على سبيل المثال:

  def get(self):
    ...
    def _defered():
      ioloop.add_callback(<whatever you want>)
    ioloop.add_callback(_defered)
    ...

لكن هذه هي الاختراقات في أحسن الأحوال. أنا أبحث عن حل أفضل في الوقت الحالي ، وربما سينتهي الأمر ببعض قائمة انتظار الرسائل أو حل مؤشر الترابط البسيط.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top