TCP bağlantılarını kabul eden bir sunucuda garip bir sorun var. Normalde bazı süreçler beklemesine rağmen, bazı bağlantılarda bu bağlantıyı askıya alır.Perl TCP sunucu betiğimde neden birçok TCP bağlantısı var?
Uzun versiyon:
sunucu Perl ile yazılmış ve yeniden bayrağıyla bir$srv
soket bağlayan ve Sonrasında == 5. dinlemek edilir
, bu $clt=$srv->accept(); do_processing($clt); $clt->shutdown(2);
istemci bir döngü ile 10 süreçlerine çatallar C de yazılmış çok basittir - bazı satırlar gönderir, sonra tüm satırları alır ve shutdown(sockfd, 2);
yapar Hiçbir şey eşzamansız devam eder ve sonunda her iki gönderi ve alma kuyrukları boştur (netstat
tarafından bildirildiği gibi).
Bağlantılar sadece ~ 20ms. Tüm müşteriler aynı şekilde davranırlar, aynı uygulama vb. Davranırlar. Şimdi istemci 1'den X
bağlantıyı kabul ettiğimi ve 2. istemciden bir başka X
kabul ettiğimi söyleyelim. İşlemler hala her zaman boşta olduklarını bildiriyorlar. İstemci 3'ten başka bir X
bağlantısı eklerseniz, aniden sunucu işlemleri kabul edildikten hemen sonra başlatılmaya başlar. accept();
'dan sonra yaptıkları ilk engelleme işlemi while (<$clt>) ...
'dur - ancak herhangi bir veri almazlar (ilk denemede). Aniden tüm 10 süreç bu durumda ve beklemeyi bırakmıyor. strace
üzerinde, sunucu işlemleri read()
'da asılı kalıyor, bu da mantıklı. Bu sunucuya ait olan TIME_WAIT
numaralı bağlantıda bir çok bağlantı vardır (sorun ortaya çıkmaya başladığında ~ 100), ancak bu kırmızı bir ringa balığı olabilir.
Burada neler olabilir?
Bazı analizlerden sonra: Bir sonraki denemeye başlamadan önce istemcinin hatalı olduğunu ve önceki bağlantıları düzgün şekilde kapatmayacağını belirtti. Yük dengeleme listesinin başında bulunan sunucular eski bağlantıları kalmıştı.
Tüm soketlerinizde arabelleğe almayı devre dışı bıraktınız mı? Daha fazla örnek kod göndermeniz gerekebilir. –
Burada kod olarak neler sağlayabileceğimi bilmiyorum - gerçekten basit. Sunucu satırlarda çalışır, bu yüzden oklar satır tamponludur ve '<...>' ile işlenir - burada başka bir şey ifade etmedikçe? İstemci C kodu bir standart 'connect (...);' ve 'yazmak (sockfd, request, ...);' - Burada arabelleğe almayı devre dışı bırakmaya ve geri raporlamaya çalışacağım. – viraptor
@Eric Strom: Şaşkınım şimdi - tamponlamayı devre dışı bırakarak ne demek istediniz? İstemci tarafında basit bir 'write (...)' kullanıyorum - tabii ki bir nagle var, ama bu sonraki 0.2s (daha fazla ya da daha az) transferini garanti ediyor. Peki aklında ne tür bir tamponlama var? – viraptor