Yapmaya çalıştığım şey şu: On binlerce mobil cihazdan (redis ile işbirliği) amaç için uzun bağlantıları tutacak bir Node.js http sunucusu geliştiriyorum tek bir makinede müşteriler.Node.js ile uzun bağlantılar, bellek kullanımını azaltma ve bellek sızıntısını nasıl önleme? Ayrıca, V8 ve webkit-devtools ile ilgili:
Test ortamı: İlk anda
1.80GHz*2 CPU/2GB RAM/Unbuntu12.04/Node.js 0.8.16
, ben modül "ekspres" hangi ile ben RAM yeterli değildir yani kullanılan takas önce yaklaşık 120k eşzamanlı bağlantı ulaşabilir kullandı. Daha sonra, yerel "http" modülüne geçtim, yaklaşık 160k'a kadar eşzamanlılık elde ettim. Ancak, yerel http modülünde gerek duymadığım çok fazla işlevsellik olduğunu fark ettim, bu yüzden yerel "net" modülüne geçtim (bu, http protokolünü kendi başıma kullanmam gerektiği anlamına geliyor, ama bu sorun değil). Şimdi, tek bir makine için yaklaşık 250 bin eşzamanlı bağlantıya ulaşabilirim. İşte
benim kodlarının ana yapıdır: Son olarakvar net = require('net');
var redis = require('redis');
var pendingClients = {};
var redisClient = redis.createClient(26379, 'localhost');
redisClient.on('message', function (channel, message) {
var client = pendingClients[channel];
if (client) {
client.res.write(message);
}
});
var server = net.createServer(function (socket) {
var buffer = '';
socket.setEncoding('utf-8');
socket.on('data', onData);
function onData(chunk) {
buffer += chunk;
// Parse request data.
// ...
if ('I have got all I need') {
socket.removeListener('data', onData);
var req = {
clientId: 'whatever'
};
var res = new ServerResponse(socket);
server.emit('request', req, res);
}
}
});
server.on('request', function (req, res) {
if (res.socket.destroyed) {
return;
}
pendingClinets[req.clientId] = {
res: res
};
redisClient.subscribe(req.clientId);
res.socket.on('error', function (err) {
console.log(err);
});
res.socket.on('close', function() {
delete pendingClients[req.clientId];
redisClient.unsubscribe(req.clientId);
});
});
server.listen(3000);
function ServerResponse(socket) {
this.socket = socket;
}
ServerResponse.prototype.write = function(data) {
this.socket.write(data);
}
, benim sorular şunlardır: o uzak eşzamanlılık artırmak böylece
nasıl bellek kullanımını azaltabilir?
Ben node.js işlem bellek kullanımını nasıl hesaplanacağı konusunda gerçekten karıştı. Chrome V8 motordan node.js biliyorum orada process.memoryUsage() API olduğunu ve üç değerleri döndürür: rss/heapTotal/heapUsed, ben daha ilgili olması parçası Aralarındaki fark, bu, ve tam olarak ne bileþimini Node.js işlem tarafından kullanılan bellek?
- Ben bazı testler yaptık ve bir sorun var görünmüyor olsa bile bellek sızıntısı endişeleniyordu. Endişe etmem gereken ya da herhangi bir tavsiyem var mı?
- Ben açıklandığı gibi, sadece yukarıda benim kodları gibi benim genel nesneyipendingClients clientid tarafından adında bir özellik eklediğinizde o, demek yeni bir gizli sınıf olmak olacak, V8 hidden class hakkında bir dokümana bulundu oluşturulan? Doz bellek sızıntısına neden olur?
- Ben node.js sürecinin yığın haritasını analiz etmek webkit-devtools-agent kullandı. İşlemi başlattım ve bir yığın fotoğrafını çektim, daha sonra 10k istekleri yolladım ve daha sonra bunları kestim, bundan sonra tekrar bir yığın fotoğraf çektim. Bu iki anlık görüntü arasındaki farkı görmek için karşılaştırması bakış açısını kullandım. İşte sahip olduğum şey: Bunu açıklayan var mı? (Dizi)/(derlenmiş kod)/(dizgi)/Komut/Dizi sayısı ve boyutu çok arttı, bu ne anlama geliyor?
DÜZENLEME: nasıl yükleme testi kaçtın?
1. İlk olarak,
1.1 (bir makine en fazla 16 bit ile temsil edilen 60k + bağlantı() olması nedeniyle, birden fazla 60k eşzamanlılık birden fazla istemci makine mi elde etmek için) bir sunucu makinesinde parametreleri hem de müşteri makineleri modifiye .Sunucu ve istemci makineleri, ben dosya tanıtıcı test programı çalıştırmak olacak kabuğunda bu komutlarını kullanmak modifiye Hem tek:
ulimit -Hn 999999
ulimit -Sn 999999
1,2. Sunucu makinede, biraz da net/tcp ilgili çekirdek parametrelerini modifiye, en önemli olanları şunlardır:
net.ipv4.tcp_mem = 786432 1048576 26777216
net.ipv4.tcp_rmem = 4096 16384 33554432
net.ipv4.tcp_wmem = 4096 16384 33554432
1,3. istemci makinelere gibi:
net.ipv4.ip_local_port_range = 1024 65535
2. İkinci olarak, özel bir yazdı çoğu yük testi araçları beri, vb ab, kuşatma, kısa bağlantıları için, ama ben değilim, node.js kullanarak istemci programı simüle uzun bağlantıları kullanarak ve bazı özel gereksinimleri var. 3.
Sonra tek bir makinede sunucu programı ve diğer üç ayrı makinelere üç müşteri programı başladı.
DÜZENLEME: bunu çok anlamlı ve pratik değil, dışarı tek bir makinede (2GB RAM) üzerinde 250k eşzamanlı bağlantı ulaşmak yaptı ama döndü. Çünkü bir bağlantı kurulduğunda, bağlantıyı beklemede bırakıyorum, başka bir şey yok. Onlara yanıt göndermeye çalıştığımda, eşzamanlılık sayısı yaklaşık 150 bin dolar civarına düştü. Ben hesaplanırken, bağlantı başına yaklaşık 4KB daha fazla bellek kullanımı var, bu net.ipv4.tcp_wmem ile ilgili olduğunu düşünüyorum olarak ayarlanmış, ama ben daha küçük, hiçbir şey değişti. Nedenini anlayamıyorum.
DÜZENLEME: Aslında, şimdi ben tcp bağlantı başına ne kadar bellek kullanır ilgileniyorum ve tek bağlantısı tarafından kullanılan belleğin tam olarak kompozisyonu nedir? benim test verilerine göre: 1800M RAM hakkında tüketilen
150k eşzamanlılık ve node.js süreci (ücretsiz -m çıkış itibaren)
Sonra ben bu farz yaklaşık 600M RSS vardı:
(1800M - 600M)/150K = 8k, bu iki parçadan oluşur, bir bağlantı çekirdek TCP küme bellek kullanımı: tampon (4 KB) + yazma tamponu (okuma 4KB) (Aslında bu, sistemin nasıl bu tamponlar için kullanmak ne kadar bellek belirler?)
net.ipv4.tcp_rmem ve net.ipv4.tcp_wmem yukarıdaki benim ayarını eşleşmiyor 600M/150k = 4k, bu tek bir bağlantı
ait node.js bellek kullanımı Birazdan muyum nedir? Bellek kullanımını her iki açıdan nasıl azaltabilirim?
Eğer iyi tanımlamamış bir yer varsa, bana bildirin, ben onu daraltacağım! Herhangi bir açıklama veya tavsiye takdir edilecektir, teşekkürler!
İlk izlenim, bu özelliklerin bulunduğu bir makinede 250k'nın şaşırtıcı olmasıdır. Şu an için endişelendiğin tüm kullanıcılara odaklanmak için zaman olabilir. = P – tehgeekmeister
Eşzamanlı bağlantıların sayısını nasıl ölçüyorsunuz? – tehgeekmeister
Yan not: Bir stackexchange sitesinden istendiğinde daha az sayıda belirli soruna bağlı kalmak en iyisidir. Bu şekilde daha fazla cevap alacaksınız. – tehgeekmeister