Это может быть глупый вопрос, но я и несколько приятелей обсуждали потенциальные ограничения TCP. У нас есть приложение, которое будет прослушивать клиентов (например, шлюз) и направлять данные всех подключенных клиентов через одного подключенного издателя kafka в одну тему.
Один из моих собеседников говорит, что TCP будет проблемой для этого шлюза, потому что он собирается устанавливать новое соединение для каждого отправляемого сообщения (проблема не в kafka, а в самом базовом транспортном протоколе), каждый раз требуя новый порт. С той скоростью, с которой мы будем отправлять сообщения этим клиентам (гигабайты), у kafka не хватит портов для чтения ??
Я занимался разработкой в течение нескольких лет и никогда не слышал об этом раньше, и хотел бы получить более низкое понимание (как я думал, я имел) того, как работает TCP. Насколько я понимаю, когда вы устанавливаете TCP-соединение, это соединение остается открытым до тех пор, пока оно не будет заблокировано приложением или принудительно закрыто сервером или клиентом. Данные, которые отправляются через это соединение, являются потоком и не будут открывать / закрывать новые соединения независимо от 3 В (объем, скорость, разнообразие).
Что касается портов, один порт используется для широковещательной передачи, а порт внутреннего дескриптора файла - это то, что приложение управляет для чтения / записи отдельных клиентов. Я никогда не понимал TCP, чтобы устанавливать новые соединения для каждого пакета, который он пишет.
Я заранее прошу прощения, если этот вопрос не является прямым или слишком расплывчатым. Я действительно сбит с толку и надеюсь, что кто-нибудь сможет предоставить больше контекста тому, что говорят мои коллеги?
источник
SO_REUSEADDR
для более быстрого закрытия сокетов, увеличения диапазона временных портов и т. Д. Кроме того,TCP_FASTOPEN
можно использовать несколько переключателей на уровне ОС, чтобы обойти другие хорошо известные ограничения TCP. В любом случае, нет смысла обсуждать ограничения TCP, когда у вас даже нет рабочей нагрузки для тестирования.Ответы:
Твой друг в замешательстве. TCP является потоковым протоколом. Он не имеет понятия о сообщениях. Конечно, он использует пакеты на уровне IP, но для приложения это деталь реализации. TCP вставляет границы пакетов там, где это имеет смысл, и не обязательно один раз для
write()
илиsend()
. Точно так же он объединяет последовательные пакеты вместе, если вы получаете более одного между вызовамиread()
илиrecv()
.Само собой разумеется, этот ориентированный на поток дизайн был бы совершенно неработоспособным, если бы каждая отправка установила новое соединение. Таким образом, единственный способ установить новое соединение - закрыть и снова открыть соединение вручную.
(На практике большинство протоколов, построенных поверх TCP, имеют нечто, напоминающее сообщения, такие как HTTP-запросы и ответы. Но TCP не знает и не заботится о структуре таких вещей.)
Вполне возможно, что ваш друг думал о UDP, который имеет сообщения, но также не имеет соединения. Большинство реализаций сокетов позволяют вам «подключать» сокет UDP к удаленному хосту, но это всего лишь удобный способ избежать повторного указания IP-адреса и порта. На самом деле он ничего не делает на сетевом уровне. Тем не менее, вы можете вручную отслеживать, с какими пирами вы общаетесь по UDP. Но если вы это сделаете, то решить, что считать «соединением», будет ваша проблема, а не ОС. Если вы хотите восстановить «соединение» для каждого сообщения, вы можете сделать это. Это, вероятно, не очень хорошая идея, однако.
источник
С точки зрения TCP, нет ни клиента, ни сервера (клиент / сервер - это концепция приложения, которая здесь не по теме). TCP устанавливает соединение между одноранговыми узлами, и оба одноранговых узла могут отправлять и получать по соединению, пока одно из них не закроет его или не истечет время ожидания из-за неактивности.
Что может сбить с толку, так это то, что некоторые приложения, например браузеры, открывают несколько соединений, чтобы одновременно загружать такие элементы, как элементы веб-страницы.
TCP не открывает новое соединение для каждого отправляемого сегмента, но приложение может открыть несколько соединений TCP. Кроме того, когда соединение TCP закрыто, порт TCP, используемый в соединении, освобождается и становится доступным для повторного использования. Этот ответ дает некоторую информацию и указывает на RFC для TCP.
источник
Нет, TCP не нужно открывать новое соединение для каждого отправляемого пакета.
Вы можете отправить несколько пакетов через постоянные соединения HTTP , где:
Прикрепленный рисунок показывает разницу между несколькими соединениями (множество соединений, созданных для отправки одного объекта на соединение) и постоянным соединением (установлено одно соединение и отправлено несколько объектов):
Источник: https://www.vcloudnine.de/how-to-dramatics-improve-website-load-times/
источник
Ваша интерпретация работы TCP правильна.
Что касается того, что сказал ваш друг, я вижу здесь две возможности:
Вы неправильно поняли своего друга, который имел в виду какое-то ограничение прикладного уровня, которое приводит к тому, что каждое сообщение отправляется по новому соединению (и это не обязательно является необычным; это может или не может быть возможным для выбора такого поведения, в зависимости от того, какое программное обеспечение стек, который вы используете);
Твой друг не прав.
источник
Как уже отмечали другие, TCP абсолютно позволяет соединению оставаться открытым в течение любого периода времени, обмениваясь любым количеством «сообщений» в любом направлении в течение этого времени. Тем не менее, в конечном счете, приложения (и клиент, и сервер) должны определить, используется ли эта возможность.
Чтобы повторно использовать существующее TCP-соединение (сокет), клиентское приложение должно держать этот сокет открытым и использовать его, когда необходимо записать больше данных. Если клиент этого не делает, а вместо этого отбрасывает старый сокет и открывает новый сокет каждый раз, когда он ему нужен, то он действительно вызовет новое соединение, которое может вызвать проблемы с ресурсами на клиенте или сервере, если сделать это достаточно часто для исчерпания ресурсов. либо пул соединений стека TCP.
Аналогично, сервер должен быть достаточно умен, чтобы держать сокет открытым на своей стороне и ждать большего количества данных. Как и клиент, он имеет возможность закрыть сокет, после чего отказоустойчивый клиент, желающий отправить больше данных, не будет иметь другого выбора, кроме как открыть новый сокет, что приведет к той же проблеме.
Наконец, как уже упоминалось, TCP ориентирован на поток. Там нет никакого обрамления вообще. Тот факт, что один узел записал данные определенным образом (например, 1 1024 байта вызова записи, за которым следуют 2 256 байтов записи вызова), не гарантирует, что другой узел будет читать их одинаковыми порциями (например, он может получить все 1536 байтов). в одном вызове чтения). Таким образом, если вы отправляете несколько «сообщений» по необработанным TCP-сокетам, вы должны предоставить свой собственный протокол кадрирования для разграничения различных сообщений. Хотя, безусловно, существуют простые способы сделать это, это, как правило, не рекомендуется, так как существует множество протоколов, построенных поверх TCP, для решения этой проблемы. Для дальнейшего обсуждения, обратитесь к этому: https://blog.stephencleary.com/2009/04/message-framing.html
источник
Я думаю, что ваш друг говорил о HTTP, а не о TCP.
Первоначально HTTP был протоколом без сохранения состояния: каждый HTTP-запрос использовал бы отдельное TCP-соединение. Вот почему нам нужны куки (или что-то подобное) для реализации сессий.
источник
Вы упомянули «одно соединение и каждый раз требуется новый порт», и я бы сказал, что у вас много клиентов, использующих технику PAT в одной сетевой среде для подключения к серверу за пределами вашей организации. PAT будет иметь ограничение 65535 (ограничение сеанса TCP для адреса IPv4). Если это правда, у вас есть предел.
Открывает ли TCP новое соединение для каждого отправляемого пакета? НЕТ, это не так долго, как сеанс TCP действителен. и ...
источник
Мне нравится отличная страница википедии по TCP . Это ясно показывает, что происходит с номером порта. Он также содержит полезную главу по использованию ресурсов:
Короче говоря, TCP использует один очень ограниченный ресурс, который представляет собой количество портов на клиенте (которое ограничено размером поля порта в заголовке TCP, 16 бит).
Таким образом, TCP является возможность запускать из портов, если клиент открывает много TCP соединений параллельно , не закрывая их. Проблема возникает только на стороне клиента, и не имеет значения, имеют ли соединения одинаковые или разные IP-адреса сервера или серверные порты.
В ваших настройках у вас, похоже, есть одно приложение, которое принимает множество клиентских запросов ( этиэто могут быть индивидуальные запросы TCP, как, например, ваши клиенты используют это для регистрации некоторых событий в вашем приложении и не удерживают канал TCP открытым между ними), и создают новый внутренний запрос к вашему брокеру Kafka (который очень легко может быть отдельными соединениями TCP если вы решили реализовать их так). В этом случае узкое место (с точки зрения ресурсов, а не производительности) будет в том случае, если вам удастся одновременно получать огромное количество запросов от ваших клиентов (для вас это не проблема, поскольку на стороне сервера вам нужен только один порт для все они), и вы открываете огромное количество запросов на пересылку к вашему Kafka, и Kafka не может обработать их достаточно быстро, и в результате вы получаете одновременно более 16 бит соединений.
Вы - собственный судья здесь; проверьте свое приложение и попытайтесь выяснить, подключаетесь ли вы к Kafka с помощью отдельного запроса каждый раз (возможно, через какой-нибудь прокси REST API). Если вы делаете это, и у вас есть огромное количество клиентов, то вы, безусловно, в опасности.
Если у вас есть всего несколько клиентов, менее 65 тыс. Штук, и / или вы сохраняете единственное соединение с браузером Kafka, то все будет в порядке.
источник