Открывает ли TCP новое соединение для каждого отправляемого пакета?


15

Это может быть глупый вопрос, но я и несколько приятелей обсуждали потенциальные ограничения TCP. У нас есть приложение, которое будет прослушивать клиентов (например, шлюз) и направлять данные всех подключенных клиентов через одного подключенного издателя kafka в одну тему.

Один из моих собеседников говорит, что TCP будет проблемой для этого шлюза, потому что он собирается устанавливать новое соединение для каждого отправляемого сообщения (проблема не в kafka, а в самом базовом транспортном протоколе), каждый раз требуя новый порт. С той скоростью, с которой мы будем отправлять сообщения этим клиентам (гигабайты), у kafka не хватит портов для чтения ??

Я занимался разработкой в ​​течение нескольких лет и никогда не слышал об этом раньше, и хотел бы получить более низкое понимание (как я думал, я имел) того, как работает TCP. Насколько я понимаю, когда вы устанавливаете TCP-соединение, это соединение остается открытым до тех пор, пока оно не будет заблокировано приложением или принудительно закрыто сервером или клиентом. Данные, которые отправляются через это соединение, являются потоком и не будут открывать / закрывать новые соединения независимо от 3 В (объем, скорость, разнообразие).

Что касается портов, один порт используется для широковещательной передачи, а порт внутреннего дескриптора файла - это то, что приложение управляет для чтения / записи отдельных клиентов. Я никогда не понимал TCP, чтобы устанавливать новые соединения для каждого пакета, который он пишет.

Я заранее прошу прощения, если этот вопрос не является прямым или слишком расплывчатым. Я действительно сбит с толку и надеюсь, что кто-нибудь сможет предоставить больше контекста тому, что говорят мои коллеги?


13
Я думаю, вы не поняли, что говорил ваш друг. TCP этого не делает, но возможно, что определенный клиент будет устанавливать новое TCP-соединение для каждого сообщения, которое он хочет передать.
Хоббс

13
TCP не может открыть новое соединение для каждого пакета, потому что ему нужно несколько пакетов для открытия нового соединения. И он не может открыть новое соединение для каждого сообщения, потому что TCP не имеет понятия сообщения. Твой приятель очень смущен. Самая важная вещь для понимания TCP, самой фундаментальной концепции, состоит в том, что TCP является протоколом потока байтов.
Дэвид Шварц,

1
Аргумент вашего собеседника не обязательно неверен - если вы не используете порты повторно через keep-alive уровня приложения или просто слишком много клиентов, ваша система может исчерпать эфемерные порты. Есть способы обойти эту проблему: использовать SO_REUSEADDRдля более быстрого закрытия сокетов, увеличения диапазона временных портов и т. Д. Кроме того, TCP_FASTOPENможно использовать несколько переключателей на уровне ОС, чтобы обойти другие хорошо известные ограничения TCP. В любом случае, нет смысла обсуждать ограничения TCP, когда у вас даже нет рабочей нагрузки для тестирования.
user1643723

Ответы:


22

Один из моих собеседников говорит, что TCP будет проблемой для этого шлюза, потому что он собирается устанавливать новое соединение для каждого отправляемого сообщения (проблема не в kafka, а в самом базовом транспортном протоколе), каждый раз требуя новый порт. С той скоростью, с которой мы будем отправлять сообщения этим клиентам (гигабайты), у kafka не хватит портов для чтения ??

Твой друг в замешательстве. TCP является потоковым протоколом. Он не имеет понятия о сообщениях. Конечно, он использует пакеты на уровне IP, но для приложения это деталь реализации. TCP вставляет границы пакетов там, где это имеет смысл, и не обязательно один раз для write()илиsend() . Точно так же он объединяет последовательные пакеты вместе, если вы получаете более одного между вызовами read()или recv().

Само собой разумеется, этот ориентированный на поток дизайн был бы совершенно неработоспособным, если бы каждая отправка установила новое соединение. Таким образом, единственный способ установить новое соединение - закрыть и снова открыть соединение вручную.

(На практике большинство протоколов, построенных поверх TCP, имеют нечто, напоминающее сообщения, такие как HTTP-запросы и ответы. Но TCP не знает и не заботится о структуре таких вещей.)

Вполне возможно, что ваш друг думал о UDP, который имеет сообщения, но также не имеет соединения. Большинство реализаций сокетов позволяют вам «подключать» сокет UDP к удаленному хосту, но это всего лишь удобный способ избежать повторного указания IP-адреса и порта. На самом деле он ничего не делает на сетевом уровне. Тем не менее, вы можете вручную отслеживать, с какими пирами вы общаетесь по UDP. Но если вы это сделаете, то решить, что считать «соединением», будет ваша проблема, а не ОС. Если вы хотите восстановить «соединение» для каждого сообщения, вы можете сделать это. Это, вероятно, не очень хорошая идея, однако.


