歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux基礎 >> Linux技術 >> Linux 內核優化

Linux 內核優化

日期:2017/3/3 12:56:47   编辑:Linux技術

TCP 相關部份常用名詞說明:

retries(再試)、TCP 服務器 <---> 客戶端通信狀態

SYN----------------> <--------------SYN,ACK

ACK---------------> 建立連接 Data1---------------->

<---------------Data1,ACK Data2---------------->

<---------------未回復 Data2---------------->重傳 [ 序列參數 tcp_sack, tcp_fack ]

[ 重傳次數參數: tcp_retries1,tcp_retries2, tcp_orphan_retries ] 數據傳輸

FIN------------------> <-----------------FIN,ACK(有時候FIN,ACK分兩次)

ACK-----------------> 斷開連接.主動關閉 FIN------------------>

<-----------------CLOSE_WAITSYN表示建立連接, RTT(Round-Trip Time): 往返時延

FIN表示關閉連接, RTO(Retransmission TimeOut)即重傳超時時間ACK表示響應,

PSH表示有 DATA數據傳輸,RST表示連接重置

TCP 抓包常見錯誤tcp out-of-order(tcp有問題) #多數是網絡擁塞引起的

tcp segment of a reassembled PDU #TCP 分片標識Tcp previous segment lost(tcp先前的分片丟失)

Tcp acked lost segment(tcp應答丟失)Tcp window update(tcp窗口更新)

Tcp dup ack(tcp重復應答)Tcp keep alive(tcp保持活動)

Tcp retransmission(tcp 重傳)

內核參數解釋net.ipv4.tcp_timestamps = 1

說明:

該參數控制RFC 1323 時間戳與窗口縮放選項。默認情況下,啟用時間戳與

窗口縮放,但是可以使用標志位進行控制。0位控制窗口縮放,1 位控制時間戳。

值為0(禁用 RFC 1323選項)

值為1(僅啟用窗口縮放)

值為2(僅啟用時間戳)

值為3(兩個選項均啟用)

net.ipv4.tcp_timestamps=0

說明:

時間戳可以避免序列號的卷繞。一個1Gbps的鏈路肯定會遇到以前用過的序列號。時間戳能夠讓內核接受這種“異常”的數據包。這裡需要將其關掉。

值為0(禁用時間戳)

值為1(啟用時間戳)

只有客戶端和服務端都開啟時間戳的情況下,才會出現能ping通不能建立tcp三次握手的情況,所以做為提供服務的公司,不可能保證所有的用戶都關閉時間戳,這個功能,所以我們必須關閉時間戳,這樣才能給所用用戶提供正常的服務。

net.ipv4.tcp_window_scaling = 1

net.ipv4.tcp_sack = 1使用 Selective ACK﹐它可以用來查找特定的遺失的數據報— 因此有助於快速恢復狀態。該文件表示是否啟用有選擇的應答(Selective Acknowledgment),這可以通過有選擇地應答亂序接收到的報文來提高性能(這樣可以讓發送者只發送丟失的報文段)。(對於廣域網通信來說這個選項應該啟用,但是這會增加對 CPU 的占用。)

net.ipv4.tcp_fack = 1打開FACK(Forward ACK) 擁塞避免快速重傳功能。(注意,當tcp_sack設置為0的時候,這個值即使設置為1也無效)

net.ipv4.tcp_retrans_collapse = 1

net.ipv4.tcp_syn_retries = 5對於一個新建連接,內核要發送多少個 SYN 連接請求才決定放棄。不應該大於255,默認值是5,對應於180秒左右時間。(對於大負載而物理通信良好的網絡而言,這個值偏高,可修改為2.這個值僅僅是針對對外的連接,對進來的連接,是由tcp_retries1 決定的)

net.ipv4.tcp_synack_retries = 5tcp_synack_retries顯示或設定 Linux 核心在回應 SYN 要求時會嘗試多少次重新發送初始 SYN,ACK 封包後才決定放棄。這是所謂的三段交握 (threeway handshake) 的第二個步驟。即是說系統會嘗試多少次去建立由遠端啟始的 TCP 連線。tcp_synack_retries 的值必須為正整數,並不能超過 255。因為每一次重新發送封包都會耗費約 30 至 40 秒去等待才決定嘗試下一次重新發送或決定放棄。tcp_synack_retries 的缺省值為 5,即每一個連線要在約

180 秒 (3 分鐘) 後才確定逾時.

