Thay đổi giá trị TCP RTO trong Linux


12

Tôi muốn thay đổi giá trị TCP RTO (thời gian chờ truyền lại) cho một kết nối và một số cách đọc tôi đã thực hiện cho thấy rằng tôi có thể làm điều này, nhưng không tiết lộ vị trí và cách thay đổi nó.

Tôi đã xem xét các /proc/sys/net/ipv4biến, nhưng không có biến nào liên quan đến RTO. Tôi sẽ đánh giá cao nếu ai đó có thể cho tôi biết cách thay đổi giá trị này.


Điều này không làm việc cho tôi. Ở mức tối thiểu bao gồm 'ms' với thời gian rto cho tôi một lỗi! Tôi đã nhận được lệnh để làm việc, nhưng ss -i nói khác. Hơn nữa, 2 lọ sysctl không tồn tại. Tôi đang chạy trên kernel 4.4
Mark Seger

Tôi đã thử trên một bản phân phối gần đây hơn và đã thực hiện thành công ip route replacethay vào đó - có vẻ như ip routecú pháp đã thay đổi một chút. Tôi đã có thể thực hiện sửa đổi thành công mặc dù. Chỉ cần lưu ý, bạn nên bình luận về câu trả lời, không phải câu hỏi nếu bạn muốn ping tôi - về cơ bản tôi đã thấy điều này một cách tình cờ, may mắn thuần túy là nó gần đây :)
Adam C

Câu trả lời:


30

Lý do bạn không thể thay đổi RTO cụ thể là vì đó không phải là giá trị tĩnh. Thay vào đó (ngoại trừ SYN ban đầu, một cách tự nhiên), nó dựa trên RTT (Thời gian khứ hồi) cho mỗi kết nối. Trên thực tế, nó dựa trên một phiên bản RTT được làm mịn và phương sai RTT với một số hằng số được đưa vào hỗn hợp. Do đó, đây là một giá trị động, được tính toán cho mỗi kết nối TCP và tôi rất khuyến nghị bài viết này sẽ đi sâu vào chi tiết hơn về tính toán và RTO nói chung.

Cũng có liên quan là RFC 6298 , trong đó nêu rõ (trong số rất nhiều thứ khác):

Bất cứ khi nào RTO được tính toán, nếu nó nhỏ hơn 1 giây, thì RTO NÊN được làm tròn lên đến 1 giây.

Có phải kernel luôn đặt RTO thành 1 giây không? Chà, với Linux, bạn có thể hiển thị các giá trị RTO hiện tại cho các kết nối mở của mình bằng cách chạy ss -ilệnh:

State       Recv-Q Send-Q                                                  Local Address:Port     Peer Address:Port
ESTAB       0      0                                                           10.0.2.15:52861   216.58.219.46:http
     cubic rto:204 rtt:4/2 cwnd:10 send 29.2Mbps rcv_space:14600
ESTAB       0      0                                                           10.0.2.15:ssh          10.0.2.2:52586
     cubic rto:201 rtt:1.5/0.75 ato:40 cwnd:10 send 77.9Mbps rcv_space:14600
ESTAB       0      0                                                           10.0.2.15:52864   216.58.219.46:http
     cubic rto:204 rtt:4.5/4.5 cwnd:10 send 26.0Mbps rcv_space:14600

Trên đây là đầu ra từ một VM mà tôi đã đăng nhập bằng SSH và có một vài kết nối mở tới google.com. Như bạn có thể thấy, RTO trên thực tế được đặt thành 200-ish (mili giây). Bạn sẽ lưu ý rằng không được làm tròn đến giá trị 1 giây từ RFC và bạn cũng có thể nghĩ rằng nó hơi cao. Đó là bởi vì có giới hạn tối thiểu (200 mili giây) và tối đa (120 giây) khi nói về RTO cho Linux (có một lời giải thích tuyệt vời về điều này trong bài viết tôi đã liên kết ở trên).

Vì vậy, bạn không thể thay đổi trực tiếp giá trị RTO, nhưng đối với các mạng bị mất (như không dây), bạn có thể thử điều chỉnh F-RTO (điều này có thể đã được bật tùy thuộc vào bản phân phối của bạn). Thực tế, có hai tùy chọn liên quan đến F-RTO mà bạn có thể điều chỉnh (tóm tắt tốt ở đây ):

