TCP gönderilen her paket için yeni bir bağlantı açar mı?


15

Bu aptalca bir soru olabilir, ancak ben ve birkaç arkadaş TCP'nin potansiyel sınırlamalarını tartışıyoruz. Müşterileri dinleyecek (bir ağ geçidi düşünün) ve bağlı tüm müşteri verilerini tek bir bağlı kafka yayıncısı aracılığıyla tek bir konuya yönlendirecek bir uygulamamız var.

Arkadaşlarımdan biri TCP'nin bu ağ geçidi için bir sorun olacağını söylüyor çünkü her mesaj için yeni bir bağlantı kuracak (kafka değil, temel ulaşım protokolünün kendisi sorun), her seferinde yeni bir bağlantı noktası gerektiriyor. Bu istemcilere mesaj göndereceğiz (gigabayt), kafka okumak için liman tükenecek ??

Birkaç yıl boyunca gelişim yaptım ve bunu daha önce hiç duymadım ve TCP'nin nasıl çalıştığına dair daha düşük düzeyde bir anlayış elde etmek istiyorum. Anladığım kadarıyla bir TCP bağlantısı oluşturduğunuzda, bu bağlantı uygulama tarafından zaman aşımına uğrayana veya sunucu veya istemci tarafından zorla kapatılana kadar açık kalır. Bu bağlantı üzerinden gönderilen veriler bir akıştır ve 3 V'lerden (hacim, hız, çeşitlilik) bağımsız olarak yeni bağlantıları açmaz / kapatmaz.

Bağlantı noktaları ilerledikçe, bir bağlantı noktası yayın için kullanılır ve dahili dosya tanımlayıcı bağlantı noktası, uygulamanın tek tek istemcilerin okuma / yazma için yönettiği bir şeydir. TCP'yi yazdığı her paket için yeni bağlantılar kuracağını hiç anlamadım.

Bu soru doğrudan ve çok belirsiz değilse şimdiden özür dilerim. Şaşkınım ve birisinin meslektaşlarımın söylediklerine daha fazla bağlam sağlayabileceğini umuyorum?


13
Bence arkadaşının ne söylediğini yanlış anladın. TCP böyle bir şey yapmaz, ancak belirli bir istemcinin geçmek istediği her mesaj için yeni bir TCP bağlantısı yapması mümkündür .
hobbs

13
TCP, her paket için yeni bir bağlantı açamadı çünkü yeni bir bağlantı açmak için birkaç pakete ihtiyaç duyuyor. TCP'nin ileti kavramı olmadığı için her ileti için yeni bir bağlantı açılamadı. Arkadaşın çok karışık. En temel kavram olan TCP hakkında anlaşılması gereken en önemli şey, TCP'nin bir bayt akışı protokolü olmasıdır.
David Schwartz

1
Arkadaşınızın argümanı mutlaka yanlış değildir - bağlantı noktalarını uygulama düzeyinde canlı tutma yoluyla yeniden kullanmazsanız veya çok fazla istemci varsa, sisteminizde geçici bağlantı noktaları tükenebilir. Bu soruna geçici bir çözüm bulmak için yollar vardır: SO_REUSEADDRYuvaları daha hızlı kapatmak, geçici bağlantı noktalarını genişletmek vb. İçin kullanılır. Ayrıca TCP_FASTOPEN, TCP'nin diğer iyi bilinen sınırlamaları için birkaç işletim sistemi düzeyinde geçiş kullanılabilir. Her iki durumda da, test edilecek bir iş yükünüz bile olmadığında TCP sınırlamalarını tartışmanın bir anlamı yoktur.
user1643723

Yanıtlar:


22

Arkadaşlarımdan biri TCP'nin bu ağ geçidi için bir sorun olacağını söylüyor çünkü her mesaj için yeni bir bağlantı kuracak (kafka değil, temel ulaşım protokolünün kendisi sorun), her seferinde yeni bir bağlantı noktası gerektiriyor. Bu istemcilere mesaj göndereceğiz (gigabayt), kafka okumak için liman tükenecek ??

Arkadaşınızın kafası karışık. TCP, akış yönelimli bir protokoldür. Mesaj kavramı yok. Tabii ki, IP katmanındaki paketleri kullanır, ancak uygulamaya göre bu bir uygulama detayıdır. Bunu yapmak için mantıklı ve burada TCP paket sınırlarını ekler başına mutlaka bir kez değil write()yasend() . Benzer şekilde, read()veya çağrıları arasında birden fazla mesaj alırsanız art arda gelen paketleri birleştirir recv().

