TCP có mở một kết nối mới cho mỗi gói được gửi không?


15

Đây có thể là một câu hỏi ngớ ngẩn nhưng tôi và một vài người bạn đã thảo luận về những hạn chế tiềm ẩn của TCP. Chúng tôi có một ứng dụng sẽ lắng nghe khách hàng (nghĩ về một cổng) và định tuyến tất cả dữ liệu khách hàng được kết nối thông qua một nhà xuất bản kafka được kết nối đến một chủ đề.

Một trong những người bạn của tôi nói rằng TCP sẽ là một vấn đề đối với cổng này bởi vì nó sẽ thiết lập một kết nối mới cho mỗi tin nhắn mà nó gửi (không phải kafka mà chính giao thức vận chuyển cơ bản là vấn đề), mỗi lần cần một cổng mới. Với tốc độ chúng tôi sẽ gửi những tin nhắn khách hàng này (gigabyte), kafka sẽ hết cổng để đọc từ ??

Tôi đã thực hiện phát triển trong vài năm và chưa bao giờ nghe về điều này trước đây và muốn có được sự hiểu biết ở cấp độ thấp hơn (mà tôi nghĩ rằng tôi có) về cách thức hoạt động của TCP. Tôi hiểu rằng khi bạn thiết lập kết nối TCP, kết nối đó vẫn mở cho đến khi ứng dụng hết thời gian hoặc bị đóng bởi máy chủ hoặc máy khách. Dữ liệu được gửi qua kết nối này là một luồng và sẽ không mở / đóng các kết nối mới bất kể 3 V (âm lượng, vận tốc, sự đa dạng).

Theo như các cổng, một cổng được sử dụng để phát sóng và cổng mô tả tệp nội bộ là thứ mà ứng dụng quản lý để đọc / ghi của từng máy khách. Tôi chưa bao giờ hiểu TCP để thiết lập các kết nối mới cho mỗi gói mà nó ghi.

Tôi xin lỗi trước nếu câu hỏi này không trực tiếp và quá mơ hồ. Tôi thực sự bối rối và đang hy vọng ai đó có thể cung cấp thêm một số bối cảnh cho những gì đồng nghiệp của tôi đang nói?


13
Tôi nghĩ bạn đã hiểu nhầm những gì bạn của bạn đang nói. TCP không làm như vậy, nhưng có thể một khách hàng nhất định sẽ tạo kết nối TCP mới cho mỗi thông báo mà nó muốn truyền.
hobbs

13
TCP không thể mở kết nối mới cho mỗi gói vì nó cần nhiều gói để mở kết nối mới. Và nó không thể mở một kết nối mới cho mỗi tin nhắn vì TCP không có khái niệm về tin nhắn. Bạn thân của bạn rất bối rối. Điều quan trọng nhất để hiểu về TCP, khái niệm cơ bản nhất, đó là TCP là một giao thức luồng byte.
David Schwartz

1
Đối số của bạn bè của bạn không nhất thiết sai - nếu bạn không sử dụng lại các cổng thông qua cấp độ ứng dụng hoặc đơn giản là có quá nhiều khách hàng, hệ thống của bạn có thể hết các cổng phù du. Có nhiều cách để khắc phục vấn đề đó: sử dụng SO_REUSEADDRđể đóng ổ cắm nhanh hơn, tăng phạm vi cổng phù du, v.v. Ngoài ra TCP_FASTOPEN, một số toggles cấp hệ điều hành có thể được sử dụng để khắc phục các hạn chế nổi tiếng khác của TCP. Dù bằng cách nào, không có lý do nào để thảo luận về các hạn chế của TCP khi bạn thậm chí không có khối lượng công việc để kiểm tra.
dùng1643723

Câu trả lời:


22

Một trong những người bạn của tôi nói rằng TCP sẽ là một vấn đề đối với cổng này bởi vì nó sẽ thiết lập một kết nối mới cho mỗi tin nhắn mà nó gửi (không phải kafka mà chính giao thức vận chuyển cơ bản là vấn đề), mỗi lần cần một cổng mới. Với tốc độ chúng tôi sẽ gửi những tin nhắn khách hàng này (gigabyte), kafka sẽ hết cổng để đọc từ ??

Bạn của bạn đang rất bối rối. TCP là một giao thức hướng luồng. Nó không có khái niệm về tin nhắn. Tất nhiên, nó sử dụng các gói ở lớp IP, nhưng với ứng dụng thì đây là một chi tiết triển khai. TCP chèn các ranh giới gói trong đó có ý nghĩa để làm như vậy và không nhất thiết phải một lần cho mỗi write()hoặcsend() . Tương tự, nó kết hợp các gói liên tiếp với nhau nếu bạn nhận được nhiều hơn một giữa các cuộc gọi đến read()hoặc recv().

