2015-11-21 7 views
13

मेरा उपयोग-मामला इस प्रकार है: मैं अपने नोड सर्वर से सार्वजनिक एपीआई में बहुत सी एपीआई कॉल करता हूं। कभी-कभी प्रतिक्रिया बड़ी होती है और कभी-कभी इसका छोटा होता है। मेरा उपयोग-केस मुझे जेएसओएन प्रतिक्रिया को मजबूत करने की मांग करता है। मुझे एक बड़ा JSON पता है क्योंकि प्रतिक्रिया मेरे इवेंट लूप को अवरुद्ध करने जा रही है। कुछ शोधों के बाद मैंने इन प्रतिक्रियाओं को पार्स करने के लिए child_process.fork का उपयोग करने का निर्णय लिया, ताकि अन्य एपीआई कॉलों की प्रतीक्षा न हो। मैंने अपनी मुख्य प्रक्रिया से फोर्क किए गए बच्चे_प्रोसेस में एक बड़ी 30 एमबी जेएसओएन फाइल भेजने की कोशिश की। बच्चे की प्रक्रिया को चुनने और जेसन को पार्स करने में बहुत लंबा समय लगता है। बच्चे की प्रक्रिया से होने वाली प्रतिक्रिया मैं बहुत बड़ी नहीं है। मैं बस स्ट्रिंग करना और लंबाई प्राप्त करना चाहता हूं और मुख्य प्रक्रिया पर वापस भेजना चाहता हूं।Node.js - child_process को एक बड़ी वस्तु भेजना धीमा है

मैं मास्टर और बाल कोड को जोड़ रहा हूं।

var moment = require('moment'); 
var fs = require('fs'); 
var process = require('child_process'); 
var request = require('request'); 

var start_time = moment.utc().valueOf(); 

request({url: 'http://localhost:9009/bigjson'}, function (err, resp, body) { 

    if (!err && resp.statusCode == 200) { 

    console.log('Body Length : ' + body.length); 

    var ls = process.fork("response_handler.js", 0); 

    ls.on('message', function (message) { 
     console.log(moment.utc().valueOf() - start_time); 
     console.log(message); 
    }); 
    ls.on('close', function (code) { 
     console.log('child process exited with code ' + code); 
    }); 
    ls.on('error', function (err) { 
     console.log('Error : ' + err); 
    }); 
    ls.on('exit', function (code, signal) { 
     console.log('Exit : code : ' + code + ' signal : ' + signal); 
    }); 
    } 
    ls.send({content: body}); 
}); 

response_handler.js

console.log("Process " + process.argv[2] + " at work "); 

process.on('message', function (json) { 
    console.log('Before Parsing'); 
    var x = JSON.stringify(json); 
    console.log('After Parsing'); 
    process.send({msg: 'Sending message from the child. total size is' + x.length}); 
}); 

वहाँ im करने का प्रयास कर क्या हासिल करना एक बेहतर तरीका है? एक तरफ मुझे प्रति सेकंड 1000 एपीआई कॉल करने के लिए node.js की शक्ति की आवश्यकता होती है, लेकिन कभी-कभी मुझे एक बड़ा JSON वापस मिलता है जो चीजों को खराब करता है।

+0

आपका दृष्टिकोण ठीक लगता है। जब आप "मेरा नोड सर्वर" कहते हैं, तो मैं इसे एक प्रक्रिया मानता हूं जो ग्राहकों की सेवा करता है।क्या आपको वास्तव में अपने सर्वर के अंदर से एपीआई कॉल करने की ज़रूरत है? क्या आप कार्य को विभिन्न प्रक्रियाओं में विभाजित नहीं कर सकते हैं और उनके और आपके सर्वर के बीच एक संदेश ब्रोकर, रेडिस, या बस पाइप या आईपीसी के किसी अन्य रूप जैसे संचार चैनल सेट कर सकते हैं? – kliron

+0

मेरा बुरा, इसे सर्वर के रूप में कॉल करने के लिए, आप इसे एजेंट मान सकते हैं। यह किसी की सेवा नहीं कर रहा है। यह एजेंट एक उच्च स्केलेबल एपीआई क्लाइंट के रूप में कार्य करता है। – Vinoth

+0

शायद आप JSON के साथ एक बड़े ब्लॉक में ऐसा करने के बजाय स्ट्रीमिंग जेसन पार्सर का उपयोग कर सकते हैं। – mcfedr

उत्तर

3

आपका काम आईओ-बाउंड (30 एमबी आकार का जेएसओएन लाने) लगता है, जहां नोड की असिंक्रोनिटी चमकती है, साथ ही साथ सीपीयू-बाउंड (30 एमबी आकार का जेएसओएन पार्सिंग) जहां एसिंच्रोनिटी आपकी मदद नहीं करती है।

