HTTP Yoklama, Uzun Yoklama, HTTP Akışı ve WebSockets Konusundaki Anlayışım


123

SO ve web'de soru başlığımdaki anahtar kelimelerle ilgili birçok yazı okudum ve onlardan çok şey öğrendim. Okuduğum sorulardan bazıları belirli uygulama zorluklarıyla ilgilidir, diğerleri ise genel kavramlara odaklanır. Sadece tüm kavramları ve X teknolojisinin neden Y teknolojisi üzerinde icat edildiğinin gerekçelerini anladığımdan emin olmak istiyorum. İşte burada:

Http Yoklama: Temelde AJAX, XmlHttpRequest kullanarak.

Http Uzun Çağırma: AJAX, ancak sunucuda bir güncelleme olmadıkça sunucu yanıtı tutar, sunucu bir güncelleme alır almaz, onu gönderir ve ardından istemci başka bir istek gönderebilir. Dezavantajı, ileri geri gönderilmesi gereken ve ek yüke neden olan ek başlık verileridir.

Http Akışı: Uzun yoklamaya benzer, ancak sunucu "Transfer Kodlaması: chunked" ile bir başlık ile yanıt verir ve bu nedenle, sunucu her veri gönderdiğinde yeni bir istek başlatmamız gerekmez (ve bu nedenle ek başlık ek yükünü kaydetmemiz gerekmez). Buradaki dezavantaj, sunucu tarafından gönderilen çoklu parçaları birbirinden ayırt etmek için verilerin yapısını "anlamamız" ve anlamamız gerektiğidir.

Java Applet, Flash, Silverlight: Soket sunucularına tcp / ip üzerinden bağlanma yeteneği sağlarlar ancak eklenti oldukları için geliştiriciler bunlara bağımlı olmak istemezler.

WebSockets: Bunlar, yukarıdaki yöntemlerin eksikliklerini aşağıdaki şekilde ele almaya çalışan yeni API'dir:

  • WebSocket'lerin Java Applet'leri, Flash veya Silverlight gibi eklentilere göre tek avantajı, WebSocket'lerin tarayıcılarda yerleşik olması ve eklentilere dayanmamasıdır.
  • WebSocket'lerin http akışına göre tek avantajı, alınan verileri "anlamak" ve ayrıştırmak için çaba sarf etmeniz gerekmemesidir.
  • WebSocket'lerin Long Polling'e göre tek avantajı, ekstra başlık boyutunun ortadan kaldırılması ve istek için soket bağlantısının açılıp kapanmasıdır.

Kaçırdığım başka önemli farklılıklar var mı? SO ile ilgili birçok soruyu tek bir soruda tekrar soruyorsam veya birleştiriyorsam özür dilerim, ancak SO'da ve bu kavramlarla ilgili web'de bulunan tüm bilgilerden mükemmel bir anlam çıkarmak istiyorum.

Teşekkürler!


4
Sunucu Tarafından Gönderilen Olaylar , çift yönlü iletişime ihtiyacınız olmadığında da bakmaya değer olabilir.
leggetter

1
Bu gerçekten yararlı bir sorudur. Birden çok yazarın katkıda bulunabileceği tek bir yanıt olsaydı, potansiyel olarak daha faydalı olacağını düşünüyorum.
leggetter

@leggetter Teşekkürler Phil, sunucu gönderilen etkinliklerle ilgili ipucu için teşekkürler. İki yönlü iletişim senaryoları hakkında bilgi edinmekle ilgileniyorum. Teşekkürler.
Software Guy

1
HTTP Akışı ve Uzun Çağırma ile çift yönlü iletişim için 2. bir bağlantıya ihtiyacınız vardır. Sunucu için daha uzun ömürlü bir bağlantı -> istemci "itme" iletişimi ve istemci -> sunucu iletişimleri için ikinci bir kısa ömürlü bağlantı. Bu ikinci bağlantı, veri aboneliklerini ayarlamak ve değiştirmek gibi şeyler yapmak için kullanılır. Dolayısıyla, EventSource iki yönlü bir çözümde kullanılabilir ve aslında HTTP Akışı ve Uzun Yoklamadan doğan standart bir çözümdür.
leggetter