Không cần phải nói, thiết kế hướng luồng này sẽ hoàn toàn không khả thi nếu mỗi lần gửi thiết lập một kết nối mới. Vì vậy, cách duy nhất để thiết lập kết nối mới là đóng và mở lại kết nối theo cách thủ công.

(Trong thực tế, hầu hết các giao thức được xây dựng trên TCP đều có thứ giống với các thông điệp, chẳng hạn như các yêu cầu và phản hồi HTTP. Nhưng TCP không biết hoặc không quan tâm đến cấu trúc của những thứ đó.)

Có thể bạn của bạn đã nghĩ về UDP, có tin nhắn, nhưng cũng không có kết nối. Hầu hết các cài đặt ổ cắm cho phép bạn "kết nối" ổ cắm UDP với máy chủ từ xa, nhưng đây chỉ là một cách thuận tiện để tránh phải liên tục chỉ định địa chỉ IP và cổng. Nó không thực sự làm bất cứ điều gì ở cấp độ mạng. Tuy nhiên, bạn có thể theo dõi thủ công những đồng nghiệp mà bạn đang nói chuyện trong UDP. Nhưng nếu bạn làm điều đó, thì việc quyết định cái gì được coi là "kết nối" là vấn đề của bạn chứ không phải của HĐH. Nếu bạn muốn thiết lập lại "kết nối" trên mỗi tin nhắn, bạn có thể làm điều đó. Nó có thể không phải là một ý tưởng rất tốt, tuy nhiên.


9

Tôi hiểu rằng khi bạn thiết lập kết nối TCP, kết nối đó vẫn mở cho đến khi ứng dụng hết thời gian hoặc bị đóng bởi máy chủ hoặc máy khách.

Từ quan điểm của TCP, không có máy khách hoặc máy chủ (máy khách / máy chủ là một khái niệm ứng dụng không có chủ đề ở đây). TCP thiết lập kết nối giữa các thiết bị ngang hàng và cả hai thiết bị ngang hàng có thể gửi và nhận trên kết nối cho đến khi một thiết bị ngang hàng đóng lại hoặc hết thời gian không hoạt động.

Dữ liệu được gửi qua kết nối này là một luồng và sẽ không mở / đóng các kết nối mới bất kể 3 V (âm lượng, vận tốc, sự đa dạng).

Điều có thể gây nhầm lẫn trong tình huống là một số ứng dụng, ví dụ như trình duyệt, sẽ mở nhiều kết nối để tải đồng thời những thứ như các thành phần của trang web.

TCP không mở kết nối mới cho mọi phân đoạn mà nó gửi, nhưng một ứng dụng có thể mở nhiều kết nối TCP. Ngoài ra, khi đóng kết nối TCP, cổng TCP được sử dụng trong kết nối sẽ được giải phóng và có sẵn để sử dụng lại. Câu trả lời này cung cấp một số thông tin và nó đưa bạn đến RFC cho TCP.


2
Mặc dù trong TCP có một đối tác khởi tạo kết nối (thường được gọi là "máy khách") và đối tác khác (thường được gọi là "máy chủ"). Tất nhiên, sau khi kết nối được thiết lập, sự khác biệt này không còn quan trọng nữa.
Paŭlo Ebermann

2
@ PaŭloEbermann, không có gì trong TCP RFC về máy khách hoặc máy chủ. Khái niệm máy khách / máy chủ là một khái niệm ứng dụng. Chủ đề ở đây là các giao thức ở hoặc dưới OSI lớp 4 và không có máy khách hoặc máy chủ nào trong các giao thức đó. Trong thực tế, trên thực tế, những gì bạn có thể giả sử là một máy khách (ứng dụng mở kết nối TCP) trên thực tế có thể là một máy chủ ứng dụng. Chúng tôi có các máy chủ khởi tạo kết nối TCP đến máy khách để thực hiện những việc như kiểm tra và cập nhật bảo mật.
Ron Maupin

7

Không, TCP không cần mở kết nối mới cho mỗi gói được gửi.

Bạn có thể gửi nhiều gói bằng các kết nối liên tục HTTP , trong đó:

... một kết nối TCP duy nhất để gửi và nhận nhiều yêu cầu / phản hồi HTTP [được sử dụng], trái ngược với việc mở một kết nối mới cho mỗi cặp yêu cầu / phản hồi.