Söylemeye gerek yok, her gönderimin yeni bir bağlantı kurması durumunda bu akış odaklı tasarım tamamen işe yaramaz olacaktır. Bu nedenle, yeni bir bağlantı kurmanın tek yolu bağlantıyı manuel olarak kapatmak ve yeniden açmaktır.

(Uygulamada, TCP'nin üzerine inşa edilen çoğu protokolde HTTP istekleri ve yanıtları gibi iletilere benzeyen bir şey vardır. Ancak TCP, bu tür şeylerin yapılarını bilmez veya umursamaz.)

Arkadaşınızın mesajları olan ama aynı zamanda bağlantısız olan UDP'yi düşünmesi de mümkündür. Çoğu soket uygulaması, bir UDP soketini uzak bir ana bilgisayara "bağlamanıza" izin verir, ancak bu, IP adresini ve bağlantı noktasını art arda belirtmekten kaçınmanın kolay bir yoludur. Aslında ağ düzeyinde hiçbir şey yapmaz. Bununla birlikte, UDP altında hangi akranlarla konuştuğunuzu manuel olarak takip edebilirsiniz. Ancak bunu yaparsanız, işletim sisteminin değil, "bağlantı" olarak neyin önemli olduğuna karar vermek sizin probleminizdir. Her iletide yeniden bir "bağlantı" kurmak istiyorsanız, bunu yapabilirsiniz. Ancak, muhtemelen çok iyi bir fikir değildir.


9

Anladığım kadarıyla bir TCP bağlantısı oluşturduğunuzda, bu bağlantı uygulama tarafından zaman aşımına uğrayana veya sunucu veya istemci tarafından zorla kapatılana kadar açık kalır.

TCP açısından bakıldığında, istemci veya sunucu yoktur (istemci / sunucu burada konu dışı bir uygulama konseptidir). TCP eşler arasında bir bağlantı kurar ve her iki eş de eşler tarafından kapatılana veya işlem yapılmadığında zaman aşımına uğramadan bağlantı üzerinden gönderebilir ve alabilir.

Bu bağlantı üzerinden gönderilen veriler bir akıştır ve 3 V'lerden (hacim, hız, çeşitlilik) bağımsız olarak yeni bağlantıları açmaz / kapatmaz.

Durumu karıştıran şey, bazı uygulamaların, örneğin tarayıcıların, bir web sayfasının öğeleri gibi şeyleri aynı anda yüklemek için birden fazla bağlantı açmasıdır.

TCP, gönderdiği her bölüm için yeni bir bağlantı açmaz, ancak bir uygulama birden çok TCP bağlantısı açabilir. Ayrıca, bir TCP bağlantısı kapatıldığında, bağlantıda kullanılan TCP bağlantı noktası serbest bırakılır ve yeniden kullanılabilir. Bu yanıt bazı bilgiler verir ve sizi TCP için RFC'ye yönlendirir.


2
TCP'de bağlantıyı başlatan bir ortak (genellikle "istemci" olarak adlandırılır) ve diğeri (genellikle "sunucu" olarak adlandırılır) bulunur. Tabii ki, bağlantı kurulduktan sonra, bu fark artık önemli değil.
Paŭlo Ebermann

2
@ PaŭloEbermann, TCP RFC'de istemciler veya sunucular hakkında hiçbir şey yoktur. İstemci / sunucu konsepti bir uygulama konseptidir. Buradaki konu OSI katman-4'teki veya altındaki protokollerdir ve bu protokollerde istemci veya sunucu yoktur. Aslında, bir istemci (TCP bağlantısını açan istemci) olarak kabul edebileceğiniz şey aslında bir uygulama sunucusu olabilir. Güvenlik kontrolleri ve güncellemeleri gibi işlemleri yapmak için istemcilere TCP bağlantıları başlatan sunucularımız var.
Ron Maupin

7

Hayır, TCP'nin gönderilen her paket için yeni bir bağlantı açmasına gerek yoktur .

HTTP kalıcı bağlantıları yoluyla birden fazla paket gönderebilirsiniz , burada:

... her bir istek / yanıt çifti için yeni bir bağlantı açmak yerine, birden çok HTTP isteği / yanıtı göndermek ve almak için tek bir TCP bağlantısı [kullanılır].

Ekte, birden çok bağlantı (bağlantı başına bir nesne göndermek için kurulan birçok bağlantı) ile kalıcı bağlantı (bir bağlantı kuruldu ve buraya gönderilen birden çok nesne) arasındaki farkı gösteren bir şekil:

Çoklu Bağlantı ve Kalıcı Bağlantı

Kaynak: https://www.vcloudnine.de/how-to-dramatically-improve-website-load-times/


7
Bu cevap katmanları karıştırıyor gibi görünüyor. Bir HTTP isteği / yanıtı nadiren tek bir pakettir.
Barmar

2
Her "açık" dan bahsetmemek gerekirse aslında 3 ok (syn, synack, ack) ve her "close" başka bir 4 (fin, ack 2x sunucusu ve istemcisi), yani paket başına bir bağlantı olursa, ek yük çabucak toplanırdı.
htmlcoderexe

5

TCP'nin nasıl çalıştığına dair yorumunuz doğrudur.

Arkadaşınızın söylediklerine gelince, burada iki olasılık görüyorum:

  1. Her bir iletinin yeni bir bağlantı üzerinden gönderilmesiyle sonuçlanan bazı uygulama katmanı sınırlamalarına atıfta bulunan arkadaşınızı yanlış anladınız (ve bu olağandışı bir durum değildir; hangi yazılıma bağlı olarak bu davranışa karar vermek mümkün olabilir veya olmayabilir) kullandığınız yığın);

  2. Arkadaşın yanlış.