net.ipv4.tcp_frto
net.ipv4.tcp_frto_response

Tùy thuộc vào những gì bạn đang cố gắng tối ưu hóa, những thứ này có thể có hoặc không hữu ích.

EDIT: theo dõi khả năng điều chỉnh các giá trị rto_min / max cho TCP từ các bình luận.

Bạn không thể thay đổi RTO tối thiểu toàn cầu cho TCP (như một bên, bạn có thể làm điều đó cho SCTP - những thứ được hiển thị trong sysctl), nhưng tin tốt là bạn có thể điều chỉnh giá trị tối thiểu của RTO trên mỗi tuyến nền tảng. Đây là bảng định tuyến của tôi trên máy ảo CentOS của tôi:

ip route
10.0.2.0/24 dev eth0  proto kernel  scope link  src 10.0.2.15 
169.254.0.0/16 dev eth0  scope link  metric 1002 
default via 10.0.2.2 dev eth0

Tôi có thể thay đổi giá trị rto_min trên tuyến mặc định như sau:

ip route change default via 10.0.2.2 dev eth0 rto_min 5ms

Và bây giờ, bảng định tuyến của tôi trông như thế này:

ip route
10.0.2.0/24 dev eth0  proto kernel  scope link  src 10.0.2.15 
169.254.0.0/16 dev eth0  scope link  metric 1002 
default via 10.0.2.2 dev eth0  rto_min lock 5ms

Cuối cùng, hãy bắt đầu một kết nối và kiểm tra ss -ixem điều này có được tôn trọng không:

ss -i
State       Recv-Q Send-Q                                               Local Address:Port                                                   Peer Address:Port   
ESTAB       0      0                                                        10.0.2.15:ssh                                                        10.0.2.2:50714   
     cubic rto:201 rtt:1.5/0.75 ato:40 cwnd:10 send 77.9Mbps rcv_space:14600
ESTAB       0      0                                                        10.0.2.15:39042                                                 216.58.216.14:http    
     cubic rto:15 rtt:5/2.5 cwnd:10 send 23.4Mbps rcv_space:14600

Sự thành công! Rto trên kết nối HTTP (sau khi thay đổi) là 15ms, trong khi kết nối SSH (trước khi thay đổi) là hơn 200 như trước.

Tôi thực sự thích cách tiếp cận này - nó cho phép bạn đặt giá trị thấp hơn trên các tuyến thích hợp hơn là trên toàn cầu nơi nó có thể làm hỏng lưu lượng khác. Tương tự (xem trang ip man ), bạn có thể điều chỉnh ước tính rtt ban đầu và rttvar ban đầu cho tuyến đường (được sử dụng khi tính toán RTO động). Mặc dù nó không phải là một giải pháp hoàn chỉnh về mặt tinh chỉnh, tôi nghĩ rằng hầu hết các phần quan trọng đều ở đó. Bạn không thể điều chỉnh cài đặt tối đa, nhưng tôi nghĩ rằng điều đó sẽ không hữu ích trong mọi trường hợp.


Cảm ơn @Adam C đã làm rõ, nhưng bạn đã đề cập đến min (200 milli) và max (120 giây), tôi có thể thay đổi bất kỳ trong số này (tối thiểu hoặc tối đa) không? nếu có, làm thế nào? ...
obiigbe91

Tôi tin rằng chúng là hằng số trong mã và tôi không biết cách nào để thiết lập chúng một cách linh hoạt nhưng sẽ đào một chút và xem vì tôi giả sử thay đổi mã và biên dịch kernel của bạn là hơi nhiều :)
Adam C

Tìm hiểu làm thế nào để điều chỉnh rto_min và thêm nó và một vài điều liên quan khác trong câu trả lời :)
Adam C

Tại sao không có gì như thế rto_max? Làm thế nào để chúng ta thiết lập thời gian chờ tối đa toàn cầu?
est

Nếu bạn đặt mức tối thiểu (hoặc chấp nhận mặc định) và sau đó thay đổi số lần thử lại ( net.ipv4.tcp_retries1net.ipv4.tcp_retries2hoặc IIRC tương tự) được phép, tôi nghĩ bạn có thể đạt mức tương đương với mức tối đa RTO.
Adam C
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.