net.ipv4.tcp_max_orphans = 131072系統所能處理不屬於任何進程的TCP sockets最大數量。假如超過這個數量,那麼不屬於任何進程的連接會被立即reset,並同時顯示警告信息。之所以要設定這個限制﹐純粹為了抵御那些簡單的 DoS 攻擊﹐千萬不要依賴這個或是人為的降低這個限制,更應該增加這個值(如果增加了內存之後)。每個孤兒套接字最多能夠吃掉你64K不可交換的內存。

net.ipv4.tcp_max_tw_buckets = 5000表示系統同時保持TIME_WAIT套接字的最大數量,如果超過這個數字,TIME_WAIT套接字將立刻被清除並打印警告信息。默認為180000。設為較小數值此項參數可以控制TIME_WAIT套接字的最大數量,避免服務器被大量的TIME_WAIT套接字拖死。

net.ipv4.tcp_keepalive_time = 7200net.ipv4.tcp_keepalive_probes = 9

net.ipv4.tcp_keepalive_intvl = 75 用實例進行說明上述三個參數:

如果某個TCP連接在idle 2個小時後,內核才發起probe(探查).如果probe 9次(每次75秒既tcp_keepalive_intvl值)不成功,內核才徹底放棄,認為該連接已失效。

net.ipv4.tcp_retries1 = 3放棄回應一個TCP 連接請求前﹐需要進行多少次重試。RFC 規定最低的數值是3﹐這也是默認值﹐根據RTO的值大約在3秒 - 8分鐘之間。(注意:這個值同時還決定進入的syn連接)

(第二種解釋:它表示的是TCP傳輸失敗時不檢測路由表的最大的重試次數,當超過了這個值,我們就需要檢測路由表了)net.ipv4.tcp_retries2 = 15

在丟棄激活(已建立通訊狀況)的TCP連接之前﹐需要進行多少次重試。默認值為15,根據RTO的值來決定,相當於13-30分鐘(RFC1122規定,必須大於100秒).(這個值根據目前的網絡設置,可以適當地改小,我的網絡內修改為了5)(第二種解釋:表示重試最大次數,只不過這個值一般要比上面的值大。和上面那個不同的是,當重試次數超過這個值,我們就必須放棄重試了)

net.ipv4.tcp_orphan_retries主要是針對孤立的socket(也就是已經從進程上下文中刪除了,可是還有一些清理工作沒有完成).對於這種socket,我們重試的最大的次數就是它

net.ipv4.tcp_fin_timeout = 30表示如果套接字由本端要求關閉,這個參數決定了它保持在 FIN-WAIT-2狀態的時間

net.ipv4.tcp_tw_recycle = 1表示開啟TCP連接中TIME-WAITsockets的快速回收,默認為0,表示關閉

net.ipv4.tcp_stdurg = 0

net.ipv4.tcp_rfc1337 = 0

net.ipv4.tcp_max_syn_backlog = 8192表示SYN隊列的長度,默認為1024,加大隊列長度為8192,可以容納更多等待連接的網絡連接數。

(第二種解釋:端口最大backlog 內核限制。此參數限制服務端應用程序 可以設置的端口最大backlog 值 (對應於端口的 syn_backlog 和 backlog 隊列長度)。動機是在內存有限的服務器上限制/避免應用程序配置超大 backlog 值而耗盡內核內存。如果應用程序設置 backlog 大於此值,操作系統將自動將之限制到此值。)

net.ipv4.tcp_abort_on_overflow = 0當 tcp 建立連接的 3 路握手完成後,將連接置入ESTABLISHED 狀態並交付給應用程序的 backlog 隊列時,會檢查 backlog 隊列是否已滿。若已滿,通常行為是將連接還原至 SYN_ACK狀態,以造成 3 路握手最後的 ACK 包意外丟失假象 —— 這樣在客戶端等待超時後可重發 ACK —— 以再次嘗試進入ESTABLISHED 狀態 —— 作為一種修復/重試機制。如果啟用tcp_abort_on_overflow 則在檢查到 backlog 隊列已滿時,直接發 RST

包給客戶端終止此連接 —— 此時客戶端程序會收到 104Connection reset by peer 錯誤。

警告:啟用此選項可能導致高峰期用戶訪問體驗到 104:Connection reset by peer 或白屏錯誤(視浏覽器而定)。在考慮啟用此選項前應先設法優化提高服務端應用程序的性能,使之能更快接管、處理連接。