5

Diğerlerinin de belirttiği gibi, TCP kesinlikle herhangi bir süre boyunca açık kalmasına izin verir ve bu süre zarfında herhangi bir sayıda "mesaj" değiştirir. Bununla birlikte, bu yeteneğin kullanılıp kullanılmadığını belirlemek sonuçta uygulamalara (hem istemci hem de sunucu) bağlıdır.

Mevcut TCP bağlantısını (soket) yeniden kullanmak için, istemci uygulamasının bu soketi açık tutması ve daha fazla veri yazması gerektiğinde kullanması gerekir. İstemci bunu yapmaz, ancak bunun yerine eski soketi atar ve her seferinde bir tane gerektiğinde yeni bir soket açarsa, gerçekten de sık sık tüketmek için istemci veya sunucuda kaynak sorunlarına neden olabilecek yeni bir bağlantı zorlar. TCP yığının bağlantı havuzu.

Aynı şekilde, sunucunun soketi yan tarafında açık tutacak ve daha fazla veri bekleyecek kadar akıllı olması gerekir. İstemci gibi, daha fazla veri göndermek isteyen hataya dayanıklı bir istemcinin aynı soruna yol açan yeni bir soket açmaktan başka seçeneği olmayacağı soketi kapatma seçeneği vardır.

Son olarak, diğerlerinin de belirttiği gibi, TCP akış yönelimlidir. Hiçbir şekilde çerçeveleme yok. Bir eşin verileri belirli bir şekilde yazması (örn. 2 256 bayt yazma çağrısından sonra 1 1024 bayt yazma çağrısı), diğer eşin aynı boyutta parçaları okuyacağını garanti etmez (örneğin, 1536 baytın tümünü alabilir) bir okuma çağrısında). Bu nedenle, ham TCP soketleri üzerinden birden çok "ileti" gönderiyorsanız, farklı iletileri tanımlamak için kendi çerçeveleme protokolünüzü sağlamanız gerekir. Bunu yapmanın kesinlikle basit yolları olsa da, genellikle bu sorunu çözmek için TCP'nin üstüne inşa edilmiş birçok protokol olduğu için tavsiye edilmez. Daha fazla tartışma için, şu adrese başvurun: https://blog.stephencleary.com/2009/04/message-framing.html


2

Bence arkadaşın TCP'den değil HTTP'den bahsediyordu.

HTTP başlangıçta durum bilgisi olmayan bir protokoldür: her HTTP isteği ayrı bir TCP bağlantısı kullanır. Bu yüzden oturumları uygulamak için çerezlere (veya benzer bir şeye) ihtiyacımız var.


0

