2013-08-13 10 views
5

मैंने टर्ननाडो का उपयोग करते हुए अजगर में लिखे गए एक व्यापक HTTP सर्वर विकसित किए हैं। कुछ विशेष सेट किए बिना, सर्वर अनुरोध पर अवरुद्ध करता है और केवल एक समय में एक को संभाल सकता है। अनुरोध मूल रूप से डेटा (mysql/redis) तक पहुंचते हैं और इसे जेसन में प्रिंट करते हैं। ये अनुरोध सबसे खराब मामले में एक सेकंड के ऊपर ले जा सकते हैं। समस्या यह है कि एक अनुरोध में आता है जो लंबे समय तक (3 एस) लेता है, फिर तुरंत एक आसान अनुरोध आता है जिसके बाद इसे संभालने के लिए 5ms लगेंगे। ठीक है क्योंकि पहला अनुरोध 3 एस लेने जा रहा है, दूसरा तब तक शुरू नहीं होता जब तक कि पहले व्यक्ति नहीं किया जाता। तो दूसरा अनुरोध संभाला जाता है> 3 एस संभाला जा सकता है।पायथन http सर्वर, एकाधिक एक साथ अनुरोध

मैं इस स्थिति को बेहतर कैसे बना सकता हूं? मुझे अन्य अनुरोधों के बावजूद निष्पादन शुरू करने के लिए उस दूसरे सरल अनुरोध की आवश्यकता है। मैं अजगर के लिए नया हूं, और अपाचे/PHP के साथ अधिक अनुभवी हूं जहां एक दूसरे को अवरुद्ध करने के दो अलग-अलग अनुरोधों की कोई धारणा नहीं है। मैंने php उदाहरण का अनुकरण करने के लिए mod_python में देखा है, लेकिन ऐसा लगता है कि यह भी ब्लॉक है। क्या मैं अपनी कार्यक्षमता प्राप्त करने के लिए अपना टर्ननाडो सर्वर बदल सकता हूं? जहां भी मैं पढ़ता हूं, यह कहता है कि टर्ननाडो कई एक साथ अनुरोधों को संभालने में बहुत अच्छा है।

यहां डेमो कोड है जिसके साथ मैं काम कर रहा हूं। मेरे पास नींद कमांड है जिसका उपयोग मैं परीक्षण करने के लिए कर रहा हूं यदि समवर्ती कार्य करता है। क्या समरूपता का परीक्षण करने का एक उचित तरीका है?

import tornado.httpserver 
import tornado.ioloop 
import tornado.web 
import tornado.gen 
import time 

class MainHandler(tornado.web.RequestHandler): 
    @tornado.web.asynchronous 
    @tornado.gen.engine 

    def handlePing1(self): 
     time.sleep(4)#simulating an expensive mysql call 
     self.write("response to browser ....") 
     self.finish() 

    def get(self): 
     start = time.time() 
     self.handlePing1() 
     #response = yield gen.Task(handlePing1)#i see tutorials around that suggest using something like this .... 

     print "done with request ...", self.request.path, round((time.time()-start),3) 



application = tornado.web.Application([ 
     (r"/.*", MainHandler), 
]) 

if __name__ == "__main__": 
    http_server = tornado.httpserver.HTTPServer(application) 
    port=8833; 
    http_server.listen(port) 
    print "listening on "+str(port); 
    tornado.ioloop.IOLoop.instance().start() 

किसी भी मदद के लिए धन्यवाद!

उत्तर

0

मुझे एक ही समस्या थी, लेकिन कोई टर्ननाडो नहीं, कोई mysql नहीं था। क्या आपके पास सभी सर्वर के साथ एक डेटाबेस कनेक्शन साझा किया गया है?

मैंने multiprocessing.Pool बनाया। प्रत्येक का अपना डीबी कनेक्शन init फ़ंक्शन द्वारा प्रदान किया जाता है। मैं फ़ंक्शन में धीमी कोड और map पूल में लपेटता हूं। तो मेरे पास कोई साझा चर और कनेक्शन नहीं हैं।

नींद अन्य धागे को अवरुद्ध नहीं करती है, लेकिन डीबी लेनदेन धागे को अवरुद्ध कर सकता है।

आपको अपने कोड के शीर्ष पर पूल सेट करने की आवश्यकता है।

