2016-01-03 5 views
15

मैं उस स्थिति में हूं जहां मुझे क्लाइंट से संदेश प्राप्त होता है। उस अनुरोध के भीतर जो उस अनुरोध को संभालता है (@ socketio.on) मैं एक समारोह को कॉल करना चाहता हूं जहां कुछ भारी काम किया जाता है। इसका परिणाम मुख्य धागे को अवरुद्ध नहीं करना चाहिए और काम पूरा होने के बाद ग्राहक को सूचित किया जाना चाहिए। इस प्रकार मैं एक नया धागा शुरू करता हूं।पायथन - फ्लास्क-सॉकेटियो थ्रेड से संदेश भेजें: हमेशा काम नहीं करते

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

इसे समेटने के लिए: यदि संदेश भेजने से पहले कुछ कम्प्यूटेशनल गहन होता है तो इसे वितरित नहीं किया जा रहा है, अन्यथा यह है।

कहा की तरह यह है here और here, एक धागे से ग्राहकों के लिए संदेश भेजने के बिल्कुल एक समस्या नहीं है:

सभी उदाहरणों में इस बिंदु सर्वर द्वारा भेजे गए एक घटना का जवाब जब तक पता चला ग्राहक। लेकिन कुछ अनुप्रयोगों के लिए, सर्वर को एक संदेश का उत्प्रेरक होना चाहिए। सर्वर में उत्पन्न होने वाली घटनाओं के क्लाइंट को नोटिफिकेशन भेजने के लिए यह उपयोगी हो सकता है, उदाहरण के लिए पृष्ठभूमि थ्रेड में।

यहां एक नमूना कोड है। टिप्पणी sharps (#) को हटाते समय संदेश ('थ्रेड से foo') क्लाइंट के लिए अपना रास्ता नहीं ढूंढता है, अन्यथा यह करता है।

from flask import Flask 
from flask.ext.socketio import SocketIO, emit 
app = Flask(__name__) 
socketio = SocketIO(app) 

from threading import Thread 
import time 

@socketio.on('client command') 
def response(data): 
    thread = Thread(target = testThreadFunction) 
    thread.daemon = True 
    thread.start() 

    emit('client response', ['foo']) 

def testThreadFunction(): 
# time.sleep(1) 

    socketio.emit('client response', ['foo from thread']) 

socketio.run(app) 

मैं पायथन 3.4.3, बोतल 0.10.1, कुप्पी के socketio1.2, eventlet 0.17.4 उपयोग कर रहा हूँ।

इस नमूना को एक .py फ़ाइल में कॉपी और चिपकाया जा सकता है और व्यवहार को तुरंत पुन: उत्पन्न किया जा सकता है।

क्या कोई इस अजीब व्यवहार को समझा सकता है?

अद्यतन

यह eventlet की एक बग हो रहा है। यदि मैं करता हूं:

socketio = SocketIO(app, async_mode='threading') 

यह एप्लिकेशन को इवेंटलेट का उपयोग न करने के लिए मजबूर करता है हालांकि यह स्थापित है।

हालांकि, यह 'थ्रेडिंग' का उपयोग करने के लिए मेरे लिए एक लागू समाधान नहीं है क्योंकि async_mode बाइनरी डेटा स्वीकार करने से इंकार कर देता है। हर बार जब मैं क्लाइंट से सर्वर तक कुछ बाइनरी डेटा भेजने यह कहते हैं:

WebSocket transport not available. Install eventlet or gevent and gevent-websocket for improved performance.

तीसरा विकल्प, async_mode रूप gevent का उपयोग कर मेरे लिए काम नहीं करता है और साथ ही gevent अजगर 3 के लिए समर्थन नहीं है अभी तक।

तो कोई अन्य सुझाव?

+0

@rfkortekaas कैसे है कि एक अतुल्यकालिक प्रोटोकॉल में मतलब होता है? और इसके अलावा प्रतिक्रिया भेजी जाती है। यही "उत्सर्जित" करता है। दूसरी बात एक अलग धागे में हो रही है। – Schnodderbalken

+0

मैंने अपनी टिप्पणी हटा दी क्योंकि मैंने प्रश्न को गलत तरीके से पढ़ा था। – rfkortekaas

+0

मैं एक बहुत ही समान मुद्दे में भाग गया, लेकिन हम कम्प्यूटेशनल रूप से महंगा कुछ भी नहीं कर रहे थे। Socketio.emit को कॉल करते समय उचित "सॉकेटियो" को पकड़ने के साथ ऐसा लगता है। क्योंकि उत्सर्जन होता है, लेकिन कोई क्लाइंट संदेश प्राप्त नहीं करता है। Async_mode = 'थ्रेडिंग' जोड़ना समस्या को ठीक करना प्रतीत होता था। लेकिन उम्मीद है कि – AMB0027

उत्तर

6

मैंने कई पायथन कार्यों को बंदरगाह करके इस मुद्दे को हल करने में कामयाब रहा जिससे पाइथन मूल के बजाय ईवेंट फ़ंक्शन का उपयोग करने का कारण बनता है। इस तरह पृष्ठभूमि धागे इवेंटलेट के साथ ठीक काम करते हैं।

https://github.com/miguelgrinberg/Flask-SocketIO/blob/master/example/app.py#L30-L31

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