2013-04-06 49 views
5

Tekrarlayan bir soru olduğunu biliyorum ve aşağıdaki gibi http://www.mailinator.com/tymaPaulMultithreaded.pdf gibi makaleleri okudum, nio'nun io'dan daha iyi olduğu doğru değildir.Bir web sunucusu için java.nio'nun faydaları nelerdir?

Ama bir web sunucusu geliştirirken java nio'nun geleneksel bir alıcı/işçi ipliği mimarisinden daha iyi nasıl ölçeklenebileceğini görmek için mücadele ediyorum? Anlatayım:

Genellikle Java web sunucuların bağlantıları işlemek için aşağıdaki modelini kullanın:

while (true) { 
    socket = serverSocket.accept(); 
    // handleRequest submits the socket to a queue 
    handleRequest(socket); 
    socket.close(); 
} 
: ServerSocket en accept() yöntemine bloke çekirdek sayısı ile sınırlı

  • Birkaç alıcı konuları

  • İstemci soketi alındığında engelleme olmayan bir sıraya gönderilir ve ardından bir çalışan iş parçacığı tarafından çalışan iş parçacığı havuzundan işlenir. Gerçekleştirilen iyo işlemlerinin süresine bağlı olarak çalışan iş parçacığı sayısı.

java.nio bu mimari nasıl daha ölçeklenebilir hale getirilir?

Engelleme işlemlerini gerçekleştiren isteği (erişim veritabanı veya dosya sistemi, dış hizmetleri çağırmak) işlemek için hala çalışan iş parçacığına ihtiyacım var. Arka uç işlemleri, node.js'de olduğu gibi eşzamansız olarak gerçekleştirilmezse, genel ölçeklenebilirlik ile 1 veya 2 olay dağıtıcı iş parçacığı arasındaki sınırı kaldıracak iş parçacıklarına ihtiyaç duyardım.

+0

NIO, uzun süreli boşta bağlantılarınız olduğunda daha kullanışlıdır. Bu nedenle, örneğin, uzun-yoklamadan ağır bir şekilde yararlanan bir uygulama, her bir uzun-polling bağlantı bloğunun IO'daki gibi IO'dan daha fazla NIO ile daha fazla istekleri işleyebildi ve bir iş parçacığı bağladı. NIO ile durum böyle değil. –

+0

İplik numaralarını azaltmak için - daha fazla iş parçacığı, daha fazla sistem çağrısı. – coolcfan

cevap

14

Paul Tyma'nın bu konudaki makalesini gerçekten çok seviyorum, gerçekten derinlemesine. Onun makalesinde iki ana noktaları görmek istiyorum:

  • Eğer (o ölçülür)
  • geleneksel, IO engelleme sunucu mantığı yolu daha az karmaşık hale getirir IO engelleme, geleneksel ile daha iyi verim alabilirsiniz - İstemci-sunucu iletişim kutusunun numaralı durumu, iş parçacığı akışında örtülü olarak tanımlanmıştır.

temel nedeni birçok, birçok eşzamanlı boşta istekleri olduğunda MİT ise engellenmeyen kullanımı. Bunun nedeni: NIO ile aynı iş parçacığından birden çok istekte bulunabilirsiniz ve bu daha iyi.

Tamam, her yerde okuyabildiğiniz şey budur. Şimdi ... neden bu iyidir?Her iplik ile gelen ek yük iki farklı ilişkili iki temel nedeni vardır

: zamanlayıcı işlemci çalıştırdığı iplik değiştirir

  • , bir "bağlam anahtarı" var, hangi pahalı bir işlem olabilir (yani iş parçacığı işlemcideki bazı durumlara sahiptir - yazmaçlardaki değerler, L1, L2, L3 önbellekleri vb. içinde yüklenen veriler) - iş parçacığı durduğunda bir yere "kaydedilmesi" gerekir ve iş parçacığı çalışmaya devam ettiğinde "yeniden yüklendi", ayrıca, L1, L2, L3 önbelleklerinin içeriğini kaybettiğinizde, büyük olasılıkla kötü (veya iş yüküne bağlı olarak değişebilir) önbellek hatalarını alacaksınız)
  • her iş parçacığı "

Yani, her iş parçacığı belki biraz daha "boşa" hafıza ve birlikte gelir (genellikle işlev çağrılarının adreslerini yerel değişkenleri saklamak ve geri dönmek için kullanılır) kendi bağımsız yığını tahsis etmek vardır israf "işlemci döngüleri" ("içerik anahtarını" gerçekleştirmek için).

Şimdi, bir sohbet sunucunuz olduğunu varsayalım, istemciler yeni iletiler için istekte bulunan HTTP bağlantılarını yaparlar ve sunucunuz yalnızca bu istemciye yeni iletiler olduğunda yanıtlar (böylece istemciler anında yeni iletiler alır). 10k gibi müşterileriniz olduğunu varsayalım. Geleneksel, engelleme, bağlantı başına bağlantı modelinde, 10k iş parçacığına sahip olursunuz. Java'da, thread yığın boyutu (-Xss) için standart bir standart değer 256kb'dir. 10k iş parçacığı ile, otomatik olarak yaklaşık 2GB bellek kullanıyorsunuz !!!!!!!! Daha da kötüsü: sohbet sunucunuzda hiç etkinlik olmasa bile, mesaj gönderilmiyor olsa da, istemciler sizi hala 2 GB'lık israftan kurtarıyor. İçerik anahtarları ton ekleyin ve bir sorun olduğunu görüyorsunuz.

Bu durumda, daha az iş parçacığının (sonuç olarak yalnızca 1!) Tüm 10k istemcilerini işlemek için yeterli olacağı, engellemeyen NIO'yu kullanmanız daha iyi olur. Böylece bağlam anahtarlarını kaydedersiniz (ör. cpu zamanı) ve iplik yığınları (yani, bellek), daha karmaşık kodun pahasına bile olsa, bu genellikle bloke edici olmayan NIO'nun kullanılmasının bir yan etkisidir.

+0

Okumak isteyenler için [Paul Tyma'nın makalesine] (http://paultyma.blogspot.sg/2008/03/writing-java-multithreaded-servers.html?m=1) bağlantı ekleniyor. – Misterhex

3

NIO veya non-blocking IO yüksek eşzamanlılık için çok iyi ölçeklenebilir, her bağlantı için özel bir iş parçacığına ihtiyacınız yoktur, bağlantıları kabul etmek için yalnızca bir ana iş parçacığına ihtiyacınız vardır ve IO işlemek için birkaç başka iş parçacığına sahip olmanız gerekir, iş parçacığı sayısı sabittir ve bu, geleneksel alıcı/çalışan iş parçacığı mimarisinden daha ölçeklenebilir olmasının ana nedenidir.