Đính kèm là hình hiển thị sự khác biệt giữa nhiều kết nối (nhiều kết nối được thiết lập để gửi một đối tượng trên mỗi kết nối) và kết nối liên tục (một kết nối được thiết lập và nhiều đối tượng được gửi trong đó):

Nhiều kết nối và kết nối liên tục

Nguồn: https://www.vcloudnine.de/how-to-dramatically-improve-website-load-times/


7
Câu trả lời này dường như là các lớp khó hiểu. Một yêu cầu / phản hồi HTTP hiếm khi là một gói duy nhất.
Barmar

2
Chưa kể mỗi "mở" thực sự là 3 mũi tên (đồng bộ, đồng bộ, ack) và mỗi "đóng" là 4 (máy chủ, máy chủ ack 2x và máy khách) khác, vì vậy nếu thực sự sẽ có một kết nối cho mỗi gói, thì trên đầu sẽ nhanh chóng thêm lên.
htmlcoderexe

5

Giải thích của bạn về cách thức hoạt động của TCP là chính xác.

Đối với những gì bạn của bạn nói, tôi thấy hai khả năng ở đây:

  1. Bạn đã hiểu nhầm bạn của mình, người đã đề cập đến một số giới hạn ở lớp ứng dụng dẫn đến mỗi tin nhắn được gửi qua một kết nối mới (và điều này không nhất thiết là bất thường; có thể hoặc không thể quyết định hành vi này, tùy thuộc vào phần mềm nào ngăn xếp bạn đang sử dụng);

  2. Bạn của bạn sai rồi.


5

Như những người khác đã chỉ ra, TCP hoàn toàn cho phép kết nối mở trong bất kỳ khoảng thời gian nào, trao đổi bất kỳ số lượng "tin nhắn" nào theo bất kỳ hướng nào trong thời gian đó. Điều đó nói rằng, cuối cùng tùy thuộc vào các ứng dụng (cả máy khách và máy chủ) để xác định xem khả năng đó có được sử dụng hay không.

Để sử dụng lại kết nối TCP (socket) hiện có, ứng dụng khách phải giữ cho socket đó mở và sử dụng nó khi cần ghi thêm dữ liệu. Nếu máy khách không làm điều này mà thay vào đó loại bỏ ổ cắm cũ và mở một ổ cắm mới mỗi khi nó cần, thì nó thực sự sẽ buộc một kết nối mới có thể gây ra sự cố tài nguyên trên máy khách hoặc máy chủ nếu được thực hiện thường xuyên đủ để cạn kiệt hoặc nhóm kết nối TCP stack.

Tương tự như vậy, máy chủ phải đủ thông minh để giữ cho ổ cắm mở về phía nó và chờ thêm dữ liệu. Giống như máy khách, nó có tùy chọn đóng ổ cắm mà tại đó máy khách chịu lỗi muốn gửi thêm dữ liệu sẽ không có lựa chọn nào khác ngoài việc mở ổ cắm mới, dẫn đến cùng một vấn đề.

Cuối cùng, như những người khác đã đề cập, TCP được định hướng theo luồng. Không có khung nào. Chỉ vì một người ngang hàng đã ghi dữ liệu theo một cách cụ thể (ví dụ: 1 cuộc gọi ghi 1024 byte theo sau 2 cuộc gọi ghi 256 byte), điều đó không đảm bảo rằng người ngang hàng khác sẽ đọc nó trong các đoạn có cùng kích thước (ví dụ: có thể nhận được tất cả 1536 byte trong một cuộc gọi đọc). Do đó, nếu bạn đang gửi nhiều "tin nhắn" qua các socket TCP thô, bạn phải cung cấp giao thức đóng khung của riêng mình để phân định các tin nhắn khác nhau. Mặc dù chắc chắn có những cách đơn giản để làm điều này, nhưng nói chung là không nên vì có nhiều giao thức được xây dựng trên TCP để giải quyết vấn đề này. Để thảo luận thêm, hãy tham khảo ý kiến ​​này: https://blog.stephencleary.com/2009/04/message-framing.html


2

Tôi nghĩ bạn của bạn đã nói về HTTP, không phải TCP.

HTTP ban đầu là một giao thức không trạng thái: mỗi yêu cầu HTTP sẽ sử dụng một kết nối TCP riêng. Đây là lý do tại sao chúng ta cần cookie (hoặc một cái gì đó tương tự) để thực hiện các phiên.


0