"Tek bağlantı ve her seferinde yeni bir bağlantı noktası gerektirir" den bahsetmiştiniz ve kuruluşunuzun dışındaki sunucuya bağlanmak için aynı ağ ortamında PAT tekniğini kullanan birçok müşteriniz olduğu şeklinde yorum yapardım. PAT, 65535 (IPv4 Adresinde TCP oturum sınırı) sınırına sahip olacaktır. Bu doğruysa, sınırınız vardır.

TCP gönderilen her paket için yeni bir bağlantı açar mı? HAYIR, TCP oturumu geçerli olduğu sürece geçerli değildir. ve ...


0

TCP'deki mükemmel wikipedia sayfasını beğendim . Bağlantı noktası numarası ile ne olduğunu açıkça gösterir. Tesadüfen, kaynak kullanımı hakkında yararlı bir bölüm içerir:

Kaynak kullanımı

Çoğu uygulama, bir oturumu çalışan bir işletim sistemi işlemiyle eşleştiren bir tabloda bir girdi ayırır. TCP paketleri bir oturum tanımlayıcısı içermediğinden, her iki uç nokta da oturumu istemcinin adresini ve bağlantı noktasını kullanarak tanımlar. Bir paket alındığında, TCP uygulamasının hedef işlemi bulmak için bu tabloda bir arama gerçekleştirmesi gerekir. Tablodaki her giriş bir İletim Kontrol Bloğu veya TCB olarak bilinir. Uç noktalar (IP ve bağlantı noktası), bağlantının durumu, değiştirilmekte olan paketler hakkında veri çalıştırma ve veri gönderme ve alma arabellekleri hakkında bilgiler içerir.

Sunucu tarafındaki oturum sayısı yalnızca bellekle sınırlıdır ve yeni bağlantılar geldikçe büyüyebilir, ancak istemcinin sunucuya ilk SYN'yi göndermeden önce rasgele bir bağlantı noktası ayırması gerekir. Bu bağlantı noktası tüm görüşme sırasında ayrılmış durumda kalır ve istemcinin IP adreslerinin her birinden giden bağlantı sayısını etkin bir şekilde sınırlar. Bir uygulama gerekli olmayan bağlantıları düzgün bir şekilde kapatamazsa, istemcinin kaynakları tükenebilir ve diğer uygulamalardan bile yeni TCP bağlantıları kuramayabilir.

Kısacası, TCP kullanır bir (TCP başlığında, 16 bit olarak bağlantı alanının boyutu ile sınırlıdır) istemci port sayısı çok sonlu Ressource.

Yani, TCP olan bir istemci bunları kapatmadan paralel olarak TCP bağlantıları çok yer açarsa, limanların tükendi mümkün. Sorun yalnızca istemci tarafında oluşur ve bağlantıların aynı veya farklı sunucu IP adresleriyle veya sunucu bağlantı noktalarıyla olması önemli değildir.

Senin ayarında, birçok müşteri istekleri alır bir uygulama (var gibi buistemcileriniz bunu uygulamanıza bazı olayları kaydetmek ve TCP kanalını aralarında açık tutmamak için kullandığından, bireysel TCP istekleri olabilir ve Kafka aracısına yeni bir dahili istek oluşturabilir (bu da kolayca bireysel TCP bağlantıları olabilir) bunları böyle uygulamayı seçtiyseniz). Bu durumda, darboğaz (performans açısından değil, kaynaklarla ilgili olarak), müşterilerinizden aynı anda çok sayıda istek almayı başarırsanız (sizin için sorun değil, sunucu tarafında yalnızca bir bağlantı noktasına ihtiyacınız vardır) hepsi) ve Kafka'nıza çok sayıda ileri istekte bulunuyorsunuz ve Kafka bunları yeterince hızlı işleyemiyor ve aynı anda 16 bitten fazla bağlantıya sahip olmanızla sonuçlanıyor.

Burada kendi hakimsiniz; başvurunuzu kontrol edin ve her seferinde ayrı bir istekle Kafka'ya bağlanıp bağlanmadığınızı öğrenmeye çalışın (belki bazı REST API proxy'si aracılığıyla). Bunu yaparsanız ve çok sayıda müşteriniz varsa, kesinlikle tehlikede olursunuz.

Sadece bir avuç müşteriniz varsa, 65k-ish'den daha azsa ve / veya Kafka tarayıcınızla tek bir bağlantınız varsa, o zaman iyi olacaksınız.

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.