9

Насколько я понимаю, когда вы устанавливаете TCP-соединение, это соединение остается открытым до тех пор, пока оно не будет заблокировано приложением или принудительно закрыто сервером или клиентом.

С точки зрения TCP, нет ни клиента, ни сервера (клиент / сервер - это концепция приложения, которая здесь не по теме). TCP устанавливает соединение между одноранговыми узлами, и оба одноранговых узла могут отправлять и получать по соединению, пока одно из них не закроет его или не истечет время ожидания из-за неактивности.

Данные, которые отправляются через это соединение, являются потоком и не будут открывать / закрывать новые соединения независимо от 3 В (объем, скорость, разнообразие).

Что может сбить с толку, так это то, что некоторые приложения, например браузеры, открывают несколько соединений, чтобы одновременно загружать такие элементы, как элементы веб-страницы.

TCP не открывает новое соединение для каждого отправляемого сегмента, но приложение может открыть несколько соединений TCP. Кроме того, когда соединение TCP закрыто, порт TCP, используемый в соединении, освобождается и становится доступным для повторного использования. Этот ответ дает некоторую информацию и указывает на RFC для TCP.


2
Хотя в TCP есть один партнер, который инициировал соединение (часто называемое «клиент»), а другой (часто называемый «сервер»). Конечно, после того, как соединение установлено, эта разница больше не имеет значения.
Paŭlo Ebermann

2
@ PaŭloEbermann, в RFC TCP нет ничего о клиентах или серверах. Концепция клиент / сервер - это концепция приложения. Здесь обсуждаются протоколы уровня 4 или ниже OSI, и в этих протоколах нет ни клиентов, ни серверов. Фактически, то, что вы можете считать клиентом (тот, который открывает TCP-соединение), на самом деле может быть сервером приложений. У нас есть серверы, которые инициируют TCP-соединения с клиентами для таких вещей, как проверки безопасности и обновления.
Рон Мопин

7

Нет, TCP не нужно открывать новое соединение для каждого отправляемого пакета.

Вы можете отправить несколько пакетов через постоянные соединения HTTP , где:

... используется одно TCP-соединение для отправки и получения нескольких HTTP-запросов / ответов, в отличие от открытия нового соединения для каждой отдельной пары запрос / ответ.

Прикрепленный рисунок показывает разницу между несколькими соединениями (множество соединений, созданных для отправки одного объекта на соединение) и постоянным соединением (установлено одно соединение и отправлено несколько объектов):

Несколько соединений против постоянного соединения

Источник: https://www.vcloudnine.de/how-to-dramatics-improve-website-load-times/


7
Этот ответ, кажется, сбивает с толку слоев. HTTP-запрос / ответ редко представляет собой один пакет.
Бармар

2
Не говоря уже о том, что каждое «открытие» на самом деле составляет 3 стрелки (syn, synack, ack), а каждое «закрытие» - это еще 4 (fin, ack 2x сервер и клиент), поэтому, если будет фактически соединение на пакет, накладные расходы бы быстро сложить.
htmlcoderexe

5

Ваша интерпретация работы TCP правильна.

Что касается того, что сказал ваш друг, я вижу здесь две возможности:

  1. Вы неправильно поняли своего друга, который имел в виду какое-то ограничение прикладного уровня, которое приводит к тому, что каждое сообщение отправляется по новому соединению (и это не обязательно является необычным; это может или не может быть возможным для выбора такого поведения, в зависимости от того, какое программное обеспечение стек, который вы используете);

  2. Твой друг не прав.


5

Как уже отмечали другие, TCP абсолютно позволяет соединению оставаться открытым в течение любого периода времени, обмениваясь любым количеством «сообщений» в любом направлении в течение этого времени. Тем не менее, в конечном счете, приложения (и клиент, и сервер) должны определить, используется ли эта возможность.

Чтобы повторно использовать существующее TCP-соединение (сокет), клиентское приложение должно держать этот сокет открытым и использовать его, когда необходимо записать больше данных. Если клиент этого не делает, а вместо этого отбрасывает старый сокет и открывает новый сокет каждый раз, когда он ему нужен, то он действительно вызовет новое соединение, которое может вызвать проблемы с ресурсами на клиенте или сервере, если сделать это достаточно часто для исчерпания ресурсов. либо пул соединений стека TCP.

Аналогично, сервер должен быть достаточно умен, чтобы держать сокет открытым на своей стороне и ждать большего количества данных. Как и клиент, он имеет возможность закрыть сокет, после чего отказоустойчивый клиент, желающий отправить больше данных, не будет иметь другого выбора, кроме как открыть новый сокет, что приведет к той же проблеме.