net.ipv4.tcp_syncookies = 1在 tcp 建立連接的 3 路握手過程中,當服務端收到最初的 SYN 請求時,會檢查應用程序的 syn_backlog 隊列是否已滿。若已滿,通常行為是丟棄此 SYN 包。若未滿,會再檢查應用程序的 backlog 隊列是否已滿。若已滿並且系統根據歷史記錄判斷該應用程序不會較快消耗連接時,則丟棄此 SYN 包。如果啟用 tcp_syncookies 則在檢查到 syn_backlog 隊列已滿時,不丟棄該 SYN 包,而改用 syncookie 技術進行 3 路握手。

警告:使用 syncookie 進行握手時,因為該技術挪用了 tcp_options 字段空間,會強制關閉 tcp 高級流控技術而退化成原始 tcp 模式。此模式會導致封包 丟失時 對端 要等待 MSL 時間來發現丟包事件並重試,以及關閉連接時 TIME_WAIT 狀態保持 2MSL 時間。該技術應該僅用於保護syn_flood 攻擊。如果在正常服務器環境中服務器負載較重導致 syn_backlog 和 backlog 隊列滿時,應優化服務端應用程序的負載能力,加大應用程序backlog 值。不過,所幸該參數是自動值,僅在 syn_backlog 隊列滿時才會觸發 (在隊列恢復可用時此行為關閉)。

Ø 服務端應用程序設置端口backlog 值,內核理論上將允許該端口最大同時接收 2*backlog 個並發連接”請求”(不含已被應用程序接管的連接) ——分別存放在 syn_backlog 和 backlog 隊列—— 每個隊列的長度為backlog 值。syn_backlog 隊列存儲 SYN_ACK 狀態的連接,backlog 則存儲 ESTABLISHED 狀態但尚未被應用程序接管的連接。

Ø syn_backlog 隊列實際上是個 hash 表,並且 hash 表大小為 2 的次方。所以實際 syn_backlog 的隊列長度要略大於應用程序設置的 backlog 值—— 取對應 2 的次方值。

Ø 當 backlog 值較小,而高峰期並發連接請求超高時,tcp 建立連接的三路握手 網絡時延將成為瓶頸 —— 並發連接超高時,syn_backlog 隊列將被充滿而導致 `can’t connect` 錯誤。此時,再提高服務端應用程序的吞吐能力已不起作用,因為連接尚未建立,服務端應用程序並不能接管和處理這些連接—— 而是需要加大backlog 值 (syn_backlog 隊列長度) 來緩解此問題。Ø 啟用 syncookie 雖然也可以解決超高並發時的` can’t connect` 問題,但會導致 TIME_WAIT 狀態 fallback 為保持 2MSL 時間,高峰期時會導致客戶端無可復用連接而無法連接服務器 (tcp 連接復用是基於 <src_ip, src_port, dst_ip, dst_port> 四元組值必須不相同,就訪問同一個目標服務器而言,<src_ip, dst_ip, dst_port> 三元組值不變,所以此時可用的連接數限制為僅src_port

所允許數目,這裡處於 TIME_WAIT 狀態的相同 src_port 連接不可復用。Linux 系統甚至更嚴格,只使用了 <src_ip, src_port, dst_ip> 三元組…)。故不建議依賴syncookie。

net.ipv4.tcp_orphan_retries = 0本端試圖關閉TCP連接之前重試多少次。缺省值是7,相當於50秒~16分鐘(取決於RTO)。如果你的機器是一個重載的WEB服務器,你應該考慮減低這個值,因為這樣的套接字會消耗很多重要的資源。參見tcp_max_orphans

net.ipv4.tcp_sack = 1SACK(SelectiveAcknowledgment,選擇性確認)技術,使TCP只重新發送交互過程中丟失的包,不用發送後續所有的包,而且提供相應機制使接收方能告訴發送方哪些數據丟失,哪些數據重發了,哪些數據已經提前收到了。如此大大提高了客戶端與服務器端數據交互的效率。

net.ipv4.tcp_reordering = 3

net.ipv4.tcp_ecn = 2

net.ipv4.tcp_dsack = 1允許TCP發送”兩個完全相同”的SACK。

net.ipv4.tcp_mem = 178368 237824 356736同樣有3個值,意思是:

net.ipv4.tcp_mem[0]: 低於此值,TCP沒有內存壓力.

net.ipv4.tcp_mem[1]: 在此值下,進入內存壓力階段.

