2012-10-25 8 views
5

मैं एक node.js स्क्रिप्ट लिख रहा हूं जो एक कनेक्टेड सॉकेट से डेटा लेता है और इसे किसी अन्य कनेक्टेड सॉकेट में भेजता है। परीक्षण के दौरान मैंने देखा कि यदि कोई सर्वर बड़ी मात्रा में डेटा भेज रहा है, तो मैं एक डिस्क को डिस्कनेक्ट और फिर से कनेक्ट करता हूं, मुझे स्मृति रिसाव मिलती है। निम्नलिखित node.js कोड है।node.js स्क्रिप्ट और संभावित मेमोरी लीक

var net = require('net'); 
var logServer = net.createServer(); 
var clientList = []; 
var clientIPList = []; 
var serverList = []; 
var serverIPList = []; 
var port = 6451; 

logServer.on('connection', function(client) { 
    client.setEncoding('utf8'); 
    client.once('data', function(data) { 
     if (data[0].toString() == 'S') { 
      var server = client; 
      client = undefined; 
      serverList.push(server); 
      serverIPList.push(server.remoteAddress + ":" + server.remotePort); 
      console.log('Server connected: %s:%d', server.remoteAddress, server.remotePort); 

      server.on('data', function(data) { 
       for(var i=0;i<clientList.length;i+=1) { 
        try { 
         clientList[i].write(data); 
        } catch (err) { 
         console.log('Error writing to client "data event": ' + clientIPList[i]); 
         // close and null the socket on write error 
         try { 
          clientList[i] = null; 
          clientList[i].end(); 
         } catch (err) {} 
         clientList.splice(i, 1); 
         clientIPList.splice(i, 1); 
        } 
       }    
      }) 

      server.on('end', function() { 
       try { 
        var d; 
        if((d = serverList.indexOf(server)) != -1) { 
         console.log('Server disconnecting "end event": ' + serverIPList[d]); 
         try { 
          serverList[d] = null; 
          serverList[d].end(); 
         } catch (err) {} 
         serverList.splice(d, 1); 
         serverIPList.splice(d, 1); 
        } 
        else { 
         console.log('Server disconnecting "end event": unknown server');      
        } 
       } catch (err) { 
        console.log('Error cleaning up server socket list on "end event"'); 
       } 
      }) 

      server.on('timeout', function() { 
       try { 
        var d; 
        if((d = serverList.indexOf(server)) != -1) { 
         console.log('Server disconnecting "timeout event": ' + serverIPList[d]); 
         try { 
          serverList[d] = null; 
          serverList[d].end(); 
         } catch (err) {} 
         serverList.splice(d, 1); 
         serverIPList.splice(d, 1); 
        } 
        else { 
         console.log('Server disconnecting "timeout event": unknown server');      
        } 
       } catch (err) { 
        console.log('Error cleaning up server socket list on "timeout event"'); 
       } 
      }) 

      server.on('error', function(e) { 
       try { 
        var d; 
        if((d = serverList.indexOf(server)) != -1) { 
         console.log('Server disconnecting ' + e.code + ' "error event": ' + serverIPList[d]); 
         try { 
          serverList[d] = null; 
          serverList[d].end(); 
         } catch (err) {} 
         serverList.splice(d, 1); 
         serverIPList.splice(d, 1); 
        } 
        else { 
         console.log('Server disconnecting "error event": unknown server');     
        } 
       } catch (err) { 
        console.log('Error cleaning up server socket list on "error event"'); 
       } 
      }) 

      server.on('close', function() { 
       try { 
        var d; 
        if((d = serverList.indexOf(server)) != -1) { 
         console.log('Server disconnecting "close event": ' + serverIPList[d]); 
         try { 
          serverList[d] = null; 
          serverList[d].end(); 
         } catch (err) {} 
         serverList.splice(d, 1); 
         serverIPList.splice(d, 1); 
        } 
       } catch (err) { 
        console.log('Error cleaning up server socket list on "close event"'); 
       } 
      }) 
      server.on('drain', function() { 
      }) 
     } 

     else { 
      clientList.push(client); 
      clientIPList.push(client.remoteAddress + ":" + client.remotePort); 
      console.log('Client connected: %s:%d',client.remoteAddress, client.remotePort); 

      client.on('data', function(data) { 
       console.log('writing "%s" to %d servers', data.replace(/[\r\n]/g,''), serverList.length); 
       for(var i=0;i<serverList.length;i+=1) { 
        try { 
         serverList[i].write(data); 
        } catch (err) { 
         console.log('Error writing to server "data event": ' + serverIPList[i]); 
         try { 
          serverList[i] = null; 
          serverList[i].end(); 
         } catch (err) {} 
         serverList.splice(i, 1); 
         serverIPList.splice(i, 1); 
        } 
       } 
      }) 

      client.on('end', function() { 
       try { 
        var d; 
        if((d = clientList.indexOf(client)) != -1) { 
         console.log('Client disconnecting "end event": ' + clientIPList[d]); 
         // close and null the socket 
         try { 
          clientList[d] = null; 
          clientList[d].end(); 
         } catch (err) {} 
         clientList.splice(d, 1); 
         clientIPList.splice(d, 1); 
        } 
        else { 
         console.log('Client disconnecting "end event": unknown client'); 
        }    
       } catch (err) { 
        console.log('Error cleaning up socket client list on "end event"'); 
       } 
      }) 

      client.on('timeout', function() { 
       try { 
        client.end(); 
       } catch (err) { 
        var d; 
        if((d = clientList.indexOf(client)) != -1) { 
         console.log('Error closing client connection "timeout event": ' + clientIPList[d]); 
        } 
        else { 
         console.log('Error closing client connection "timeout event": unknown client');     
        } 
       }    
       try { 
        var d; 
        if((d = clientList.indexOf(client)) != -1) { 
         console.log('Client disconnecting "timeout event": ' + clientIPList[d]); 
         try { 
          clientList[d] = null; 
          clientList[d].end(); 
         } catch (err) {} 
         clientList.splice(d, 1); 
         clientIPList.splice(d, 1); 
        } 
        else { 
         console.log('Client disconnecting "timeout event": unknown client'); 
        }    
       } catch (err) { 
        console.log('Error cleaning up client socket list on "timeout event"'); 
       } 
      }) 

      client.on('error', function(e) { 
       try { 
        var d; 
        if((d = clientList.indexOf(client)) != -1) { 
         console.log('Client disconnecting ' + e.code + ' "error event": ' + clientIPList[d]); 
         try { 
          clientList[d] = null; 
          clientList[d].end(); 
         } catch (err) {} 
         clientList.splice(d, 1); 
         clientIPList.splice(d, 1); 
        } 
        else { 
         console.log('Client disconnecting ' + e.code + ' "error event": unknown client'); 
        }    
       } catch (err) { 
        console.log('Error cleaning up client socket list on "error event"'); 
       } 
      }) 

      client.on('close', function() { 
       try { 
        var d; 
        if((d = clientList.indexOf(client)) != -1) { 
         console.log('Client disconnecting "close event": ' + clientIPList[d]); 
         try { 
          clientList[d] = null; 
          clientList[d].end(); 
         } catch (err) {} 
         clientList.splice(d, 1); 
         clientIPList.splice(d, 1); 
        } 
       } catch (err) { 
        console.log('Error cleaning up client socket list on "close event"'); 
       } 
      }) 

      client.on('drain', function() { 
       // nothing 
      }) 
     } 
    }) 
}) 
logServer.listen(port); 

