(해석 또는 이해가 잘못된 부분이 있다면 댓글로 편하게 알려주세요.)
TCP has a data stream interface that permits applications to stream data of any size to the TCP stack—even a single byte at a time! But because each TCP segment carries at least 40 bytes of flags and headers, network performance can be degraded severely if TCP sends large numbers of packets containing small amounts of data.*
TCP는 전송할 데이터가 한 바이트일지라도 응용 프로그램이 한 번에 어느 사이즈의 데이터든 전송할 수 있게 하는 데이터 스트림 인터페이스를 보유하고 있습니다.
그러나 각각의 TCP 세그먼트는 최소 40바이트의 플래그와 헤더를 전송하기 때문에 TCP가 작은 양의 데이터를 포함한 패킷을 대량 전송하는 경우 네트워크 성능이 심각하게 저하될 수 있습니다.
Nagle’s algorithm (named for its creator, John Nagle) attempts to bundle up a large amount of TCP data before sending a packet, aiding network efficiency. The algorithm is described in RFC 896, “Congestion Control in IP/TCP Internetworks.”
Nagle 알고리즘(해당 알고리즘을 제작한 사람이 John Nagle)은 네트워크의 효율을 높이기 위해 패킷을 전송하기 전 다량의 TCP 데이터를 묶으려고 시도합니다.
이 알고리즘은 RFC 896 "Congestion Control in IP/TCP Internetworks"에 명시되어 있습니다.
Nagle’s algorithm discourages the sending of segments that are not full-size (a maximum-size packet is around 1,500 bytes on a LAN, or a few hundred bytes across the Internet). Nagle’s algorithm lets you send a non-full-size packet only if all other packets have been acknowledged. If other packets are still in flight, the partial data is buffered. This buffered data is sent only when pending packets are acknowldged or when the buffer has accumulated enough data to send a full packet.
Nagle 알고리즘은 최대 사이즈가 아닌 세그먼트들을 전송하는 것을 지양합니다. (패킷의 최대 사이즈는 LAN에서 약 1500바이트 혹은 인터넷을 통해 수백 바이트 정도입니다)
Nagle 알고리즘은 다른 모든 패킷이 ACK를 받았을 때만 최대 사이즈가 아닌 패킷을 전송할 수 있게 합니다.
만약 다른 패킷이 전송중이라면 데이터의 일부분은 버퍼됩니다.
이 버퍼된 데이터는 전송중인 패킷이 ACK를 받았거나 꽉 찬 패킷을 전송할 수 있을 만큼 충분한 데이터가 모였을 때 전송됩니다.
Nagle’s algorithm causes several HTTP performance problems. First, small HTTP messages may not fill a packet, so they may be delayed waiting for additional data that will never arrive. Second, Nagle’s algorithm interacts poorly with disabled acknowledgments—Nagle’s algorithm will hold up the sending of data until an acknowledgment arrives, but the acknowledgment itself will be delayed 100–200 milliseconds by the delayed acknowledgment algorithm.
Nagle 알고리즘은 몇 가지 HTTP 성능 문제를 야기합니다.
우선, 작은 HTTP 메시지는 패킷을 가득 채우지 않습니다. 이러한 메시지들은 절대 도착하지 않을 추가 정보를 기다리며 지연됩니다.
두 번째로, Nagle 알고리즘은 지연 확인 응답과 잘 상호작용하지 못합니다. 이것은 ACK가 도착할 때까지 데이터를 붙잡고 있지만 ACK는 지연 응답 알고리즘에 의해 그 자체로 100-200 밀리초만큼 지연될 것입니다.
(Nagle 알고리즘대로라면 ACK가 와야 다음 패킷이 전송되는데 Piggybacking 할 패킷 찾느라 ACK가 안 와서 더 오래 걸린다는 뜻)
HTTP applications often disable Nagle’s algorithm to improve performance, by setting the TCP_NODELAY parameter on their stacks. If you do this, you must ensure that you write large chunks of data to TCP so you don’t create a flurry of small packets.
일반적으로 HTTP 응용 프로그램은 스택에 TCP_NODELAY 파라미터를 세팅함으로써 성능 향상을 위해 Nagle 알고리즘을 비활성화합니다.
이렇게 하면 TCP에 많은 양의 데이터를 기록하여 작은 패킷을 만들지 않도록 해야 합니다.
TIME_WAIT port exhaustion is a serious performance problem that affects performance benchmarking but is relatively uncommon in real deployments. It warrants special attention because most people involved in performance benchmarking eventually run into this problem and get unexpectedly poor performance.
TIME_WAIT 포트 소진은 성능 벤치마킹에 영향을 미치는 심각한 성능 문제지만, 실제 구현에서는 상대적으로 흔하게 발생하지 않습니다.
성능 벤치마킹에 참여하는 대부분의 사람들은 결국 이 문제에 맞닥뜨려 예상치 못하게 성능이 저하되기 때문에 특별한 주의를 기울여야 합니다.
When a TCP endpoint closes a TCP connection, it maintains in memory a small control block recording the IP addresses and port numbers of the recently closed connection. This information is maintained for a short time, typically around twice the estimated maximum segment lifetime (called “2MSL”; often two minutes*), to make sure a new TCP connection with the same addresses and port numbers is not created during this time. This prevents any stray duplicate packets from the previous connection from accidentally being injected into a new connection that has the same addresses and port numbers. In practice, this algorithm prevents two connections with the exact same IP addresses and port numbers from being created, closed, and recreated within two minutes.
TCP 엔드포인트가 TCP 연결을 종료하면, 최근 종료된 연결의 IP 주소와 포트 번호를 기록하는 작은 제어 블록을 메모리에 유지합니다.
이 정보는 일정 시간 동안 동일한 주소와 포트 번호를 가진 새로운 TCP 연결이 생성되지 않게 하기 위해 잠시 동안 유지됩니다. 유지 시간은 일반적으로 예상되는 세그먼트의 최대 생존 시간의 두 배 정도입니다. (2MSL, 보통 2분)
이를 통해 이전 연결에서 배회하는 중복 패킷이 우연히 같은 주소와 포트 번호를 갖는 새 연결에 주입되지 않게 할 수 있습니다.
실제로 이 알고리즘은 정확히 동일한 IP 주소와 포트 넘버를 가지는 두 개의 연결이 생성 및 종료, 그리고 2분 이내에 재생성되는 것을 막습니다.
Today’s higher-speed routers make it extremely unlikely that a duplicate packet will show up on a server’s doorstep minutes after a connection closes. Some operating systems set 2MSL to a smaller value, but be careful about overriding this value. Packets do get duplicated, and TCP data will be corrupted if a duplicate packet from a past connection gets inserted into a new stream with the same connection values.
오늘날의 고속 라우터는 연결이 종료되고 몇 분 후 중복 패킷이 서버의 목전에 나타날 가능성을 극단적으로 줄어들게 합니다.
어떤 운영체제는 2MSL을 더 작은 값으로 설정하기도 하지만 값을 덮어쓰지 않게 조심해야 합니다.
패킷이 복제되고, 과거 연결로부터 중복 패킷이 동일한 연결 값을 가진 새로운 스트림으로 삽입된다면 TCP 데이터는 손상될 것입니다.
The 2MSL connection close delay normally is not a problem, but in benchmarking situations, it can be. It’s common that only one or a few test load-generation computers are connecting to a system under benchmark test, which limits the number of client IP addresses that connect to the server. Furthermore, the server typically is listening on HTTP’s default TCP port, 80. These circumstances limit the available combinations of connection values, at a time when port numbers are blocked from reuse by TIME_WAIT.
2MSL 연결 종료 지연은 보통 문제가 되지 않지만, 벤치마킹 상황에서는 문제가 될 수 있습니다.
벤치마크 테스트에서는 단 한 개, 혹은 아주 적은 수의 테스트 load-generation 컴퓨터가 시스템에 연결 중인 것이 일반적입니다. 이것은 서버에 연결하는 클라이언트의 IP 주소 개수를 제한합니다.
게다가 서버는 일반적으로 HTTP의 디폴트 TCP 포트 번호인 80에서 연결을 주시합니다.
이러한 상황은 포트 넘버가 TIME_WAIT에 의해 재사용이 불가능할 때 연결 값의 사용 가능한 조합 수를 제한합니다.
In a pathological situation with one client and one web server, of the four values that make up a TCP connection:
<source-IP-address, source-port, destination-IP-address, destination-port>
three of them are fixed—only the source port is free to change:
<client-IP, source-port, server-IP, 80>
하나의 클라이언트와 하나의 웹 서버가 존재하는 극한의 상황에서 TCP 연결을 만드는 4가지 값(soure-IP-address, source-port, destination-IP-address, destination-port) 중 세 가지는 하나의 값으로 고정되어 있습니다.
오직 소스 포트만이 변경할 수 있는 값입니다.
Each time the client connects to the server, it gets a new source port in order to have a unique connection. But because a limited number of source ports are available (say, 60,000) and no connection can be reused for 2MSL seconds (say, 120 sec- onds), this limits the connect rate to 60,000 / 120 = 500 transactions/sec. If you keep making optimizations, and your server doesn’t get faster than about 500 transactions/sec, make sure you are not experiencing TIME_WAIT port exhaustion. You can fix this problem by using more client load-generator machines or making sure the client and server rotate through several virtual IP addresses to add more connection combinations.
클라이언트는 서버에 연결할 때마다 고유한 연결을 위해 새로운 소스 포트 번호를 할당 받습니다.
그러나 사용할 수 있는 소스 포트의 수가 제한되어 있고(통상 60000개) 2MSL 초(통상 120초) 동안 어떠한 연결도 재사용할 수 없기 때문에 이러한 제한은 연결 속도를 초당 60000/120 = 500 트랜잭션으로 제한합니다.
최적화를 계속 하고 있음에도 여러분의 서버가 초당 500 트랜잭션의 속도보다 빨라지지 않는다면 TIME_WAIT 포트 소진이 발생하지 않았는지 확인해봐야 합니다.
이 문제는 더 많은 클라이언트 load-generator 장치를 활용하거나, 클라이언트와 서버가 가상 IP 주소를 통해 더 많은 연결 조합을 생성하도록 순환하게 함으로써 해결할 수 있습니다.
Even if you do not suffer port exhaustion problems, be careful about having large numbers of open connections or large numbers of control blocks allocated for connection in wait states. Some operating systems slow down dramatically when there are numerous open connections or control blocks.
여러분이 포트 소진 문제로 골머리를 앓지 않았다고 하더라도, 대기 상태에서 다수의 열린 연결을 가지거나 제어 블록이 할당되는 것을 경계하는 것이 좋습니다.
일부 운영체제는 수많은 열린 연결이나 제어 블록이 있을 때 극단적으로 느려지기도 합니다.
절대 의지가 꺾여서 하루 포스팅 안 쓴 건 아니고,, 그냥,,, 일요일이라 놀러 갔다 와서 안 썼습니다,, 사실 시간은 있었는데,,, 운영체제 공부하다가 화딱지나서 그냥 자버렸어용 ㅎ ㅎㅎ ㅎ 반성하겠습니다.
오늘 내용은 저에게도 완전히 새로운 내용이었답니다!! Slow Start나 Delayed Acknowledgment, Handshake에 의한 지연은 이미 조금 알고 있던 내용이라 휙휙 잘 읽혔는데 오늘 분량은 읽기 조금 힘들었습니다. 모르는 내용인데 텍스트는 고봉밥 ㅠㅠ 그래도 공강 시간에 짬짬이 다 읽어냈습니다.
만약 오늘 내용을 몰랐다면, 최적화를 했는데도 테스트에서 더 이상 속도가 개선되지 않을 때 어디가 문제인 건지 한참 찾아야 했을 겁니다. 자주 발생하는 문제는 아니지만 HTTP를 사용해서 서비스를 개발하는 사람이라면 이런 지식이 언젠가 도움이 될 날이 올 거라고 생각합니다.