1
Ayrıca yazdığım tekniklerin bu sınıflandırmasına da göz atmak isteyebilirsiniz: stackoverflow.com/questions/12078550/…
Alessandro Alinone

Yanıtlar:


92

Tanımladığınızlardan daha fazla farklılık var.

Dubleks / yönlü:

  • Tek yönlü: HTTP anketi, uzun anket, akış.
  • İki yönlü: WebSockets, eklenti ağı

Gecikmeyi artırma sırasına göre (yaklaşık):

  • WebSockets
  • Eklenti ağı
  • HTTP akışı
  • HTTP uzun anket
  • HTTP yoklama

CORS (çapraz kaynak desteği):

  • WebSockets: evet
  • Eklenti ağı: Politika isteği yoluyla Flash (diğerleri hakkında emin değilim)
  • HTTP * (bazı yeni destek)

Yerel ikili veriler (türlenmiş diziler, bloblar):

  • WebSockets: evet
  • Eklenti ağı: Flash ile değil (ExternalInterface genelinde URL kodlaması gerektirir)
  • HTTP *: ikili tür desteğini etkinleştirmek için son teklif

Verimliliği azaltmada bant genişliği:

  • Eklenti ağ iletişimi: Flash soketleri, ilk politika isteği dışında işlenmemiş
  • WebSockets: bağlantı kurulumu anlaşması ve çerçeve başına birkaç bayt
  • HTTP akışı (sunucu bağlantısının yeniden kullanımı)
  • HTTP uzun anket: her mesaj için bağlantı
  • HTTP anketi: her mesaj için bağlantı + veri mesajı yok

Mobil cihaz desteği:

  • WebSocket: iOS 4.2 ve üstü. Her ikisi de yerel WebSocket desteği sağlayan Flash emülasyonu veya Android için Firefox veya Android için Google Chrome kullanarak bazı Android .
  • Eklenti ağı: bazı Android. İOS'ta değil
  • HTTP *: çoğunlukla evet

Javascript kullanım karmaşıklığı (en basitinden en karmaşığına). Kuşkusuz karmaşıklık ölçüleri bir şekilde özneldir.

  • WebSockets
  • HTTP anketi
  • Eklenti ağı
  • HTTP uzun anket, akış

Ayrıca, Sunucu Tarafından Gönderilen Olaylar olarak adlandırılan HTTP akışını standartlaştırmak için bir W3C önerisi olduğunu unutmayın . Şu anda gelişiminin oldukça erkendir ve WebSockets ile karşılaştırılabilir basitlikte standart bir Javascript API'si sağlamak için tasarlanmıştır.


1
Güzel cevap için çok teşekkürler Kanaka. Lütfen bana http akışının neden / nasıl web soketlerinden daha yüksek bir gecikme süresine sahip olduğunu söyleyebilir misiniz? belki basit bir örnekle? çok teşekkürler.
Software Guy

2
@SoftwareGuy. Pek çok sebep. Son tarayıcılarda, verilerden haberdar olmak için XMLHTTPRequest onprogress olay işleyicisini kullanabilirsiniz. Ancak teknik özellikler, 50ms'nin en küçük bildirim aralığı olduğunu söylüyor. Aksi takdirde, yanıt verilerini sorgulamalısınız. Ayrıca, istemci gönderileri yeni bir HTTP bağlantısı kurar ve bu nedenle gidiş-dönüş gecikmesini önemli ölçüde artırır. Ayrıca, birçok web sunucusu 30 saniye sonra HTTP bağlantılarını keser, bu da genellikle sunucu push bağlantısını yeniden kurmanız gerektiği anlamına gelir. Yerel bir ağda 5-10 ms WebSocket gidiş dönüş gecikmeleri gördüm. HTTP akış gecikmesi büyük olasılıkla 50ms + olacaktır.
kanaka