जहाँ तक मुझे पता है, मैं सभी गंभीर 'शुद्ध' घटनाओं सौंपने रहा हूँ और मैं ठीक से सॉकेट की सफाई कर रहा हूँ, एक बार मैं एक डिस्कनेक्ट का पता लगाने के रूप में। यहां दो स्क्रिप्ट्स हैं जिनका मैं परीक्षण करने के लिए उपयोग कर रहा हूं। पहला क्लाइंट के रूप में बस कनेक्ट और डिस्कनेक्ट करता है और दूसरा सर्वर के रूप में डेटा भेजता है। मैं उन्हें एक साथ दोनों चलाता हूं।

condiscon.rb: क्लाइंट के रूप में खुद को पंजीकृत करने के बाद कनेक्ट और डिस्कनेक्ट हो जाता है "एक बार कनेक्ट होने पर एक नई लाइन भेजता है"। मैं के साथ '1000 ./condiscon.rb'

#!/usr/bin/ruby 

require 'rubygems' 
require 'socket' 

def connectFlac 
    host = '10.211.55.10' 
    port = 6451 

    sock = TCPSocket.open(host, port) 
    sock.puts("") 
    sock 
end 

sock = connectFlac() 
data = [] 
user_agents = {} 
instances_lat = {} 

count = ARGV.shift.to_i 

