SORU
27 Aralık 2012, PERŞEMBE


Bellek kullanımını azaltmak ve bellek sızıntısı önlemek için nasıl node.js uzun bir bağlantısı var mı? V8 ile de ilgili ve aynı zamanda y-devtools

Burada ne yapmaya çalışıyorum: Ben gelişmekte olan bir Node.js http Sunucusu, güçlü ol uzun bağlantılar için bastırıyor amaç(işbirliği ile redis) on binlerce mobil istemcileri tek bir makine.

Test ortamı olarak kullanılmalıdır

1.80GHz*2 CPU/2GB RAM/Unbuntu12.04/Node.js 0.8.16

İlk anda, "yaklaşık 120 k eşzamanlı bağlantı önce ulaşamadım" modülü, RAM yeterli değil demek ki. kullanılan takas ifade kullandım Daha sonra, yerel "" modülü, yaklaşık 160 k. eşzamanlılık var http geçtim Ama anladım ki orada hala çok fazla işlevselliği gerek yok yerli http modülü, o yüzden değiştirdim bu yerli "net" modülü(bu demek istiyorum tanıtıcı http protokolü kendimi, ama sorun değil). şimdi, tek makine başına yaklaşık 250 bin eş zamanlı bağlantı ulaşabilirim.

İşte benim kodları ana yapısı:

var 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);
}

Son olarak, burada benim soru:

  1. Nasıl eşzamanlılık daha artırmak için bellek kullanımını azaltabilir miyim?

  2. Gerçekten node.js işlemin bellek kullanımını hesaplamak için nasıl hakkında karıştı. Node.js Krom ile güçlendirilmiş V8, olduğunu biliyorumsüreç.() memoryUsageapı ve geri üç değer: rss/heapTotal/heapUsed, ne onlarla aramızdaki fark, hangi bölümü kullanmalıyım endişe daha fazla, ve ne tam olarak kompozisyon tarafından kullanılan bellek Node.js süreç?

  3. Bazı testler yaptım bile olsa bellek sızıntısı merak ettim bir sorun yok gibi. Endişe etmeli miyim ya da herhangi bir tavsiye herhangi bir nokta var mı?

  4. Tarif ettiği gibi V8 hidden class hakkında bir doktor, bir özelliği adında eklemek için zaman anlamına mı geliyor buldumclientıdküresel nesne benim içinpendingClientsyeni gizli bir sınıf olacak benim yukarıda kodları oluşturulmuş olması gibi mi? Bellek sızıntısı neden olur doz?

  5. webkit-devtools-agent node.js sürecin yığın harita analiz etmek için kullandım. Süreç başladı ve bir yığın anlık aldı, sonra da bir yığın anlık tekrar aldım sonra o 10k istekleri gönderdim ve daha sonra bağlantısı kesildi. Kullandımkarşılaştırmabakış açısı bu iki fotoğraf arasında farkı görmek için. Ne var burada: enter image description here Biri bunu açıklayabilir mi? (Dizi) (kod derlenmiş) (string)///Komut/Dizi sayısı çok artmış, bu ne anlama geliyor?

EDİT: Nasıl yükleme testini yaptım?
1. Öncelikle, ben değiştirilmiş bazı parametreler her iki makine üzerinde sunucu ve istemci makineler için) elde etmek için daha fazla 60bin eşzamanlılık gereken birden fazla istemci makine, çünkü bir makine sadece 60bin port(tarafından temsil edilen 16 bit) en fazla seçilebilir)
1.1. Her iki sunucu ve istemci makineleri, test programı çalıştırmak olacak dosya tanımlayıcısı kabuğunda Bu komutları kullanmak değiştirdim:

ulimit -Hn 999999
ulimit -Sn 999999

1.2. Sunucu makinede, ben de en önemlileri tcp ilgili çekirdek parametreleri/net değiştirilmiş,:

net.ipv4.tcp_mem = 786432 1048576 26777216
net.ipv4.tcp_rmem = 4096 16384 33554432
net.ipv4.tcp_wmem = 4096 16384 33554432

1.3. İstemci makineler için:

net.ipv4.ip_local_port_range = 1024 65535

2. İkinci olarak, yazdığım bir özel taklit istemci programı kullanarak Node.js yana en yük test araçları, ab, kuşatma, vb, kısa bağlantı, ama ben kullanıyorum uzun bağlantılar ve bazı özel gereksinimleri.
3. Sonra diğer üç ayrı makinelerde, tek ve üç makine bir istemci program, sunucu programın başladım.

