2014-09-30 4 views
6

पर समय लेने वाली कॉल को संभालने के लिए मुझे एक फ्लास्क ऐप मिला है जो बाहरी सेवाओं (अलग-अलग, लेकिन आमतौर पर लंबे प्रतिक्रिया समय के साथ) के साथ दिए गए यूआरएल से जुड़ता है और वहां कुछ सामानों की खोज करता है। उसके बाद पुनर्प्राप्त डेटा पर कुछ CPU भारी ऑपरेशन हैं। इसमें कुछ समय लगता है।फ्लास्क और/या टोरनाडो - बाहरी webservice

मेरी समस्या: बाहरी से प्रतिक्रिया कुछ समय ले सकती है। आप इसके बारे में ज्यादा कुछ नहीं कर सकते हैं, लेकिन जब आप एक साथ कई अनुरोध करते हैं तो यह एक बड़ी समस्या बन जाती है - बाहरी सेवा के लिए फ्लास्क अनुरोध धागे को अवरुद्ध करता है और शेष प्रतीक्षा कर रहा है।

समय की स्पष्ट बर्बादी और यह ऐप को मार रहा है।

मैंने टोरनाडो नामक इस असंगत पुस्तकालय के बारे में सुना। और मेरे प्रश्न हैं:

  1. क्या इसका मतलब यह है कि यह एकाधिक रिकॉर्ड्स को संभालने में सक्षम हो सकता है और बाहरी से प्रतिक्रिया के बाद ही कॉलबैक को ट्रिगर कर सकता है?
  2. क्या मैं इसे अपने वर्तमान फ्लास्क ऐप के साथ प्राप्त कर सकता हूं (शायद डब्लूएसजीआई के अनुमान के कारण नहीं?) या शायद मुझे पूरे ऐप को टॉरनाडो में फिर से लिखना होगा?
  3. उन CPU भारी परिचालनों के बारे में क्या - क्या यह मेरे धागे को अवरुद्ध करेगा? वैसे भी कुछ लोड संतुलन करना अच्छा विचार है, लेकिन मुझे उत्सुकता है कि टॉरनाडो कैसे संभालता है।
  4. संभावित जाल, गॉथस?

उत्तर

5

फ्लास्क में बनाया गया वेब सर्वर उत्पादन में उपयोग करने के लिए बिल्कुल नहीं है, क्योंकि आप सूचीबद्ध हैं - यह सिंगल थ्रेडेड है, और यदि कोई अनुरोध गैर-तुच्छ समय के लिए अवरुद्ध हो जाता है तो आसानी से नीचे गिर जाता है। फ्लास्क प्रलेखन lists several options for deploying it in a production environment; mod_wsgi, gunicorn, uSWGI, आदि। उन सभी परिनियोजन विकल्प थ्रेड, प्रक्रियाओं, या गैर-अवरुद्ध I/O के माध्यम से समेकन को संभालने के लिए तंत्र प्रदान करते हैं। नोट, हालांकि, अगर आप सीपीयू-बाउंड ऑपरेशंस कर रहे हैं, तो एकमात्र विकल्प जो सही समेकन देगा, कई प्रक्रियाओं का उपयोग करना है।

यदि आप tornado का उपयोग करना चाहते हैं, तो आपको tornado शैली में अपने एप्लिकेशन को फिर से लिखना होगा। चूंकि स्पष्ट आर्किंक्रोनस I/O पर आधारित इसकी वास्तुकला, यदि आप इसे WSGI एप्लिकेशन के रूप में तैनात करते हैं तो आप इसकी एसिंक्रोनस विशेषताओं का उपयोग नहीं कर सकते हैं। "tornado शैली" का मूल रूप से सभी I/O संचालन के लिए गैर-अवरुद्ध API का उपयोग करना और किसी भी लंबे समय से चलने वाले CPU-bound संचालन को संभालने के लिए उप-प्रक्रियाओं का उपयोग करना है। tornado प्रलेखन कैसे अतुल्यकालिक मैं/हे कॉल करने के लिए शामिल किया गया है, लेकिन यहाँ यह कैसे काम करता की एक बुनियादी उदाहरण है:

from tornado import gen 

@gen.coroutine 
def fetch_coroutine(url): 
    http_client = AsyncHTTPClient() 
    response = yield http_client.fetch(url) 
    return response.body 