net.ipv4.tcp_mem[2]: 高於此值,TCP拒絕分配socket.

net.ipv4.tcp_wmem = 4096 16384 4194304TCP寫buffer,可參考的優化值: 8192436600 873200

net.ipv4.tcp_rmem = 4096 87380 4194304TCP讀buffer,可參考的優化值:32768 436600 873200

net.ipv4.tcp_app_win = 31

net.ipv4.tcp_adv_win_scale = 2

net.ipv4.tcp_tw_reuse = 1表示開啟重用。允許將TIME-WAITsockets重新用於新的TCP連接,默認為0,表示關閉;

net.ipv4.tcp_frto = 2開啟F-RTO,一個針對TCP重傳超時(RTOs)的增強的恢復算法。在無線環境下特別有益處,因為在這種環境下分組丟失典型地是因為隨機無線電干擾而不是中間路由器組塞。參考RFC 4318了解更多的細節。

這個文件擁有下列值之一:

Ø 0 禁用。

Ø 1 開啟基本版本的F-RTO算法。

Ø 2 如果流使用SACK的話,開啟SACK-增強的F-TRO算法。不過當使用SACK時是基本版本也是可以使用的,因為有這種場景存在,F-RTO和開啟SACK的TCP流分組計數合作不好。

net.ipv4.tcp_frto_response = 0當F-RTO偵測到TCP超時是偽的時(例如,通過設置了更長的超時值避免了超時),TCP有幾個選項決定接下來如何去做。可能的值是:

Ø 1 基於速率減半;平滑保守的響應,導致一個RTT之後擁塞窗口(cwnd)和慢啟動閥值(ssthresh)減半。

Ø 2非常保守的響應;不推薦這樣做,因為即時有效,它和TCP的其他部分交互不好;立即減半擁塞窗口(cwnd)和慢啟動閥值(ssthresh)。

Ø 3侵占性的響應;廢棄現在已知不必要的擁塞控制措施(或略一個將引起TCP更加謹慎保守的丟失的重傳);cwnd and ssthresh恢復到超時之前的值。

net.ipv4.tcp_slow_start_after_idle = 1表示擁塞窗口在經過一段空閒時間後仍然有效而不必重新初始化。

net.ipv4.tcp_low_latency = 0允許 TCP/IP 協議棧適應在高吞吐量情況下低延時的情況;這個選項應該禁用。

net.ipv4.tcp_no_metrics_save = 0一個tcp連接關閉後,把這個連接曾經有的參數比如慢啟動門限snd_sthresh,擁塞窗口snd_cwnd 還有srtt等信息保存到dst_entry中, 只要dst_entry 沒有失效,下次新建立相同連接的時候就可以使用保存的參數來初始化這個連接.tcp_no_metrics_save 設置為1就是不保持這些參數(經驗值),每次建立連接後都重新摸索一次. 我覺得沒什麼好處. 所以系統默認把它設為0。

net.ipv4.tcp_moderate_rcvbuf = 1打開了TCP內存自動調整功能(1為打開、0為禁止)

net.ipv4.tcp_tso_win_divisor = 3

單個TSO段可消耗擁塞窗口的比例,默認值為3。

net.ipv4.tcp_congestion_control = cubicnet.ipv4.tcp_available_congestion_control = cubic reno

net.ipv4.tcp_allowed_congestion_control = cubic reno丟包使得TCP傳輸速度大幅下降的主要原因是丟包重傳機制,控制這一機制的就是TCP擁塞控制算法。 congestion(擁塞)

Linux內核中提供了若干套TCP擁塞控制算法,已加載進內核的可以通過內核參數net.ipv4.tcp_available_congestion_control看到:

沒有加載進內核的一般是編譯成了模塊,可以用modprobe加載,這些算法各自適用於不同的環境。

Ø reno是最基本的擁塞控制算法,也是TCP協議的實驗原型。Ø bic適用於rtt較高但丟包極為罕見的情況,比如北美和歐洲之間的線路,這是2.6.8到2.6.18之間的Linux內核的默認算法。

Ø cubic是修改版的bic,適用環境比bic廣泛一點,它是2.6.19之後的linux內核的默認算法。Ø hybla適用於高延時、高丟包率的網絡,比如衛星鏈路。

載入tcp_hybl模塊 modprobe tcp_hyblaTCP擁塞控制 算法對TCP傳輸速率的影響可很大。

net.ipv4.tcp_abc = 0