Ayrıntılı yanıt için çok teşekkürler :)
Software Guy

1
@leggetter Teşekkürler Phil, istemciden sunucuya http akışı yoluyla veri göndermenin ek yüke neden olacağını mı söylüyorsun? sunucuya yeni bir bağlantı açmadan http akışı üzerinden veri göndermek mümkün mü? Teşekkürler.
Software Guy

1
@Nathan kulağa iyi bir yüksek lisans tezi projesi gibi geliyor! Kuşkusuz, yoklama sistemi olay güdümlü bir modelden daha yoğun tutacaktır, ancak güç tasarrufunun tam olarak ne olabileceği, farklı ölçeklerde oldukça kapsamlı deneysel testler gerektirecektir.
kanaka

13

Başkalarından çok şey kapsayan bazı harika cevaplar. İşte biraz fazladan.

WebSocket'lerin Java Applet'leri, Flash veya Silverlight gibi eklentilere göre tek avantajı, WebSocket'lerin tarayıcılarda yerleşik olması ve eklentilere dayanmamasıdır.

Bununla bir soket bağlantısı kurmak için Java Applet'leri, Flash veya Silverlight'ı kullanabileceğinizi kastediyorsanız, evet, bu mümkündür. Ancak bunun gerçek dünyada kısıtlamalar nedeniyle çok sık kullanıldığını görmüyorsunuz.

Örneğin, aracılar bu trafiği kapatabilir ve kapatabilir. WebSocket standardı, mevcut HTTP altyapısıyla uyumlu olacak şekilde tasarlanmıştır ve bu nedenle, güvenlik duvarları ve proxy'ler gibi aracıların müdahalesine çok daha az eğilimlidir.

Dahası, WebSocket, mevcut HTTP altyapısıyla mümkün olduğunca uyumlu olacak şekilde protokol tasarımı sayesinde, özel portlar gerektirmeden port 80 ve 443'ü kullanabilir.

Bu soket alternatiflerinin (Java, Flash ve Silverlight) çapraz kaynaklı bir mimaride güvenli bir şekilde kullanılması zordur. Bu nedenle, onları çoğunlukla çapraz olarak kullanmaya çalışan insanlar, güvenli bir şekilde yapma çabasına gitmek yerine güvensizliklere tahammül edeceklerdir.

Ayrıca ek "standart olmayan" bağlantı noktalarının açılmasını (yöneticilerin yapmaktan nefret ettikleri bir şey) veya yönetilmesi gereken ilke dosyalarını gerektirebilirler.

Kısacası, soket bağlantısı için Java, Flash veya Silverlight kullanmak yeterince sorunludur, ciddi mimarilerde çok sık kullanıldığını görmezsiniz. Flash ve Java, muhtemelen en az 10 yıldır bu özelliğe sahipler ve henüz yaygın değil.

WebSocket standardı, bu kısıtlamaları akılda tutarak yeni bir yaklaşımla başlayabildi ve umarım onlardan bazı dersler çıkardı.

Bazı WebSocket uygulamaları, WebSocket bağlantısı kurulamadığında (örneğin eski bir tarayıcıda çalışırken veya bir aracı müdahale ettiğinde) yedek olarak Flash'ı (veya muhtemelen Silverlight ve / veya Java'yı) kullanır.

Bu durumlar için bir tür geri dönüş stratejisi akıllıca, hatta gerekli olsa da, Flash ve diğerlerini kullananların çoğu yukarıda açıklanan dezavantajlardan muzdarip olacaktır. Bu şekilde olmak zorunda değil - Flash, Silverlight, vb. Kullanarak güvenli çapraz kaynak özellikli bağlantılar elde etmek için geçici çözümler var - ancak çoğu uygulama bunu yapmayacak çünkü kolay değil.