Bạn đã đề cập đến "kết nối đơn và yêu cầu một cổng mới mỗi lần" và tôi sẽ giải thích khi bạn có nhiều máy khách sử dụng kỹ thuật PAT trong cùng môi trường mạng để kết nối với máy chủ bên ngoài tổ chức của bạn. PAT sẽ có giới hạn 65535 (giới hạn phiên TCP trên Địa chỉ IPv4). Nếu nó là sự thật, bạn có giới hạn.

TCP có mở một kết nối mới cho mỗi gói được gửi không? KHÔNG, nó không miễn là phiên TCP hợp lệ. và ...


0

Tôi thích trang wikipedia tuyệt vời trên TCP . Nó cho thấy rõ những gì xảy ra với số cổng. Nó, tình cờ, cũng chứa một chương hữu ích về việc sử dụng ressource:

Sử dụng tài nguyên

Hầu hết các triển khai đều phân bổ một mục trong bảng ánh xạ phiên tới quy trình hệ điều hành đang chạy. Vì các gói TCP không bao gồm định danh phiên, cả hai điểm cuối đều xác định phiên sử dụng địa chỉ và cổng của máy khách. Bất cứ khi nào một gói được nhận, việc triển khai TCP phải thực hiện tra cứu trên bảng này để tìm quá trình đích. Mỗi mục trong bảng được gọi là Khối điều khiển truyền hoặc TCB. Nó chứa thông tin về các điểm cuối (IP và cổng), trạng thái của kết nối, chạy dữ liệu về các gói đang được trao đổi và bộ đệm để gửi và nhận dữ liệu.

Số lượng phiên ở phía máy chủ chỉ bị giới hạn bởi bộ nhớ và có thể tăng lên khi có kết nối mới, nhưng máy khách phải phân bổ một cổng ngẫu nhiên trước khi gửi SYN đầu tiên đến máy chủ. Cổng này vẫn được phân bổ trong toàn bộ cuộc trò chuyện và giới hạn hiệu quả số lượng kết nối đi từ mỗi địa chỉ IP của khách hàng. Nếu một ứng dụng không đóng đúng các kết nối không được yêu cầu, máy khách có thể hết tài nguyên và không thể thiết lập các kết nối TCP mới, ngay cả từ các ứng dụng khác.

Nói tóm lại, TCP sử dụng tối đa một nguồn tài nguyên rất hữu hạn, đó là số lượng cổng trên máy khách (bị giới hạn bởi kích thước của trường cổng trong tiêu đề TCP, 16 bit).

Vì vậy, TCP có thể chạy ra khỏi cổng, nếu một khách hàng mở ra rất nhiều kết nối TCP song song mà không cần đóng. Sự cố chỉ xảy ra ở phía máy khách và không có vấn đề gì nếu các kết nối có cùng địa chỉ IP máy chủ hoặc cổng máy chủ khác nhau.

Trong cài đặt của bạn, dường như bạn có một ứng dụng nhận nhiều yêu cầu của khách hàng ( những ứng dụng nàycó thể là các yêu cầu TCP riêng lẻ, vì có thể khách hàng của bạn sử dụng điều này để ghi nhật ký một số sự kiện vào ứng dụng của bạn và không giữ kênh TCP mở giữa chừng) và tạo một yêu cầu nội bộ mới cho nhà môi giới Kafka của bạn (rất dễ có thể là các kết nối TCP riêng lẻ nếu bạn chọn thực hiện chúng như thế này). Trong trường hợp này, nút cổ chai (về nguồn tài nguyên, không phải hiệu suất) sẽ là nếu bạn quản lý để nhận được số lượng lớn yêu cầu cùng lúc từ khách hàng của mình (không có vấn đề gì với bạn, vì về phía máy chủ, bạn chỉ cần một cổng cho tất cả trong số họ) và bạn mở ra một số lượng lớn yêu cầu chuyển tiếp tới Kafka của bạn và Kafka không thể xử lý chúng đủ nhanh, kết thúc là bạn có các kết nối trị giá hơn 16 bit được mở đồng thời.

Bạn là thẩm phán riêng ở đây; kiểm tra ứng dụng của bạn và thử tìm hiểu xem bạn có đang kết nối với Kafka với một yêu cầu riêng biệt mỗi lần không (có thể thông qua một số proxy API REST). Nếu bạn làm như vậy, và bạn có số lượng khách hàng khổng lồ, thì bạn chắc chắn đang gặp nguy hiểm.

Nếu bạn chỉ có một số ít khách hàng, dưới 65 nghìn đồng và / hoặc bạn giữ một kết nối duy nhất với trình duyệt Kafka của mình, thì bạn sẽ ổn thôi.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.