while(count > 0) 
    sock = connectFlac() 
    sleep(0.05) 
    sock.close() 
    sleep(0.05) 
    count-= 1 
end 

dataflood.rb चलाएँ: एक सर्वर के रूप में कनेक्ट करता है और भेजता है ~ की 2600 बाइट पैकेट एक काउंटर के साथ abcde। मैं 'dataflood.rb 30000'

#!/usr/bin/ruby 

require 'socket' 

def connectFlac 
    host = '10.211.55.10' 
    port = 6451 

    sock = TCPSocket.open(host, port) 
    sock.setsockopt(Socket::IPPROTO_TCP,Socket::TCP_NODELAY,1) 
    sock.puts("S") 
    sock 
end 

def syntax() 
    print "./script number_of_packets\n" 
    exit(1) 
end 

data = "" 
(1..100).each { 
    data+= "abcdefghijklmnopqrstuvwxyz" 
} 

sock = connectFlac() 

numpackets = ARGV.shift.to_i || syntax() 
counter = 1 
byteswritten = 0 

while(numpackets > 0) 
    r,w,e = IO.select(nil, [sock], nil, nil) 
    w.each do |sock_write| 
     print numpackets, "\n" 
     sock.write(counter.to_s + "|" + data + "\n") 
     sock.flush() 
     byteswritten+= counter.to_s.length + 1 + data.length + 1 
     counter+= 1 
     numpackets-= 1 
    end 
end 
sock.close() 

print "Wrote #{byteswritten} bytes\n" 

यहां कुछ परिणाम देख रहे हैं जो मैं देख रहा हूं। किसी भी परीक्षण से पहले logserver.js पर मेमोरी प्रोफाइल चलाते समय यह लगभग 9 मेगाबाइट निवासी स्मृति का उपयोग करता है। मैं स्मृति के खंड को दिखाने के लिए एक pmap सहित हूँ कि रिसाव पर कब्जा प्रतीत होता है।

[[email protected] ~]# ps vwwwp 20658 
    PID TTY  STAT TIME MAJFL TRS DRS **RSS** %MEM COMMAND 
20658 pts/4 Sl+ 0:00  0 8100 581943 **8724** 0.8 /usr/local/node-v0.8.12/bin/node logserverdemo.js 

[[email protected] ~]# pmap 20658 
20658: /usr/local/node-v0.8.12/bin/node logserverdemo.js  
0000000000400000 8104K r-x-- /usr/local/node-v0.8.12/bin/node  
0000000000de9000  76K rwx-- /usr/local/node-v0.8.12/bin/node  
0000000000dfc000  40K rwx-- [ anon ]  
**000000001408a000 960K rwx-- [ anon ]**  
0000000040622000  4K ----- [ anon ] 