def spawn_pool(fishes=None): 
    global pool 
    from multiprocessing import Pool 
    def init(): 
     from storage import db #private connections 
     db.connect() #connections stored in db-framework and will be global in each process 
    pool = Pool(processes=fishes,initializer=init) 

if __name__ == "__main__": 
    spawn_pool(8) 


from storage import db #shared connection for quick-type requests. 

#code here 

if __name__ == "__main__": 
    start_server() 

समवर्ती त्वरित से अनेक अनुरोध मंदी एक बड़ा अनुरोध है, लेकिन इस संगामिति डेटाबेस सर्वर केवल पर रखा जाएगा सकता है।

3

संपादित करें: याद रखें कि रेडिस भी एक थ्रेडेड है, इसलिए यदि आपके समवर्ती अनुरोध हैं, तो आपकी बाधा रेडिस होगी। आप अधिक अनुरोध संसाधित नहीं कर पाएंगे क्योंकि रेडिस उन्हें संसाधित नहीं कर पाएंगे।

टोरनाडो एकल-थ्रेडेड, इवेंट-लूप आधारित सर्वर है।

प्रलेखन से

:

गैर अवरुद्ध नेटवर्क का उपयोग करके मैं/हे, तूफान खुले कनेक्शनों की हजारों करने के लिए पैमाने पर कर सकते हैं, यह लंबे समय मतदान, WebRTC, और अन्य अनुप्रयोगों है कि एक की आवश्यकता के लिए आदर्श बना प्रत्येक उपयोगकर्ता के लिए दीर्घकालिक कनेक्शन।

टॉरनाडो में समेकन एसिंक्रोनस कॉलबैक के माध्यम से हासिल किया जाता है। विचार मुख्य घटना लूप (सिंगल-थ्रेडेड) में जितना संभव हो उतना कम करना है ताकि कॉलबैक के माध्यम से I/O संचालन को अवरुद्ध और स्थगित कर दिया जा सके।

यदि एसिंक्रोनस ऑपरेशंस का उपयोग करना आपके लिए काम नहीं करता है (उदा: माईएसQL, या रेडिस के लिए कोई एसिंक ड्राइवर नहीं), तो अधिक समवर्ती अनुरोधों को संभालने का आपका एकमात्र तरीका एकाधिक प्रक्रियाओं को चलाने के लिए है।

सबसे आसान तरीका है अपनी टर्ननाडो प्रक्रियाओं को एक रिवर्स-प्रॉक्सी जैसे हैप्रोक्सी या निजिनक्स के साथ। टॉरनाडो डॉक्टर नेगिनक्स की सिफारिश की: http://www.tornadoweb.org/en/stable/overview.html#running-tornado-in-production

आपके मूल रूप से विभिन्न बंदरगाहों पर आपके ऐप के कई संस्करण चलाते हैं। उदाहरण के लिए:

python app.py --port=8000 
python app.py --port=8001 
python app.py --port=8002 
python app.py --port=8003 

इसका एक अच्छा शासन अपने सर्वर पर प्रत्येक कोर के लिए 1 प्रक्रिया चलाने के लिए है।

Nginx प्रत्येक आने वाले अनुरोधों को अलग-अलग बैकएंडों को संतुलित करने का ख्याल रखेगा। इसलिए यदि अनुरोध में से एक धीमा है (~ 3 एस) आपके पास आने वाले अनुरोधों के लिए एन-1 अन्य प्रक्रियाएं सुन रही हैं। यह संभव है - और बहुत संभावना है कि सभी प्रक्रियाएं धीमे-आश अनुरोध को संसाधित करने में व्यस्त होंगी, जिसमें किसी भी प्रक्रिया को मुक्त होने पर मामले के अनुरोधों को कतारबद्ध और संसाधित किया जाएगा, उदाहरण के लिए। अनुरोध को संसाधित करना समाप्त कर दिया।

मैं दृढ़ता से अनुशंसा करता हूं कि आप HAPROxy की कोशिश करने से पहले Nginx से शुरू करें क्योंकि बाद वाला थोड़ा और उन्नत है और इस प्रकार ठीक से सेटअप करने के लिए थोड़ा अधिक जटिल (ट्विक करने के लिए बहुत सारे स्विच)।

उम्मीद है कि इससे मदद मिलती है। कुंजी ले-दूर: टॉरनाडो एसिंक I/O के लिए बहुत अच्छा है, सीपीयू भारी वर्कलोड के लिए कम है।

संबंधित मुद्दे