Örneğin, çapraz kaynak bağlantısı için WebSocket'e güveniyorsanız, bu iyi çalışacaktır. Ancak daha sonra eski bir tarayıcıda veya bir güvenlik duvarında / proxy'de müdahale ederseniz ve mesela, yedek olarak Flash'a güvenirseniz, aynı çapraz kaynak bağlantısını yapmakta zorlanacaksınız. Tabii ki güvenliği önemsemediğiniz sürece.

Bu, yerel ve yerel olmayan bağlantılar için çalışan tek bir birleşik mimariye sahip olmanın zor olduğu anlamına gelir, oldukça fazla iş yapmaya veya bunu iyi yapan bir çerçeveye gitmeye hazır değilseniz. İdeal bir mimaride, bağlantıların yerel olup olmadığını fark etmezsiniz; güvenlik ayarlarınız her iki durumda da çalışır; kümeleme ayarlarınız yine de çalışır; kapasite planlamanız yine de geçerli olacaktır; ve bunun gibi.

WebSocket'lerin http akışına göre tek avantajı, alınan verileri "anlamak" ve ayrıştırmak için çaba sarf etmeniz gerekmemesidir.

Verileriniz dakikalar, saatler veya daha uzun süre akarken, bir HTTP akışını açmak ve arkanıza yaslanmak kadar basit değildir. Farklı müşteriler farklı davranır ve bunu yönetmeniz gerekir. Örneğin, bazı istemciler verileri arabelleğe alacak ve bazı eşikler karşılanana kadar uygulamaya bırakmayacaktır. Daha da kötüsü, bazıları bağlantı kapanana kadar verileri uygulamaya aktarmaz.

Dolayısıyla, istemciye birden fazla mesaj gönderiyorsanız, istemci uygulamasının, örneğin 50 mesaj değerinde veri alınana kadar verileri almaması mümkündür. Bu çok gerçek zamanlı değil.

HTTP akışı, WebSocket mevcut olmadığında uygulanabilir bir alternatif olabilir, ancak her derde deva değildir. Gerçek dünya koşullarında Web'in kötü bölgelerinde sağlam bir şekilde çalışmak için iyi bir anlayışa ihtiyacı vardır.

Kaçırdığım başka önemli farklılıklar var mı?

Henüz kimsenin bahsetmediği bir şey daha var, bu yüzden onu açacağım.

WebSocket protokolü, daha yüksek seviyeli protokoller için bir taşıma katmanı olacak şekilde tasarlanmıştır. JSON mesajlarını veya neyi doğrudan bir WebSocket bağlantısı üzerinden gönderebilirken, standart veya özel protokolleri de taşıyabilir.

Örneğin, insanların zaten yaptığı gibi WebSocket üzerinden AMQP veya XMPP yapabilirsiniz. Böylece bir istemci, AMQP aracısından doğrudan aracının kendisine (ve bazı durumlarda bağlı) bağlıymış gibi mesajlar alabilir.

Veya bazı özel protokollere sahip mevcut bir sunucunuz varsa, bunu WebSocket üzerinden taşıyabilir, böylece bu arka uç sunucusunu Web'e genişletebilirsiniz. Genellikle, kuruluşta kilitlenmiş olan mevcut bir uygulama, arka uç altyapısını değiştirmek zorunda kalmadan WebSocket kullanarak erişimini genişletebilir.

(Doğal olarak, tüm bunları güvenli bir şekilde yapmak istersiniz, bu nedenle satıcıya veya WebSocket sağlayıcısına danışın.)

Bazı kişiler WebSocket'e Web için TCP olarak başvurmuştur. Çünkü tıpkı TCP'nin üst düzey protokolleri taşıdığı gibi, WebSocket de öyle, ancak bir şekilde Web altyapısıyla uyumludur.