बहुत सारी प्रक्रियाओं को फोर्किंग जल्द ही एक संसाधन हॉग बन जाती है और प्रदर्शन घट जाती है। सीपीयू-बाध्य कार्यों के लिए आपको उतनी ही प्रक्रियाओं की आवश्यकता होती है जितनी आपके पास कोर हैं और नहीं।

मैं एन अन्य प्रक्रियाओं को लाने और प्रतिनिधि पार्सिंग करने के लिए एक अलग प्रक्रिया का उपयोग करता हूं, जहां एन आपके सीपीयू कोर की संख्या 1 से अधिक है और प्रक्रिया संचार के लिए आईपीसी के कुछ रूपों का उपयोग करता है।

एक विकल्प नोड के क्लस्टर मॉड्यूल का उपयोग करने के लिए ऊपर के सभी रच के लिए है: https://nodejs.org/docs/latest/api/cluster.html

इस मॉड्यूल का उपयोग करके आप एक मास्टर प्रक्रिया अग्रिम अपने कार्यकर्ता प्रक्रियाओं बना सकते हैं और चिंता करने की जब कांटा की जरूरत नहीं है हो सकता है, बनाने के लिए कितनी प्रक्रियाएं, आदि आईपीसी सामान्य रूप से process.send और process.on के साथ काम करता है। तो एक संभावित वर्कफ़्लो है:

  1. एप्लिकेशन स्टार्टअप: मास्टर प्रक्रिया एक "फ़ेचर" और एन "पार्सर" प्रक्रियाएं बनाती है।
  2. फ़ेचर को प्रक्रिया के लिए एपीआई एंडपॉइंट्स की एक कार्य सूची भेजी जाती है और जेएसओएन को मास्टर प्रोसेस पर वापस भेजना शुरू कर देता है। प्रत्येक JSON पर
  3. मास्टर ने एक पार्सर प्रक्रिया में भेज दिया। आप उन्हें राउंड-रॉबिन फैशन में उपयोग कर सकते हैं या मास्टर प्रक्रिया में सिग्नल करने का एक अधिक परिष्कृत तरीका उपयोग कर सकते हैं जब एक पार्सर वर्क कतार खाली है या कम चल रहा है।
  4. पार्सर प्रक्रिया परिणामी JSON ऑब्जेक्ट को मास्टर पर वापस भेजती है।

ध्यान दें कि आईपीसी में गैर-तुच्छ ओवरहेड भी है, खासकर जब बड़ी वस्तुओं को भेजना/प्राप्त करना। आप इस से बचने के लिए चारों ओर गुजरने के बजाय भ्रूण भी बहुत छोटे प्रतिक्रियाओं का विश्लेषण कर सकते हैं। यहां "छोटा" शायद < 32 केबी है।

यह भी देखें: Is it expensive/efficient to send data between processes in Node?

+0

यह वही है जो मैं करने की कोशिश कर रहा था। मुख्य धागा विभिन्न एपीआई से सभी सामग्रियों को लाने और अलग प्रक्रियाओं द्वारा गणना करने के लिए गणना करने जा रहा है। यहां समस्या इन नई प्रक्रियाओं के जवाब पारित कर रही है। मैंने एक सरलीकृत उदाहरण दिया है, जहां ऐसा लगता है कि मैं प्रतिक्रियाओं के रूप में कई प्रक्रियाओं को बनाने जा रहा हूं। लेकिन मैं निश्चित रूप से इसे कोर की संख्या तक सीमित करने की योजना बना रहा हूं। हालांकि यह नहीं मिल रहा है कि इसे नोड क्लस्टर द्वारा कैसे व्यवस्थित किया जा सकता है। अगर मुझे कुछ याद आ रहा है तो मुझे बताएं। यदि आपके पास कोई संकेतक है, तो कृपया मुझे उस पर इंगित करें। अपनी प्रतिक्रिया की सराहना करें। – Vinoth

+0

@ विनोथ मैंने जवाब अपडेट किया। क्लस्टर के लिए प्रलेखन पर एक नज़र डालें, यह काफी सरल है। – kliron

+0

बीमार कोशिश करें। ऐसा लगता है कि यहां पर धारणा मास्टर से पार्सर्स के लिए बड़े जेसन को पाइप कर रही है, मेरे उदाहरण में जितना समय लगता है उतना समय नहीं लेगा। मैं child_process.fork() का उपयोग कर रहा हूं। चूंकि नोड क्लस्टर आंतरिक रूप से child_process.fork() का उपयोग करता है, मुझे आश्चर्य है कि यह कैसे भिन्न व्यवहार कर सकता है। मैं इसे पुष्टि करने के लिए एक शॉट दे। प्रतिक्रिया की सराहना करें। – Vinoth

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