Наконец, как уже упоминалось, TCP ориентирован на поток. Там нет никакого обрамления вообще. Тот факт, что один узел записал данные определенным образом (например, 1 1024 байта вызова записи, за которым следуют 2 256 байтов записи вызова), не гарантирует, что другой узел будет читать их одинаковыми порциями (например, он может получить все 1536 байтов). в одном вызове чтения). Таким образом, если вы отправляете несколько «сообщений» по необработанным TCP-сокетам, вы должны предоставить свой собственный протокол кадрирования для разграничения различных сообщений. Хотя, безусловно, существуют простые способы сделать это, это, как правило, не рекомендуется, так как существует множество протоколов, построенных поверх TCP, для решения этой проблемы. Для дальнейшего обсуждения, обратитесь к этому: https://blog.stephencleary.com/2009/04/message-framing.html


2

Я думаю, что ваш друг говорил о HTTP, а не о TCP.

Первоначально HTTP был протоколом без сохранения состояния: каждый HTTP-запрос использовал бы отдельное TCP-соединение. Вот почему нам нужны куки (или что-то подобное) для реализации сессий.


0

Вы упомянули «одно соединение и каждый раз требуется новый порт», и я бы сказал, что у вас много клиентов, использующих технику PAT в одной сетевой среде для подключения к серверу за пределами вашей организации. PAT будет иметь ограничение 65535 (ограничение сеанса TCP для адреса IPv4). Если это правда, у вас есть предел.

Открывает ли TCP новое соединение для каждого отправляемого пакета? НЕТ, это не так долго, как сеанс TCP действителен. и ...


0

Мне нравится отличная страница википедии по TCP . Это ясно показывает, что происходит с номером порта. Он также содержит полезную главу по использованию ресурсов:

Использование ресурса

Большинство реализаций выделяют запись в таблице, которая отображает сеанс на работающий процесс операционной системы. Поскольку пакеты TCP не включают идентификатор сеанса, обе конечные точки идентифицируют сеанс, используя адрес и порт клиента. Всякий раз, когда пакет получен, реализация TCP должна выполнить поиск в этой таблице, чтобы найти процесс назначения. Каждая запись в таблице называется блоком управления передачей или TCB. Он содержит информацию о конечных точках (IP и порт), состоянии соединения, данных об обмене пакетами и буферах для отправки и получения данных.

Количество сеансов на стороне сервера ограничено только памятью и может увеличиваться по мере поступления новых соединений, но клиент должен выделить случайный порт перед отправкой первого SYN на сервер. Этот порт остается выделенным в течение всего сеанса связи и эффективно ограничивает количество исходящих соединений от каждого из IP-адресов клиента. Если приложению не удается правильно закрыть ненужные соединения, клиент может исчерпать ресурсы и не сможет установить новые соединения TCP, даже из других приложений.

Короче говоря, TCP использует один очень ограниченный ресурс, который представляет собой количество портов на клиенте (которое ограничено размером поля порта в заголовке TCP, 16 бит).

Таким образом, TCP является возможность запускать из портов, если клиент открывает много TCP соединений параллельно , не закрывая их. Проблема возникает только на стороне клиента, и не имеет значения, имеют ли соединения одинаковые или разные IP-адреса сервера или серверные порты.

В ваших настройках у вас, похоже, есть одно приложение, которое принимает множество клиентских запросов ( этиэто могут быть индивидуальные запросы TCP, как, например, ваши клиенты используют это для регистрации некоторых событий в вашем приложении и не удерживают канал TCP открытым между ними), и создают новый внутренний запрос к вашему брокеру Kafka (который очень легко может быть отдельными соединениями TCP если вы решили реализовать их так). В этом случае узкое место (с точки зрения ресурсов, а не производительности) будет в том случае, если вам удастся одновременно получать огромное количество запросов от ваших клиентов (для вас это не проблема, поскольку на стороне сервера вам нужен только один порт для все они), и вы открываете огромное количество запросов на пересылку к вашему Kafka, и Kafka не может обработать их достаточно быстро, и в результате вы получаете одновременно более 16 бит соединений.

Вы - собственный судья здесь; проверьте свое приложение и попытайтесь выяснить, подключаетесь ли вы к Kafka с помощью отдельного запроса каждый раз (возможно, через какой-нибудь прокси REST API). Если вы делаете это, и у вас есть огромное количество клиентов, то вы, безусловно, в опасности.

Если у вас есть всего несколько клиентов, менее 65 тыс. Штук, и / или вы сохраняете единственное соединение с браузером Kafka, то все будет в порядке.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.