EDİT: Tek bir makine(2 GB RAM) 250 bin eş zamanlı bağlantı ulaşamadığım, ama çıktı, çok anlamlı ve pratik değil. Bir bağlantı bağlı çünkü, ben sadece bir bağlantı, başka bir şey bekleyen edelim. Kendisine gönderilen yanıt için çalışırken, eşzamanlılık sayısı 150 k civarında aşağı düştü. Yaklaşık 4 KB daha fazla bellek kullanımı var bağlantı başına hesapladım olarak, ilgili sanırımnet.ıpv4.tcp_wmemiçin yola çıktım4096 16384 33554432ama küçük için düzenledim bile, değişen bir şey yok. Neden olduğunu çözemiyorum.

EDİT: Aslında, bellek, tek bir bağlantı tarafından kullanılan tam olarak bileşimi nedir ne kadar tcp bağlantı başına bellek kullanır ve daha çok ilgileniyorum? Benim test verilerine göre:

150 k eşzamanlılık 1800M RAM hakkında tüketilen(danfree-mçıkış), ve Node.js bu süreç yaklaşık 600 milyon RSS vardı

Sonra, düşündüm:

  • (1800M - 600) / 150 k = 8 k, bu çekirdek TCP yığın bellek kullanımı tek bir bağlantı, iki bölümden oluşur: okuma arabelleği(4 KB) yazma olayı(4 KB)(Aslında, bu uymuyor benim ayarınet.ıpv4.tcp_rmemvenet.ıpv4.tcp_wmemyukarıdaki sistem nasıl ne kadar bu arabellekleri için kullanmak belirler?)

  • = 600 MİLYON / 150 K 4 K, bu tek bir bağlantı node.js bellek kullanımı

Haksız mıyım? Nasıl her iki bakımdan da bellek kullanımını azaltabilir miyim?

Eğer iyi tarif edemedim yerde varsa, bana bildirin, tasfiye edeceğim! Açıklamalar veya herhangi bir tavsiye takdir edilecektir, teşekkür ederim!

CEVAP
29 Aralık 2012, CUMARTESİ


  1. Daha fazla bellek kullanımını azaltma hakkında endişelenmenize gerek yok bence. Bu okuma sizi dahil, minimum akla (ben bir birim Belirli değil standart olan bayt olarak yorumlamak) için çok uzak değil gibi görünüyor.

  2. Bu cevap daha derinlemesine bir soru olacak ama RSS. Yığın dinamik olarak ayrılan bellek nereden geldiğini anladığım kadarıyla en iyi unıx sistemleri. Yani, öbek öbek toplam kullanılan kullandın ne ise kullanım için öbek üzerinde tahsis edilen tüm olacak gibi görünüyor.

  3. Bellek kullanımı oldukça iyi, ve gerçekten bir sızıntı var gibi görünmüyor. Henüz endişelenmeyin. =]

  4. Bilmiyorum.

  5. Bu görüntü, makul görünüyor. Nesneleri istekleri dalgalanma oluşturulan bazı çöp toplandı bekliyorum, ve diğerleri yoktu. 10k nesne üzerinde bir şey yok görüyorsunuz, ve bu nesnelerin çoğu oldukça küçük. O kadar iyi diyorum.

Daha da önemlisi, yük bu test nasıl olduğunu merak ediyorum. Denedim yapmak büyük yük testi daha önce de böyle ve çoğu araçlar sadece yapamıyorum oluşturmak için bu tür bir yük linux, çünkü sınırları üzerinde sayıda açık dosya tanımlayıcıları (genellikle bir Bin başı işlem tarafından varsayılan). Bir soket kullanılır Bir kez de, yeniden kullanıma hemen hazır değil. Bir dakika hatırladığım kadarıyla, tekrar kullanılabilir olması için bazı önemli kısmını alır. Arasında bu gerçeği ettim normalde görülen sistem açık dosya tanıtıcı limit altında bir yerde 100 k, emin değilim o da olabilir almak o kadar yük değiştirilmemiş bir kutu, ya da oluşturmak için bir tek kutu. Bu yöndeki adımların söz yok, aynı zaman da yük testi, sence ne yapıyor emin olmak için araştırmak gerek sanırım.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Distractify

    Distractify

    1 Aralık 2011
  • kruno j

    kruno j

    6 Mayıs 2007
  • Trulia

    Trulia

    29 Kasım 2006