Bu nedenle, JSON (veya her neyse) mesajlarını doğrudan WebSocket üzerinden göndermek her zaman mümkün olsa da, mevcut protokoller de dikkate alınmalıdır. Çünkü yapmak istediğiniz birçok şey için, muhtemelen bunu yapmak için zaten düşünülmüş bir protokol vardır.

SO ile ilgili birçok soruyu tek bir soruda tekrar soruyorsam veya birleştiriyorsam özür dilerim, ancak SO'da ve bu kavramlarla ilgili web'de bulunan tüm bilgilerden mükemmel bir anlam çıkarmak istiyorum.

Bu harika bir soruydu ve cevapların hepsi çok bilgilendirici oldu!


Mükemmel yardım ve bilgi için çok teşekkürler Robin. Bir şey daha sorabilirsem: Bir makalede, http akışının proxyler tarafından önbelleğe alınabileceğini, ancak web yuvalarının bulunmadığını söyleyen bir makaleye rastladım. Bu ne anlama geliyor?
Software Guy

StackOverflow, yanıt yorumlarında boyutu sınırladığından, cevabımı aşağıda verdim: stackoverflow.com/questions/12555043/…
Robin Zimmermann

@RobinZimmermann, cevabınız benim favorim. Gerçekten iyi ayrıntılı cevap için +1.
securecurve

10

Bir şey daha sorabilirsem: Bir makalede, http akışının proxyler tarafından önbelleğe alınabileceğini, ancak web yuvalarının bulunmadığını söyleyen bir makaleye rastladım. Bu ne anlama geliyor?

(StackOverflow, yorum yanıtlarının boyutunu sınırlar, bu nedenle satır içi yerine burada yanıtlamak zorunda kaldım.)

İyi bir noktaya değindin. Bunu anlamak için, ... geleneksel HTTP senaryo hakkında düşünüyorum ister bu yüzden, bir tarayıcı bir web sayfası açtı düşünün http://example.com , söz. Sunucu, sayfanın HTML'sini içeren HTTP ile yanıt verir. Ardından tarayıcı sayfada kaynakların olduğunu görür, böylece CSS dosyalarını, JavaScript dosyalarını ve tabii ki resimleri istemeye başlar. Bunların tümü, talep eden tüm istemciler için aynı olacak statik dosyalardır .

Bazı proxy'ler statik kaynakları önbelleğe alır, böylece diğer istemcilerden gelen sonraki istekler, bunları almak için merkezi web sunucusuna tamamen geri dönmek zorunda kalmadan, bu statik kaynakları proxy'den alabilir. Bu önbelleğe alma işlemidir ve merkezi hizmetlerinizden istekleri ve işlemleri boşaltmak için harika bir stratejidir.

Yani 1 numaralı müşteri http://example.com/images/logo.gif istiyor , diyelim. Bu istek, proxy üzerinden logo.gif'i sunan merkezi web sunucusuna kadar gider. Logo.gif proxy'den geçerken, proxy bu görüntüyü kaydedecek ve http://example.com/images/logo.gif adresiyle ilişkilendirecektir .

İstemci 2 geldiğinde ve ayrıca http://example.com/images/logo.gif istediğinde , proxy görüntüyü geri döndürebilir ve merkezdeki web sunucusuyla hiçbir iletişim gerekmez. Bu, son kullanıcıya daha hızlı yanıt verir, bu her zaman harikadır, ancak aynı zamanda merkezde daha az yük olduğu anlamına gelir. Bu, daha düşük donanım maliyetleri, daha düşük ağ maliyetleri vb. Anlamına gelebilir. Yani bu iyi bir şey.

Sorun logo.gif web sunucusunda güncellendiğinde ortaya çıkar. Proxy, yeni bir görüntünün olduğunun farkında olmadan eski görüntüyü sunmaya devam edecektir. Bu, sürenin dolmasına yol açar, böylece proxy görüntüyü "süresi dolmadan" önce kısa bir süre için önbelleğe alır ve sonraki istek proxy üzerinden web sunucusuna gider ve ardından proxy önbelleğini yeniler. Ayrıca, merkezi bir sunucunun bilinen önbellekleri vb. Gönderebildiği ve her şeyin oldukça karmaşıklaşabildiği daha gelişmiş çözümler de vardır.