net.ipv4.tcp_mtu_probing = 0

net.ipv4.tcp_fastopenGoogleTFO特性,kernel 3.6以上版本支持,具體實現方法參考本文檔 Google TFO特性。

net.ipv4.tcp_base_mss= 512分組層路徑MTU發現(MTU探測)中使用的search_low的初始值。如果允許MTU探測,這個初始值就是連接使用的初始MSS值。

net.ipv4.route.min_adv_mss= 256該文件表示最小的MSS(MaximumSegment Size)大小,取決於第一跳的路由器MTU。

net.ipv4.tcp_workaround_signed_windows = 0

net.ipv4.tcp_dma_copybreak= 4096下限.以字節為單位.socket 的大小將卸載到一個 dma 復制引擎.如果存在一個在系統和內核配置為使用 config_net_dma 選項。

net.ipv4.tcp_max_ssthresh= 0慢啟動階段,就是當前擁塞窗口值比慢啟動阈值(snd_ssthresh)小的時候,所處的階段就叫做慢啟動階段。

當我們收到一個新的ACK時,則會調用tcp_slow_start()這個函數,並且為擁塞窗口增加1.(Linux中擁塞窗口的值代表數據包的個數,而不是實際的發送

字節數目。實際可以發送的字節數等於可以發送的數據包個數*MSS。)

直到慢啟動階段出現數據包的丟失。

而引入了tcp_max_ssthresh 這個參數後,則可以控制在慢啟動階段擁塞窗口增加的頻度。

默認這個參數不打開,如果這個參數的值設置為1000,則當擁塞窗口值大於1000時,

則沒收到一個ACK,並不再增加擁塞窗口一個單位了,而是約收到2個ACK才增加一個窗口單位。收到2ACK並不是決定值!!

需要根據當前的擁塞窗口值,tcp_max_ssthresh值進行判斷。

net.ipv4.tcp_thin_linear_timeouts= 0這個函數RTO超時的處理函數。如果是thin流,則不要新設RTO是原先的2倍。

net.ipv4.tcp_thin_dupack= 0與tcp_thin_linear_timeouts同為快速重傳算法參數

net.core.netdev_max_backlog=300進入包的最大設備隊列.默認是300,對重負載服務器而言,該值太低,可調整到1000。

ip link set eth0mtu 1500設置網卡mtu大小。

IP 相關部份net.ipv4.ip_local_port_range = 1024 65000

表示用於向外連接的端口范圍。缺省情況下很小:32768到61000,改為1024到65000。

net.ipv4.ip_conntrack_max = 655360在內核內存中netfilter可以同時處理的“任務”(連接跟蹤條目)another

# 避免放大攻擊

net.ipv4.icmp_echo_ignore_broadcasts = 1# 開啟惡意icmp錯誤消息保護

net.ipv4.icmp_ignore_bogus_error_responses = 1# 開啟SYN洪水攻擊保護

net.ipv4.tcp_syncookies = 1# 開啟並記錄欺騙,源路由和重定向包

net.ipv4.conf.all.log_martians = 1net.ipv4.conf.default.log_martians = 1

# 處理無源路由的包

net.ipv4.conf.all.accept_source_route = 0net.ipv4.conf.default.accept_source_route = 0

# 開啟反向路徑過濾

net.ipv4.conf.all.rp_filter = 1net.ipv4.conf.default.rp_filter = 1

# 確保無人能修改路由表

net.ipv4.conf.all.accept_redirects = 0net.ipv4.conf.default.accept_redirects = 0

net.ipv4.conf.all.secure_redirects = 0net.ipv4.conf.default.secure_redirects = 0

# 不充當路由器

net.ipv4.ip_forward = 0net.ipv4.conf.all.send_redirects = 0

net.ipv4.conf.default.send_redirects = 0# 開啟execshild

kernel.exec-shield = 1kernel.randomize_va_space = 1

網絡相關部份(/sys)sys/class/net/eth0/statistics.rx_packets:

收到的數據包數據

sys/class/net/eth0/statistics.tx_packets: 傳輸的數據包數量

sys/class/net/eth0/statistics.rx_bytes: 接收的字節數

sys/class/net/eth0/statistics.tx_bytes: 傳輸的字節數

sys/class/net/eth0/statistics.rx_dropped:收包時丟棄的數據包

sys/class/net/eth0/statistics.tx_dropped: 發包時丟棄的數據包

Copyright © Linux教程網 All Rights Reserved