एएमई यहां कभी logserver के खिलाफ उपरोक्त दो गहरे लाल रंग का स्क्रिप्ट चलाने के बाद स्मृति के बारे में 30 मिनट की तरह लग रहा है क्या यातायात बंद हो जाता है के बाद है। (मैं सभी जीसी होने की इंतजार कर रहे थे)

[[email protected] ~]# ps vwwwp 20658 
    PID TTY  STAT TIME MAJFL TRS DRS RSS %MEM COMMAND 
20658 pts/4 Sl+ 0:01  0 8100 665839 **89368** 8.7 /usr/local/node-v0.8.12/bin/node logserverdemo.js 

[[email protected] ~]# pmap 20658 
20658: /usr/local/node-v0.8.12/bin/node logserverdemo.js 

0000000000400000 8104K r-x-- /usr/local/node-v0.8.12/bin/node 
0000000000de9000  76K rwx-- /usr/local/node-v0.8.12/bin/node  
0000000000dfc000  40K rwx-- [ anon ]  
**000000001408a000 80760K rwx-- [ anon ]** 
0000000040622000  4K ----- [ anon ] 
0000000040623000  64K rwx-- [ anon ] 

dataflood.rb डेटा के 78,198,894 बाइट्स की कुल लिखा था और रिसाव बहुत करीब है। मैंने मेमोरी को 0x1408a000 पर छोड़ दिया और मैंने देखा कि डेटाफ्लू.आरबी से भेजे जा रहे अधिकांश पैकेट स्मृति में फंस गए थे।

[[email protected] ~]# ./memoryprint 20658 0x1408a000 80760000 > 20658.txt 
[[email protected] ~]# strings 20658.txt | grep '|abcde' | wc -l 
30644 
[[email protected] ~]# strings 20658.txt | grep '|abcde' | sort | uniq | wc -l 
29638 

24 घंटे प्रतीक्षा करने के बाद स्मृति अभी भी मुक्त नहीं हुई थी। कोई भी मदद जो मुझे दे सकती है उसकी सराहना की जाएगी।

+0

मुझे अब भी यही समस्या आ रही है। बहुत कम कोड वाला मेरा प्रॉक्सी सर्वर लीक हो रहा है, और प्रोफाइलिंग कुछ भी नहीं दिखा रहा है। – majidarif

उत्तर

0

शायद रिसाव के कारण नहीं है, लेकिन आप अंत कर रहे हैं() सॉकेट ing आप अशक्त करने के लिए उन्हें सेट करने के बाद:

clientList[i] = null; 
clientList[i].end(); 

कि दूसरी तरह के आसपास नहीं होना चाहिए?

0

यह समस्या इनपुट स्ट्रीम और आउटपुट स्ट्रीम के बीच गति के असंतुलन के कारण हो सकती है।

नीचे स्रोत कोड बदलने का प्रयास करें।

<AS-IS> 

server.on('data', function(data) { 
       for(var i=0;i<clientList.length;i+=1) { 
        try { 
         clientList[i].write(data); 
        } catch (err) { 
         console.log('Error writing to client "data event": ' + clientIPList[i]); 
         // close and null the socket on write error 
         try { 
          clientList[i] = null; 
          clientList[i].end(); 
         } catch (err) {} 
         clientList.splice(i, 1); 
         clientIPList.splice(i, 1); 
        } 
       }    
      }) 

<TO-BE> 

for(var i=0;i<clientList.length;i+=1) { 
    try { 
     server.pipe(clientList[i]); 
    } catch (err) { 
     console.log('Error writing to client "data event": ' + clientIPList[i]); 
     // close and null the socket on write error 
     try { 
      clientList[i] = null; 
      clientList[i].end(); 
     } catch (err) {} 
      clientList.splice(i, 1); 
      clientIPList.splice(i, 1); 
     } 
    }    
} 

यह कोड आपकी स्मृति समस्या को समायोजित करेगा।