2011-12-19 16 views
10

मैं Socket.io को native load balancing ("क्लस्टर") के साथ बहु-थ्रेड किए जाने के लिए Node.js v.0.6.0 और बाद में काम करने के लिए देख रहा हूं।Node.js, बहु-थ्रेडिंग और सॉकेट.io

जो मैं समझता हूं उससे, सॉकेट.ओ अपने आंतरिक डेटा को स्टोर करने के लिए रेडिस का उपयोग करता है। मेरी समझ यह है: प्रत्येक कार्यकर्ता के लिए एक नया रेडिस उदाहरण पैदा करने के बजाय, हम मजदूरों को उसी रेडिस इंस्टेंस को मास्टर के रूप में उपयोग करने के लिए मजबूर करना चाहते हैं। इस प्रकार, कनेक्शन डेटा सभी श्रमिकों में साझा किया जाएगा। मास्टर में

कुछ इस तरह:

RedisInstance = new io.RedisStore; 

हम किसी भी तरह श्रमिकों को RedisInstance गुजरती हैं और निम्न करना होगा: वर्ष, 3 पार्टी क्लस्टर मॉड्यूल का उपयोग कर this implementation द्वारा

io.set('store', RedisInstance); 

प्रेरित होकर , मेरे पास निम्नलिखित गैर-कार्यशील कार्यान्वयन है:

var cluster = require('cluster'); 
var http = require('http'); 
var numCPUs = require('os').cpus().length; 

if (cluster.isMaster) { 
    // Fork workers. 
    for (var i = 0; i < numCPUs; i++) { 
    cluster.fork(); 
    } 

    var sio = require('socket.io') 
    , RedisStore = sio.RedisStore 
    , io = sio.listen(8080, options); 

    // Somehow pass this information to the workers 
    io.set('store', new RedisStore); 

} else { 
    // Do the work here 
    io.sockets.on('connection', function (socket) { 
    socket.on('chat', function (data) { 
     socket.broadcast.emit('chat', data); 
    }) 
    }); 
} 

विचार? मैं पूरी तरह गलत दिशा में जा रहा हूं, कोई भी कुछ विचारों को इंगित कर सकता है?

+1

मुझे आश्चर्य है कि क्या दृष्टिकोण आप उपयोग कर अंत। –

उत्तर

10

वास्तव में अपने कोड इस तरह दिखना चाहिए:

var cluster = require('cluster'); 
var http = require('http'); 
var numCPUs = require('os').cpus().length; 

if (cluster.isMaster) { 
    // Fork workers. 
    for (var i = 0; i < numCPUs; i++) { 
    cluster.fork(); 
    } 
} else { 
    var sio = require('socket.io') 
    , RedisStore = sio.RedisStore 
    , io = sio.listen(8080, options); 

    // Somehow pass this information to the workers 
    io.set('store', new RedisStore); 

    // Do the work here 
    io.sockets.on('connection', function (socket) { 
    socket.on('chat', function (data) { 
     socket.broadcast.emit('chat', data); 
    }) 
    }); 
} 

एक अन्य विकल्प कई बंदरगाहों पर सुनने और HAProxy लोड संतुलन सामान की तरह कुछ है करने के लिए Socket.IO खोलने के लिए है। वैसे भी आप सबसे महत्वपूर्ण बात जानते हैं: RedisStore का उपयोग प्रक्रिया के बाहर स्केल करने के लिए!

संसाधन:

http://nodejs.org/docs/latest/api/cluster.html
How can I scale socket.io?
How to reuse redis connection in socket.io?
Node: Scale socket.io/nowjs - scale across different instances
http://delicious.com/alessioaw/socket.io

+0

क्या वह कार्यान्वयन प्रत्येक कार्यकर्ता के लिए एक नया RedisStore नहीं बनाएगा? इसके अलावा, HAPROxy जैसे कुछ का उपयोग करने का क्या फायदा होगा? लगता है कि नोड में मूल रूप से उपस्थित कार्यक्षमता का उपयोग करना बेहतर है। –

+2

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

+0

मैंने अभी आपके कोड नमूने की कोशिश की, ऐसा लगता है कि काम नहीं कर रहा है। जब एकल-थ्रेडिंग, 1500 कनेक्शन 50% CPU तक चलाते हैं (प्रत्येक कार्यकर्ता नमूना के मुकाबले थोड़ा अधिक काम कर रहा है)। अपने नमूने का उपयोग करते हुए, * हर * प्रक्रिया 80-90% सीपीयू तक चलने से पहले मुझे 500 कनेक्शन तक नहीं मिल सकता है। तो स्पष्ट रूप से, कुछ गलत है क्योंकि यह स्थिति खराब कर रहा है। –

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