Bu, sorunuza nasıl bağlanıyor?

Sunucunun bir istemciye HTTP akışı sağladığı HTTP akışını sordunuz. Ancak akışlı HTTP, veri göndermeyi bırakmamanız dışında normal HTTP gibidir. Bir web sunucusu bir görüntü sunuyorsa, istemciye sonunda sona eren HTTP gönderir: görüntünün tamamını siz gönderdiniz. Ve eğer veri göndermek istiyorsanız, tamamen aynıdır, ancak sunucu gerçekten uzun bir süre (örneğin devasa bir görüntü gibi) gönderir veya hiç bitmez.

Proxy'nin bakış açısından, görüntü gibi statik bir kaynak için HTTP ile HTTP akışından gelen verileri ayırt edemez. Her iki durumda da, müşteri sunucudan bir istekte bulundu. Vekil bu isteği ve yanıtı da hatırladı. Bu istek bir sonraki sefer geldiğinde, proxy aynı yanıtı verir.

Dolayısıyla, müşteriniz hisse senedi fiyatları için bir talepte bulunduysa ve bir yanıt aldıysa, sonraki müşteri aynı talebi yapabilir ve önbelleğe alınmış verileri alabilir. Muhtemelen istediğin şey değil! Hisse senedi fiyatlarını talep ederseniz en son verileri istersiniz, değil mi?

Yani bu bir problem.

Bunun gibi sorunları çözmek için püf noktaları ve geçici çözümler var, bu doğru. Açıkçası, bugün kullanımda olduğu için HTTP akışını çalıştırabilirsiniz. Her şey son kullanıcı için şeffaftır, ancak bu mimarileri geliştiren ve sürdüren insanlar çemberlerden atlamak ve bir bedel ödemek zorundadır. Aşırı karmaşık mimarilerle sonuçlanır, bu da daha fazla bakım, daha fazla donanım, daha fazla karmaşıklık ve daha fazla maliyet anlamına gelir. Bu aynı zamanda geliştiricilerin genellikle sadece uygulamaya, GUI'ye ve iş mantığına odaklanmaları gereken bir şeyi önemsemeleri gerektiği anlamına gelir - altta yatan iletişim hakkında endişelenmeleri gerekmez.


1
mükemmel detay Robin, çok teşekkürler! Tam cevabınızı gerçekten takdir ediyorum. Buradaki tüm harika insanlardan çok şey öğrendim! :)
Software Guy

4

HTTP, bir istemcinin bir sunucuyla sahip olabileceği bağlantı sayısını 2 ile sınırlandırır (ancak bu, alt alanlar kullanılarak azaltılabilir) ve IE'nin bunu hevesle uyguladığı bilinmektedir. Firefox ve Chrome daha fazlasına izin veriyor (kafamın tepesini tam olarak kaç tane hatırlayamasam da). Bu çok büyük bir sorun gibi görünmeyebilir, ancak gerçek zamanlı güncellemeler için sürekli olarak 1 bağlantı kullanıyorsanız, diğer tüm isteklerin diğer HTTP bağlantısı üzerinden darboğaz yapması gerekir. Ve istemcilerden daha fazla açık bağlantıya sahip olmak, sunucuya daha fazla yük getirir.

WebSockets, TCP tabanlı bir protokoldür ve bu nedenle bu HTTP düzeyi bağlantı sınırından etkilenmez (ancak, elbette, tarayıcı desteği tek tip değildir).


özü için teşekkürler, sizin tarafınızdan vurgulandığı gibi aynı anda birden fazla bağlantı sorunu dışında, web soketleriyle ilgili diğer varsayımlarım doğru mu?
Software Guy
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.