response = yield http_client.fetch(curl) कॉल वास्तव में अतुल्यकालिक है; जब अनुरोध शुरू होता है तो यह टर्ननाडो इवेंट लूप पर नियंत्रण वापस कर देगा, और प्रतिक्रिया मिलने के बाद फिर से शुरू हो जाएगी। यह एकाधिक एसिंक्रोनस HTTP अनुरोधों को समवर्ती रूप से चलाने की अनुमति देता है, सब एक थ्रेड के भीतर।हालांकि, ध्यान दें कि fetch_coroutine के अंदर जो कुछ भी आप करते हैं असीमित I/O ईवेंट लूप को अवरुद्ध कर देगा, और उस कोड के चलते कोई अन्य अनुरोध संभाला नहीं जा सकता है।

लंबे समय से चल रहे CPU- बाध्य संचालन से निपटने के लिए, आपको इवेंट लूप को अवरुद्ध करने से बचने के लिए कार्य को एक उपप्रोसेसर में भेजने की आवश्यकता है। पायथन के लिए, आमतौर पर इसका मतलब है multiprocessing या concurrent.futures का उपयोग करना। tornado के साथ उन पुस्तकालयों को एकीकृत करने के तरीके के बारे में अधिक जानकारी के लिए मैं this question पर एक नज़र डालेगा। ध्यान दें कि आप सिस्टम पर मौजूद CPUs की संख्या से अधिक एक प्रक्रिया पूल को बनाए रखना नहीं चाहते हैं, इसलिए इस बात पर विचार करें कि आप कितने समवर्ती CPU-bound संचालन को किसी भी समय चलने की उम्मीद करते हैं जब आप यह पता लगा रहे हैं कि कैसे एक मशीन से परे इसे स्केल करने के लिए।

बवंडर प्रलेखन has a section dedicated to running behind a load balancer, साथ ही साथ। वे इस उद्देश्य के लिए एनजीआईएनएक्स का उपयोग करने की सलाह देते हैं।

1

टॉर्नडो फ्लास्क की तुलना में इस कार्य के लिए अधिक उपयुक्त लगता है। Tornado.web.RequestHandler का एक सबक्लास tornado.ioloop के उदाहरण में चलाया जाना चाहिए, आपको गैर अवरुद्ध अनुरोध हैंडलिंग देना चाहिए। मुझे उम्मीद है कि यह ऐसा कुछ दिखाई देगा।

import tornado 
import tornado.web 
import tornado.ioloop 
import json 

class handler(tornado.web.RequestHandler): 
    def post(self): 
     self.write(json.dumps({'aaa':'bbbbb'})) 


if __name__ == '__main__': 
    app = tornado.web.Application([('/', handler)]) 
    app.listen(80, address='0.0.0.0') 
    loop = tornado.ioloop.IOLoop.instance() 
    loop.start() 

अगर आप अपनी पोस्ट हैंडलर अतुल्यकालिक होना चाहते हैं आप के साथ 'AsyncHTTPClient or grequests` tornado.gen.coroutine के साथ सजाने कर सकते हैं। यह आपको गैर अवरुद्ध अनुरोध देगा। आप संभावित रूप से अपनी गणना को कोरआउट में भी डाल सकते हैं, हालांकि मुझे पूरी तरह से यकीन नहीं है।

+0

बस एक हैंडलर को '@ tornado.gen.coroutine' सजावट जोड़ने वाला यह अतुल्यकालिक नहीं बनाता है। आपको वास्तव में हैंडलर के अंदर भी गैर-अवरुद्ध कॉल करना होगा। यदि आप फ़ंक्शन में कोई अवरुद्ध करने वाले ऑपरेशन करते हैं, तो संपूर्ण ईवेंट लूप अवरुद्ध हो जाएगा, भले ही आप 'कोरआउटिन' सजावट का उपयोग करें या नहीं। – dano

+0

आप सही हैं, मेरी गलती। क्या आप async अनुरोध प्राप्त करने के लिए grequests का उपयोग कर सकते हैं? – ragingSloth

+0

'grequests' एसिंक्रोनस I/O, हां प्रदान करने के लिए' gevent' का उपयोग करता है। यदि आप 'टॉरनाडो' का उपयोग कर रहे हैं, तो शायद आप अपने अंतर्निर्मित 'AsyncHTTPClient' का उपयोग करना चाहते हैं, हालांकि, यह टर्ननाडो ईवेंट लूप के साथ एकीकृत है। – dano