成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Linux內核性能調優:讓系統飛起來的秘籍

系統 Linux
Linux 內核性能調優絕非小事,它直接關系到系統的穩定性、可靠性以及業務的正常運轉。通過對內核參數進行合理調整、優化系統資源分配、采用高效的調度算法等手段,可以顯著提升 Linux 內核的性能,讓系統在面對各種復雜工作負載時都能游刃有余。

在當今數字化時代,Linux 系統憑借其強大的穩定性、開放性和靈活性,廣泛應用于服務器、云計算、大數據等諸多領域。然而,隨著業務量的不斷增長和應用場景的日益復雜,Linux 內核的性能面臨著巨大挑戰。哪怕是微小的性能瓶頸,都可能像滾雪球一樣,在高負載運行時被無限放大,進而引發一系列嚴重問題。

想象一下,一個電商網站在購物高峰期,由于 Linux 內核性能不佳,導致服務器響應遲緩。用戶點擊商品詳情,頁面卻遲遲無法加載;提交訂單后,長時間得不到反饋。這不僅會讓用戶體驗大打折扣,還可能導致大量潛在客戶流失,給企業帶來不可估量的經濟損失。再比如,一個實時數據分析系統,因為內核性能問題,無法及時處理海量數據,使得分析結果嚴重滯后,企業決策層基于這些滯后數據做出的決策,很可能與市場實際情況脫節,進而影響企業的戰略布局和發展方向。

由此可見,Linux 內核性能調優絕非小事,它直接關系到系統的穩定性、可靠性以及業務的正常運轉。通過對內核參數進行合理調整、優化系統資源分配、采用高效的調度算法等手段,可以顯著提升 Linux 內核的性能,讓系統在面對各種復雜工作負載時都能游刃有余。接下來,就讓我們一同深入探索 Linux 內核性能調優的精彩世界。

一、系統性能指標大揭秘

在深入探討 Linux 內核性能調優方法之前,我們首先要明確衡量系統性能的關鍵指標。就如同評價一輛汽車的性能,我們會關注它的速度、油耗、操控性等指標一樣,對于 Linux 系統,吞吐量、系統延遲、CPU 使用率、內存使用率和磁盤 I/O 等指標,能幫助我們全面了解系統的運行狀態。

1.1吞吐量:數據處理的速度擔當

吞吐量,是指在單位時間內系統成功處理的數據量或請求數 ,它直觀地反映了系統的數據處理能力。以一個電商網站為例,假設在促銷活動期間,該網站每秒能夠處理 1000 個商品查詢請求和 200 個訂單提交請求,這些請求處理的數量就是網站系統的吞吐量體現。如果網站的吞吐量較低,在高并發的情況下,大量請求就會堆積,導致系統響應緩慢甚至崩潰。就像一條狹窄的公路,車流量稍大就會造成交通堵塞。提高系統吞吐量,能夠讓系統在單位時間內處理更多的任務,滿足業務增長的需求。

1.2系統延遲:影響用戶體驗的關鍵

系統延遲,指的是從請求發出到收到響應所經歷的時間。還是以電商網站為例,當用戶點擊商品詳情頁時,頁面如果能在 1 秒內加載完成,用戶幾乎察覺不到延遲,體驗流暢;但如果加載時間長達 5 秒甚至更久,用戶就會感到不耐煩,可能會離開網站。低延遲對于提升用戶體驗至關重要,尤其在對實時性要求極高的場景,如在線游戲、金融交易等。在在線游戲中,玩家的每一個操作都需要及時反饋到游戲畫面中,如果系統延遲過高,玩家發出的攻擊指令可能要數秒后才會生效,這會嚴重影響游戲的公平性和趣味性。

一般來說,一個系統的性能受到這兩個條件的約束,缺一不可。比如,我的系統可以頂得住一百萬的并發,但是系統的延遲是2分鐘以上,那么,這個一百萬的負載毫無意義。系統延遲很短,但是吞吐量很低,同樣沒有意義。所以,一個好的系統的性能測試必然受到這兩個條件的同時作用。

有經驗的朋友一定知道,這兩個東西的一些關系:

  • Throughput越大,Latency會越差。因為請求量過大,系統太繁忙,所以響應速度自然會低。
  • Latency越好,能支持的Throughput就會越高。因為Latency短說明處理速度快,于是就可以處理更多的請求。

二、定位性能瓶頸的實用方法

2.1系統性能測試

經過上述的說明,我們知道要測試系統的性能,需要我們收集系統的Throughput和Latency這兩個值。

  • 首先,需要定義Latency這個值,比如說,對于網站系統響應時間必需是5秒以內(對于某些實時系統可能需要定義的更短,比如5ms以內,這個更根據不同的業務來定義)
  • 其次,開發性能測試工具,一個工具用來制造高強度的Throughput,另一個工具用來測量Latency。對于第一個工具,你可以參考一下“十個免費的Web壓力測試工具”,關于如何測量Latency,你可以在代碼中測量,但是這樣會影響程序的執行,而且只能測試到程序內部的Latency,真正的Latency是整個系統都算上,包括操作系統和網絡的延時,你可以使用Wireshark來抓網絡包來測量。這兩個工具具體怎么做,這個還請大家自己思考去了。
  • 最后,開始性能測試。你需要不斷地提升測試的Throughput,然后觀察系統的負載情況,如果系統頂得住,那就觀察Latency的值。這樣,你就可以找到系統的最大負載,并且你可以知道系統的響應延時是多少。

再多說一些,

  • 關于Latency,如果吞吐量很少,這個值估計會非常穩定,當吞吐量越來越大時,系統的Latency會出現非常劇烈的抖動,所以,我們在測量Latency的時候,我們需要注意到Latency的分布,也就是說,有百分之幾的在我們允許的范圍,有百分之幾的超出了,有百分之幾的完全不可接受。也許,平均下來的Latency達標了,但是其中僅有50%的達到了我們可接受的范圍。那也沒有意義。
  • 關于性能測試,我們還需要定義一個時間段。比如:在某個吞吐量上持續15分鐘。因為當負載到達的時候,系統會變得不穩定,當過了一兩分鐘后,系統才會穩定。另外,也有可能是,你的系統在這個負載下前幾分鐘還表現正常,然后就不穩定了,甚至垮了。所以,需要這么一段時間。這個值,我們叫做峰值極限。
  • 性能測試還需要做Soak Test,也就是在某個吞吐量下,系統可以持續跑一周甚至更長。這個值,我們叫做系統的正常運行的負載極限。

性能測試有很多很復要的東西,比如:burst test等。這里不能一一詳述,這里只說了一些和性能調優相關的東西。總之,性能測試是一細活和累活。

有了上面的鋪墊,我們就可以測試到到系統的性能了,再調優之前,我們先來說說如何找到性能的瓶頸。我見過很多朋友會覺得這很容易,但是仔細一問,其實他們并沒有一個比較系統的方法。

2.2查看操作系統負載

在排查 Linux 內核性能問題時,查看操作系統負載是關鍵的第一步。通過這一操作,我們能夠了解系統當前的工作壓力,進而找出可能存在的性能瓶頸。

利用 top 命令,我們可以實時查看系統的整體運行狀態。在命令行中輸入 “top”,隨即會出現一個動態更新的界面,展示諸多重要信息。最上方的一行詳細呈現了 CPU 的使用情況,其中包括用戶空間進程使用的 CPU 時間百分比(us)、內核空間進程使用的 CPU 時間百分比(sy)、被調整優先級的用戶進程使用的 CPU 時間(ni)、空閑的 CPU 時間百分比(id)、等待 I/O 操作完成的 CPU 時間百分比(wa)、硬件中斷使用的 CPU 時間百分比(hi)、軟件中斷使用的 CPU 時間百分比(si)以及虛擬機管理程序等待其他虛擬 CPU 運行的時間百分比(st)。舉例來說,如果發現 us 值較高,那就意味著用戶空間的進程消耗了大量 CPU 資源,此時我們就需要深入檢查這些進程,判斷是否存在異常或低效的代碼。

而 htop 命令則提供了更為直觀和豐富的信息展示。它以可視化的方式呈現 CPU 的使用情況,不同顏色的條形圖分別代表不同類型的 CPU 負載,如綠色表示用戶進程使用的 CPU,紅色表示內核進程使用的 CPU 等。同時,它還能清晰地顯示每個進程的詳細信息,包括進程 ID、用戶、優先級、內存使用量等。當我們懷疑某個進程對系統性能產生較大影響時,使用 htop 能夠更方便地定位和分析該進程。

SystemTap 是一款強大的動態內核和用戶空間追蹤工具。它允許我們編寫腳本,對系統運行時的各種事件進行捕獲和分析。假設我們想要了解某個特定進程在執行過程中對系統資源的占用情況,就可以編寫一個 SystemTap 腳本,專門針對該進程進行監控。通過腳本,我們能夠獲取該進程的 CPU 利用率、內存訪問頻率等詳細信息,從而精準定位問題所在。

LatencyTOP 則專注于檢測系統中的延遲問題。在運行 LatencyTOP 后,它會分析系統中各個進程的延遲情況,并將延遲較高的進程凸顯出來。例如,若 LatencyTOP 報告某個驅動程序進程的延遲過高,這可能表明該驅動程序存在性能缺陷,需要進一步優化或更新。

首先,當我們系統有問題的時候,我們不要急于去調查我們代碼,這個毫無意義。我們首要需要看的是操作系統的報告。看看操作系統的CPU利用率,看看內存使用率,看看操作系統的IO,還有網絡的IO,網絡鏈接數,等等。Windows下的perfmon是一個很不錯的工具,Linux下也有很多相關的命令和工具,比如:SystemTap,LatencyTOP,vmstat, sar, iostat, top, tcpdump等等 。通過觀察這些數據,我們就可以知道我們的軟件的性能基本上出在哪里。比如:

  • 先看CPU利用率,如果CPU利用率不高,但是系統的Throughput和Latency上不去了,這說明我們的程序并沒有忙于計算,而是忙于別的一些事,比如IO。(另外,CPU的利用率還要看內核態的和用戶態的,內核態的一上去了,整個系統的性能就下來了。而對于多核CPU來說,CPU 0 是相當關鍵的,如果CPU 0的負載高,那么會影響其它核的性能,因為CPU各核間是需要有調度的,這靠CPU0完成)
  • 然后,我們可以看一下IO大不大,IO和CPU一般是反著來的,CPU利用率高則IO不大,IO大則CPU就小。關于IO,我們要看三個事,一個是磁盤文件IO,一個是驅動程序的IO(如:網卡),一個是內存換頁率。這三個事都會影響系統性能。
  • 然后,查看一下網絡帶寬使用情況,在Linux下,你可以使用iftop, iptraf, ntop, tcpdump這些命令來查看。或是用Wireshark來查看。
  • 如果CPU不高,IO不高,內存使用不高,網絡帶寬使用不高。但是系統的性能上不去。這說明你的程序有問題,比如,你的程序被阻塞了。可能是因為等那個鎖,可能是因為等某個資源,或者是在切換上下文。

通過了解操作系統的性能,我們才知道性能的問題,比如:帶寬不夠,內存不夠,TCP緩沖區不夠,等等,很多時候,不需要調整程序的,只需要調整一下硬件或操作系統的配置就可以了

2.3使用Profiler測試

接下來,我們需要使用性能檢測工具,也就是使用某個Profiler來差看一下我們程序的運行性能。如:Java的JProfiler/TPTP/CodePro Profiler,GNU的gprof,IBM的PurifyPlus,Intel的VTune,AMD的CodeAnalyst,還有Linux下的OProfile/perf,后面兩個可以讓你對你的代碼優化到CPU的微指令級別,如果你關心CPU的L1/L2的緩存調優,那么你需要考慮一下使用VTune。使用這些Profiler工具,可以讓你程序中各個模塊函數甚至指令的很多東西,如:運行的時間 ,調用的次數CPU的利用率,等等。這些東西對我們來說非常有用。

我們重點觀察運行時間最多,調用次數最多的那些函數和指令。這里注意一下,對于調用次數多但是時間很短的函數,你可能只需要輕微優化一下,你的性能就上去了(比如:某函數一秒種被調用100萬次,你想想如果你讓這個函數提高0.01毫秒的時間 ,這會給你帶來多大的性能)

使用Profiler有個問題我們需要注意一下,因為Profiler會讓你的程序運行的性能變低,像PurifyPlus這樣的工具會在你的代碼中插入很多代碼,會導致你的程序運行效率變低,從而沒發測試出在高吞吐量下的系統的性能,對此,一般有兩個方法來定位系統瓶頸:

  • 在你的代碼中自己做統計,使用微秒級的計時器和函數調用計算器,每隔10秒把統計log到文件中。
  • 分段注釋你的代碼塊,讓一些函數空轉,做Hard Code的Mock,然后再測試一下系統的Throughput和Latency是否有質的變化,如果有,那么被注釋的函數就是性能瓶頸,再在這個函數體內注釋代碼,直到找到最耗性能的語句。

最后再說一點,對于性能測試,不同的Throughput會出現不同的測試結果,不同的測試數據也會有不同的測試結果。所以,用于性能測試的數據非常重要,性能測試中,我們需要觀測試不同Throughput的結果。

2.4剖析 IO 情況

IO 操作在系統性能中扮演著舉足輕重的角色,對其進行深入剖析,能幫助我們發現許多潛在的性能問題。

在磁盤文件 IO 方面,iostat 命令是我們的得力助手。通過執行 “iostat -d -x 1”(其中 “-d” 表示僅顯示磁盤相關信息,“-x” 表示顯示更詳細的信息,“1” 表示每隔 1 秒輸出一次數據),我們可以獲取到每個磁盤設備的詳細統計信息。其中,“r/s” 代表每秒完成的讀次數,“w/s” 代表每秒完成的寫次數,“rkB/s” 表示每秒讀數據量,“wkB/s” 表示每秒寫數據量,“% util” 則表示設備的繁忙程度。當 “% util” 接近 100% 時,說明磁盤 I/O 系統已經滿負荷運轉,很可能成為系統性能的瓶頸。比如,在一個數據存儲服務器中,如果發現某個磁盤的 “% util” 長期保持在 95% 以上,那么就需要考慮對該磁盤進行優化,如更換為更高性能的磁盤,或者對數據存儲方式進行調整。

iotop 命令能夠讓我們清晰地看到哪些進程正在大量占用磁盤 I/O 資源。執行 “iotop” 后,會列出各個進程的 I/O 使用情況,包括讀速率、寫速率等。當我們發現某個進程的 I/O 讀寫速率異常高時,就需要進一步分析該進程的業務邏輯,看是否存在不合理的 I/O 操作。例如,某個備份進程在進行數據備份時,采用了頻繁的小文件讀寫方式,這可能會導致磁盤 I/O 性能下降,此時可以考慮優化備份策略,采用大文件讀寫或者批量操作的方式。

驅動程序 IO 對系統性能的影響也不容小覷。如果驅動程序存在問題,可能會導致設備與系統之間的數據傳輸效率低下。以網絡驅動程序為例,若驅動程序版本過舊,可能無法充分發揮網卡的性能,導致網絡傳輸速度受限。在這種情況下,及時更新驅動程序往往能顯著提升系統性能。

內存換頁率也是衡量系統性能的重要指標。vmstat 命令可以幫助我們查看內存換頁情況。在輸出結果中,“si” 表示從磁盤交換到內存的交換頁數量,“so” 表示從內存交換到磁盤的交換頁數量。如果 “si” 和 “so” 的值較大,說明系統頻繁進行內存換頁操作,這會嚴重影響系統性能。通常,這可能是由于內存不足導致的。比如,在一個運行多個大型應用程序的服務器上,如果發現內存換頁率過高,就需要考慮增加物理內存,或者對應用程序的內存使用進行優化。

2.5洞察網絡帶寬使用

在網絡環境中,了解網絡帶寬的使用情況對于定位性能瓶頸至關重要。

iftop 是一款出色的實時流量監控工具。通過執行 “iftop -i eth0”(其中 “-i” 指定要監測的網卡,“eth0” 是常見的網卡名稱),我們可以直觀地看到指定網卡的實時流量情況。在 iftop 的界面中,會清晰地顯示出各個 IP 地址之間的流量傳輸情況,包括發送流量(TX)、接收流量(RX)以及總流量(TOTAL)。同時,還能看到不同時間段的平均流量,如過去 2 秒、10 秒、40 秒的平均流量。這有助于我們快速發現哪些 IP 地址之間的流量過大,從而判斷是否存在網絡瓶頸。例如,在一個企業網絡中,如果發現某個 IP 地址與外部服務器之間的流量持續超過網絡帶寬的 80%,那么就需要進一步檢查該 IP 地址對應的業務,看是否存在數據傳輸異常的情況。

iptraf 同樣是一款功能強大的網絡流量監測工具。它不僅可以實時監測網絡接口的流量,還能提供詳細的網絡連接信息,如 TCP 連接、UDP 連接等。通過 “iptraf -g” 命令,我們可以進入圖形化界面,方便地查看各個網絡接口的流量統計信息。此外,iptraf 還支持按協議類型查看流量,這對于分析網絡中不同協議的使用情況非常有幫助。比如,在一個以 HTTP 協議為主的網絡環境中,如果發現 HTTP 流量占比過高,導致其他業務的網絡帶寬受到擠壓,那么就可以考慮對 HTTP 業務進行優化,如采用緩存技術、優化頁面加載方式等,以減少網絡帶寬的占用。

三、性能調優的方法

下面這些東西是我所經歷過的一些問題,也許并不全,也許并不對,大家可以補充指正,我純屬拋磚引玉。一般來說,性能優化也就是下面的幾個策略:

  • 用空間換時間。各種cache如CPU L1/L2/RAM到硬盤,都是用空間來換時間的策略。這樣策略基本上是把計算的過程一步一步的保存或緩存下來,這樣就不用每次用的時候都要再計算一遍,比如數據緩沖,CDN,等。這樣的策略還表現為冗余數據,比如數據鏡象,負載均衡什么的。
  • 用時間換空間。有時候,少量的空間可能性能會更好,比如網絡傳輸,如果有一些壓縮數據的算法(如前些天說的“Huffman 編碼壓縮算法” 和 “rsync 的核心算法”),這樣的算法其實很耗時,但是因為瓶頸在網絡傳輸,所以用時間來換空間反而能省時間。
  • 簡化代碼。最高效的程序就是不執行任何代碼的程序,所以,代碼越少性能就越高。關于代碼級優化的技術大學里的教科書有很多示例了。如:減少循環的層數,減少遞歸,在循環中少聲明變量,少做分配和釋放內存的操作,盡量把循環體內的表達式抽到循環外,條件表達的中的多個條件判斷的次序,盡量在程序啟動時把一些東西準備好,注意函數調用的開銷(棧上開銷),注意面向對象語言中臨時對象的開銷,小心使用異常(不要用異常來檢查一些可接受可忽略并經常發生的錯誤),…… 等等,等等,這連東西需要我們非常了解編程語言和常用的庫。
  • 并行處理。如果CPU只有一個核,你要玩多進程,多線程,對于計算密集型的軟件會反而更慢(因為操作系統調度和切換開銷很大),CPU的核多了才能真正體現出多進程多線程的優勢。并行處理需要我們的程序有Scalability,不能水平或垂直擴展的程序無法進行并行處理。

從架構上來說,這表再為——是否可以做到不改代碼只是加加機器就可以完成性能提升?

總之,根據2:8原則來說,20%的代碼耗了你80%的性能,找到那20%的代碼,你就可以優化那80%的性能。下面的一些東西都是我的一些經驗,我只例舉了一些最有價值的性能調優的的方法,供你參考,也歡迎補充。

3.1算法調優

算法非常重要,好的算法會有更好的性能。舉幾個我經歷過的項目的例子,大家可以感覺一下。

  • 一個是過濾算法,系統需要對收到的請求做過濾,我們把可以被filter in/out的東西配置在了一個文件中,原有的過濾算法是遍歷過濾配置,后來,我們找到了一種方法可以對這個過濾配置進行排序,這樣就可以用二分折半的方法來過濾,系統性能增加了50%。
  • 一個是哈希算法。計算哈希算法的函數并不高效,一方面是計算太費時,另一方面是碰撞太高,碰撞高了就跟單向鏈表一個性能(可參看Hash Collision DoS 問題)。我們知道,算法都是和需要處理的數據很有關系的,就算是被大家所嘲笑的“冒泡排序”在某些情況下(大多數數據是排好序的)其效率會高于所有的排序算法。哈希算法也一樣,廣為人知的哈希算法都是用英文字典做測試,但是我們的業務在數據有其特殊性,所以,對于還需要根據自己的數據來挑選適合的哈希算法。對于我以前的一個項目,公司內某牛人給我發來了一個哈希算法,結果讓我們的系統性能上升了150%。(關于各種哈希算法,你一定要看看StackExchange上的這篇關于各種hash算法的文章 )

分而治之和預處理。以前有一個程序為了生成月報表,每次都需要計算很長的時間,有時候需要花將近一整天的時間。于是我們把我們找到了一種方法可以把這個算法發成增量式的,也就是說我每天都把當天的數據計算好了后和前一天的報表合并,這樣可以大大的節省計算時間,每天的數據計算量只需要20分鐘,但是如果我要算整個月的,系統則需要10個小時以上(SQL語句在大數據量面前性能成級數性下降)。這種分而治之的思路在大數據面前對性能有很幫助,就像merge排序一樣。SQL語句和數據庫的性能優化也是這一策略,如:使用嵌套式的Select而不是笛卡爾積的Select,使用視圖,等等。

3.2代碼調優

從我的經驗上來說,代碼上的調優有下面這幾點:

字符串操作。這是最費系統性能的事了,無論是strcpy, strcat還是strlen,最需要注意的是字符串子串匹配。所以,能用整型最好用整型。舉幾個例子,第一個例子是N年前做銀行的時候,我的同事喜歡把日期存成字符串(如:2012-05-29 08:30:02),我勒個去,一個select where between語句相當耗時。另一個例子是,我以前有個同事把一些狀態碼用字符串來處理,他的理由是,這樣可以在界面上直接顯示,后來性能調優的時候,我把這些狀態碼全改成整型,然后用位操作查狀態,因為有一個每秒鐘被調用了150K次的函數里面有三處需要檢查狀態,經過改善以后,整個系統的性能上升了30%左右。還有一個例子是,我以前從事的某個產品編程規范中有一條是要在每個函數中把函數名定義出來,如:const char fname[]=”functionName()”, 這是為了好打日志,但是為什么不聲明成 static類型的呢?

多線程調優。有人說,thread is evil,這個對于系統性能在某些時候是個問題。因為多線程瓶頸就在于互斥和同步的鎖上,以及線程上下文切換的成本,怎么樣的少用鎖或不用鎖是根本(比如:多版本并發控制(MVCC)在分布式系統中的應用 中說的樂觀鎖可以解決性能問題),此外,還有讀寫鎖也可以解決大多數是讀操作的并發的性能問題。這里多說一點在C++中,我們可能會使用線程安全的智能指針AutoPtr或是別的一些容器,只要是線程安全的,其不管三七二十一都要上鎖,上鎖是個成本很高的操作,使用AutoPtr會讓我們的系統性能下降得很快,如果你可以保證不會有線程并發問題,那么你應該不要用AutoPtr。

我記得我上次我們同事去掉智能指針的引用計數,讓系統性能提升了50%以上。對于Java對象的引用計數,如果我猜的沒錯的話,到處都是鎖,所以,Java的性能問題一直是個問題。另外,線程不是越多越好,線程間的調度和上下文切換也是很夸張的事,盡可能的在一個線程里干,盡可能的不要同步線程。這會讓你有很多的性能。

內存分配。不要小看程序的內存分配。malloc/realloc/calloc這樣的系統調非常耗時,尤其是當內存出現碎片的時候。我以前的公司出過這樣一個問題——在用戶的站點上,我們的程序有一天不響應了,用GDB跟進去一看,系統hang在了malloc操作上,20秒都沒有返回,重啟一些系統就好了。這就是內存碎片的問題。這就是為什么很多人抱怨STL有嚴重的內存碎片的問題,因為太多的小內存的分配釋放了。有很多人會以為用內存池可以解決這個問題,但是實際上他們只是重新發明了Runtime-C或操作系統的內存管理機制,完全于事無補。

當然解決內存碎片的問題還是通過內存池,具體來說是一系列不同尺寸的內存池(這個留給大家自己去思考)。當然,少進行動態內存分配是最好的。說到內存池就需要說一下池化技術。比如線程池,連接池等。池化技術對于一些短作業來說(如http服務) 相當相當的有效。這項技術可以減少鏈接建立,線程創建的開銷,從而提高性能。

異步操作。我們知道Unix下的文件操作是有block和non-block的方式的,像有些系統調用也是block式的,如:Socket下的select,Windows下的WaitforObject之類的,如果我們的程序是同步操作,那么會非常影響性能,我們可以改成異步的,但是改成異步的方式會讓你的程序變復雜。異步方式一般要通過隊列,要注間隊列的性能問題,另外,異步下的狀態通知通常是個問題,比如消息事件通知方式,有callback方式,等,這些方式同樣可能會影響你的性能。但是通常來說,異步操作會讓性能的吞吐率有很大提升(Throughput),但是會犧牲系統的響應時間(latency)。這需要業務上支持。

語言和代碼庫。我們要熟悉語言以及所使用的函數庫或類庫的性能。比如:STL中的很多容器分配了內存后,那怕你刪除元素,內存也不會回收,其會造成內存泄露的假像,并可能造成內存碎片問題。再如,STL某些容器的size()==0 和 empty()是不一樣的,因為,size()是O(n)復雜度,empty()是O(1)的復雜度,這個要小心。Java中的JVM調優需要使用的這些參數:-Xms -Xmx -Xmn -XX:SurvivorRatio -XX:MaxTenuringThreshold,還需要注意JVM的GC,GC的霸氣大家都知道,尤其是full GC(還整理內存碎片),他就像“恐龍特級克賽號”一樣,他運行的時候,整個世界的時間都停止了。

3.3網絡調優

關于網絡調優,尤其是TCP Tuning(你可以以這兩個關鍵詞在網上找到很多文章),這里面有很多很多東西可以說。看看Linux下TCP/IP的那么多參數就知道了(順便說一下,你也許不喜歡Linux,但是你不能否認Linux給我們了很多可以進行內核調優的權力)。

⑴TCP調優

我們知道TCP鏈接是有很多開銷的,一個是會占用文件描述符,另一個是會開緩存,一般來說一個系統可以支持的TCP鏈接數是有限的,我們需要清楚地認識到TCP鏈接對系統的開銷是很大的。正是因為TCP是耗資源的,所以,很多攻擊都是讓你系統上出現大量的TCP鏈接,把你的系統資源耗盡。比如著名的SYNC Flood攻擊。

所以,我們要注意配置KeepAlive參數,這個參數的意思是定義一個時間,如果鏈接上沒有數據傳輸,系統會在這個時間發一個包,如果沒有收到回應,那么TCP就認為鏈接斷了,然后就會把鏈接關閉,這樣可以回收系統資源開銷。(注:HTTP層上也有KeepAlive參數)對于像HTTP這樣的短鏈接,設置一個1-2分鐘的keepalive非常重要。這可以在一定程度上防止DoS攻擊。有下面幾個參數(下面這些參數的值僅供參考):

net. ipv4. tcp_ keepalive_ probes =5
net. ipv4.tcp. keepalive. intvl = 20
net. ipv4.tcp_ fin. timeout = 30

對于TCP的TIME_WAIT這個狀態,主動關閉的一方進入TIME_WAIT狀態,TIME_WAIT狀態將持續2個MSL(Max Segment Lifetime),默認為4分鐘,TIME_WAIT狀態下的資源不能回收。有大量的TIME_WAIT鏈接的情況一般是在HTTP服務器上。對此,有兩個參數需要注意:

net.ipv4.tcp_tw_ reuse = 1
net.ipv4.tcp_tw_ recycle = 1

前者表示重用TIME_WAIT,后者表示回收TIME_WAIT的資源。TCP還有一個重要的概念叫RWIN(TCP Receive Window Size),這個東西的意思是,我一個TCP鏈接在沒有向Sender發出ack時可以接收到的最大的數據包。為什么這個很重要?因為如果Sender沒有收到Receiver發過來ack,Sender就會停止發送數據并會等一段時間,如果超時,那么就會重傳。這就是為什么TCP鏈接是可靠鏈接的原因。重傳還不是最嚴重的,如果有丟包發生的話,TCP的帶寬使用率會馬上受到影響(會盲目減半),再丟包,再減半,然后如果不丟包了,就逐步恢復。相關參數如下:

net.core . wmem _default = 8388608
net. core . rmem_ default = 8388608
net. core. rmem max = 16777216
net. core .wmem max = 16777216

傳所有的數據,反而影響網絡性能。(當然,網絡差的情況下,就別玩什么高性能了) 所以,高性能的網絡重要的是要讓網絡丟包率非常非常地小(基本上是用在LAN里),如果網絡基本是可信的,這樣用大一點的buffer會有更好的網絡傳輸性能(來來回回太多太影響性能了)。

另外,我們想一想,如果網絡質量非常好,基本不丟包,而業務上我們不怕偶爾丟幾個包,如果是這樣的話,那么,我們為什么不用速度更快的UDP呢?你想過這個問題了嗎?

⑵UDP調優

說到UDP的調優,有一些事我想重點說一樣,那就是MTU——最大傳輸單元(其實這對TCP也一樣,因為這是鏈路層上的東西)。所謂最大傳輸單元,你可以想像成是公路上的公交車,假設一個公交車可以最多坐70人,帶寬就像是公路的車道數一樣,如果一條路上最多可以容下100輛公交車,那意味著我最多可以運送7000人,但是如果公交車坐不滿,比如平均每輛車只有20人,那么我只運送了2000人,于是我公路資源(帶寬資源)就被浪費了。所以,我們對于一個UDP的包,我們要盡量地讓他大到MTU的最大尺寸再往網絡上傳,這樣可以最大化帶寬利用率。對于這個MTU,以太網是1500字節,光纖是4352字節,802.11無線網是7981。

但是,當我們用TCP/UDP發包的時候,我們的有效負載Payload要低于這個值,因為IP協議會加上20個字節,UDP會加上8個字節(TCP加的更多),所以,一般來說,你的一個UDP包的最大應該是1500-8-20=1472,這是你的數據的大小。當然,如果你用光纖的話, 這個值就可以更大一些。(順便說一下,對于某些NB的千光以態網網卡來說,在網卡上,網卡硬件如果發現你的包的大小超過了MTU,其會幫你做fragment,到了目標端又會幫你做重組,這就不需要你在程序中處理了)

再多說一下,使用Socket編程的時候,你可以使用setsockopt() 設置 SO_SNDBUF/SO_RCVBUF 的大小,TTL和KeepAlive這些關鍵的設置,當然,還有很多,具體你可以查看一下Socket的手冊。

最后說一點,UDP還有一個最大的好處是multi-cast多播,這個技術對于你需要在內網里通知多臺結點時非常方便和高效。而且,多播這種技術對于機會的水平擴展(需要增加機器來偵聽多播信息)也很有利。

⑶網卡調優

對于網卡,我們也是可以調優的,這對于千兆以及網網卡非常必要,在Linux下,我們可以用ifconfig查看網上的統計信息,如果我們看到overrun上有數據,我們就可能需要調整一下txqueuelen的尺寸(一般默認為1000),我們可以調大一些,如:ifconfig eth0 txqueuelen 5000。Linux下還有一個命令叫:ethtool可以用于設置網卡的緩沖區大小。在Windows下,我們可以在網卡適配器中的高級選項卡中調整相關的參數(如:Receive Buffers, Transmit Buffer等,不同的網卡有不同的參數)。把Buffer調大對于需要大數據量的網絡傳輸非常有效。

⑷其它網絡性能

關于多路復用技術,也就是用一個線程來管理所有的TCP鏈接,有三個系統調用要重點注意:一個是select,這個系統調用只支持上限1024個鏈接,第二個是poll,其可以突破1024的限制,但是select和poll本質上是使用的輪詢機制,輪詢機制在鏈接多的時候性能很差,因主是O(n)的算法,所以,epoll出現了,epoll是操作系統內核支持的,僅當在鏈接活躍時,操作系統才會callback,這是由操作系統通知觸發的,但其只有Linux Kernel 2.6以后才支持(準確說是2.5.44中引入的),當然,如果所有的鏈接都是活躍的,過多的使用epoll_ctl可能會比輪詢的方式還影響性能,不過影響的不大。

另外,關于一些和DNS Lookup的系統調用要小心,比如:gethostbyaddr/gethostbyname,這個函數可能會相當的費時,因為其要到網絡上去找域名,因為DNS的遞歸查詢,會導致嚴重超時,而又不能通過設置什么參數來設置time out,對此你可以通過配置hosts文件來加快速度,或是自己在內存中管理對應表,在程序啟動時查好,而不要在運行時每次都查。另外,在多線程下面,gethostbyname會一個更嚴重的問題,就是如果有一個線程的gethostbyname發生阻塞,其它線程都會在gethostbyname處發生阻塞,這個比較變態,要小心。(你可以試試GNU的gethostbyname_r(),這個的性能要好一些) 這種到網上找信息的東西很多,比如,如果你的Linux使用了NIS,或是NFS,某些用戶或文件相關的系統調用就很慢,所以要小心。

3.4系統調優

⑴I/O模型

前面說到過select/poll/epoll這三個系統調用,我們都知道,Unix/Linux下把所有的設備都當成文件來進行I/O,所以,那三個操作更應該算是I/O相關的系統調用。說到 I/O模型,這對于我們的I/O性能相當重要,我們知道,Unix/Linux經典的I/O方式是(關于Linux下的I/O模型,大家可以讀一下這篇文章《使用異步I/O大大提高性能》):

  • 第一種,同步阻塞式I/O,這個不說了。
  • 第二種,同步無阻塞方式。其通過fctnl設置 O_NONBLOCK 來完成。
  • 第三種,對于select/poll/epoll這三個是I/O不阻塞,但是在事件上阻塞,算是:I/O異步,事件同步的調用。
  • 第四種,AIO方式。這種I/O 模型是一種處理與 I/O 并行的模型。I/O請求會立即返回,說明請求已經成功發起了。在后臺完成I/O操作時,向應用程序發起通知,通知有兩種方式:一種是產生一個信號,另一種是執行一個基于線程的回調函數來完成這次 I/O 處理過程。

第四種因為沒有任何的阻塞,無論是I/O上,還是事件通知上,所以,其可以讓你充分地利用CPU,比起第二種同步無阻塞好處就是,第二種要你一遍一遍地去輪詢。Nginx之所所以高效,是其使用了epoll和AIO的方式來進行I/O的。

再說一下Windows下的I/O模型:

  • a)一個是WriteFile系統調用,這個系統調用可以是同步阻塞的,也可以是同步無阻塞的,關于看文件是不是以Overlapped打開的。關于同步無阻塞,需要設置其最后一個參數Overlapped,微軟叫Overlapped I/O,你需要WaitForSingleObject才能知道有沒有寫完成。這個系統調用的性能可想而知。
  • b)另一個叫WriteFileEx的系統調用,其可以實現異步I/O,并可以讓你傳入一個callback函數,等I/O結束后回調之, 但是這個回調的過程Windows是把callback函數放到了APC(Asynchronous Procedure Calls)的隊列中,然后,只用當應用程序當前線程成為可被通知狀態(Alterable)時,才會被回調。只有當你的線程使用了這幾個函數時WaitForSingleObjectEx, WaitForMultipleObjectsEx, MsgWaitForMultipleObjectsEx, SignalObjectAndWait 和 SleepEx,線程才會成為Alterable狀態。可見,這個模型,還是有wait,所以性能也不高。
  • c)然后是IOCP – IO Completion Port,IOCP會把I/O的結果放在一個隊列中,但是,偵聽這個隊列的不是主線程,而是專門來干這個事的一個或多個線程去干(老的平臺要你自己創建線程,新的平臺是你可以創建一個線程池)。IOCP是一個線程池模型。這個和Linux下的AIO模型比較相似,但是實現方式和使用方式完全不一樣。

當然,真正提高I/O性能方式是把和外設的I/O的次數降到最低,最好沒有,所以,對于讀來說,內存cache通常可以從質上提升性能,因為內存比外設快太多了。對于寫來說,cache住要寫的數據,少寫幾次,但是cache帶來的問題就是實時性的問題,也就是latency會變大,我們需要在寫的次數上和相應上做權衡。

⑵多核CPU調優

關于CPU的多核技術,我們知道,CPU0是很關鍵的,如果0號CPU被用得過狠的話,別的CPU性能也會下降,因為CPU0是有調整功能的,所以,我們不能任由操作系統負載均衡,因為我們自己更了解自己的程序,所以,我們可以手動地為其分配CPU核,而不會過多地占用CPU0,或是讓我們關鍵進程和一堆別的進程擠在一起。

  • 對于Windows來說,我們可以通過“任務管理器”中的“進程”而中右鍵菜單中的“設置相關性……”(Set Affinity…)來設置并限制這個進程能被運行在哪些核上。
  • 對于Linux來說,可以使用taskset命令來設置(你可以通過安裝schedutils來安裝這個命令:apt-get install schedutils)

多核CPU還有一個技術叫NUMA技術(Non-Uniform Memory Access)。傳統的多核運算是使用SMP(Symmetric Multi-Processor )模式,多個處理器共享一個集中的存儲器和I/O總線。于是就會出現一致存儲器訪問的問題,一致性通常意味著性能問題。NUMA模式下,處理器被劃分成多個node, 每個node有自己的本地存儲器空間。關于NUMA的一些技術細節,你可以查看一下這篇文章《Linux 的 NUMA 技術》,在Linux下,對NUMA調優的命令是:numactl 。如下面的命令:(指定命令“myprogram arg1 arg2”運行在node 0 上,其內存分配在node 0 和 1上)

1

numactl --cpubind=0 --membind=0,1 myprogram arg1 arg2

當然,上面這個命令并不好,因為內存跨越了兩個node,這非常不好。最好的方式是只讓程序訪問和自己運行一樣的node,如:

1

$ numactl --membind 1 --cpunodebind 1 --localalloc myapplication

⑶文件系統調優

關于文件系統,因為文件系統也是有cache的,所以,為了讓文件系統有最大的性能。首要的事情就是分配足夠大的內存,這個非常關鍵,在Linux下可以使用free命令來查看 free/used/buffers/cached,理想來說,buffers和cached應該有40%左右。然后是一個快速的硬盤控制器,SCSI會好很多。最快的是Intel SSD 固態硬盤,速度超快,但是寫次數有限。

接下來,我們就可以調優文件系統配置了,對于Linux的Ext3/4來說,幾乎在所有情況下都有所幫助的一個參數是關閉文件系統訪問時間,在/etc/fstab下看看你的文件系統 有沒有noatime參數(一般來說應該有),還有一個是dealloc,它可以讓系統在最后時刻決定寫入文件發生時使用哪個塊,可優化這個寫入程序。還要注間一下三種日志模式:data=journal、data=ordered和data=writeback。默認設置data=ordered提供性能和防護之間的最佳平衡。

當然,對于這些來說,ext4的默認設置基本上是最佳優化了。

這里介紹一個Linux下的查看I/O的命令—— iotop,可以讓你看到各進程的磁盤讀寫的負載情況。

其它還有一些關于NFS、XFS的調優,大家可以上google搜索一些相關優化的文章看看。關于各文件系統,大家可以看一下這篇文章——《Linux日志文件系統及性能分析》

3.5數據庫調優

數據庫調優并不是我的強項,我就僅用我非常有限的知識說上一些吧。注意,下面的這些東西并不一定正確,因為在不同的業務場景,不同的數據庫設計下可能會得到完全相反的結論,所以,我僅在這里做一些一般性的說明,具體問題還要具體分析。

⑴數據庫引擎調優

我對數據庫引擎不是熟,但是有幾個事情我覺得是一定要去了解的。

數據庫的鎖的方式。這個非常非常地重要。并發情況下,鎖是非常非常影響性能的。各種隔離級別,行鎖,表鎖,頁鎖,讀寫鎖,事務鎖,以及各種寫優先還是讀優先機制。性能最高的是不要鎖,所以,分庫分表,冗余數據,減少一致性事務處理,可以有效地提高性能。NoSQL就是犧牲了一致性和事務處理,并冗余數據,從而達到了分布式和高性能。

數據庫的存儲機制。不但要搞清楚各種類型字段是怎么存儲的,更重要的是數據庫的數據存儲方式,是怎么分區的,是怎么管理的,比如Oracle的數據文件,表空間,段,等等。了解清楚這個機制可以減輕很多的I/O負載。比如:MySQL下使用show engines;可以看到各種存儲引擎的支持。不同的存儲引擎有不同的側重點,針對不同的業務或數據庫設計會讓你有不同的性能。

數據庫的分布式策略。最簡單的就是復制或鏡像,需要了解分布式的一致性算法,或是主主同步,主從同步。通過了解這種技術的機理可以做到數據庫級別的水平擴展。

⑵SQL語句優化

關于SQL語句的優化,首先也是要使用工具,比如:MySQL SQL Query Analyzer,Oracle SQL Performance Analyzer,或是微軟SQL Query Analyzer,基本上來說,所有的RMDB都會有這樣的工具,來讓你查看你的應用中的SQL的性能問題。還可以使用explain來看看SQL語句最終Execution Plan會是什么樣的。

還有一點很重要,數據庫的各種操作需要大量的內存,所以服務器的內存要夠,優其應對那些多表查詢的SQL語句,那是相當的耗內存。

下面我根據我有限的數據庫SQL的知識說幾個會有性能問題的SQL:

全表檢索。比如:select * from user where lastname = “xxxx”,這樣的SQL語句基本上是全表查找,線性復雜度O(n),記錄數越多,性能也越差(如:100條記錄的查找要50ms,一百萬條記錄需要5分鐘)。對于這種情況,我們可以有兩種方法提高性能:一種方法是分表,把記錄數降下來,另一種方法是建索引(為lastname建索引)。索引就像是key-value的數據結構一樣,key就是where后面的字段,value就是物理行號,對索引的搜索復雜度是基本上是O(log(n)) ——用B-Tree實現索引(如:100條記錄的查找要50ms,一百萬條記錄需要100ms)。

索引。對于索引字段,最好不要在字段上做計算、類型轉換、函數、空值判斷、字段連接操作,這些操作都會破壞索引原本的性能。當然,索引一般都出現在Where或是Order by字句中,所以對Where和Order by子句中的子段最好不要進行計算操作,或是加上什么NOT之類的,或是使用什么函數。

多表查詢。關系型數據庫最多的操作就是多表查詢,多表查詢主要有三個關鍵字,EXISTS,IN和JOIN(關于各種join,可以參看圖解SQL的Join一文)。基本來說,現代的數據引擎對SQL語句優化得都挺好的,JOIN和IN/EXISTS在結果上有些不同,但性能基本上都差不多。有人說,EXISTS的性能要好于IN,IN的性能要好于JOIN,我各人覺得,這個還要看你的數據、schema和SQL語句的復雜度,對于一般的簡單的情況來說,都差不多,所以千萬不要使用過多的嵌套,千萬不要讓你的SQL太復雜,寧可使用幾個簡單的SQL也不要使用一個巨大無比的嵌套N級的SQL。還有人說,如果兩個表的數據量差不多,Exists的性能可能會高于In,In可能會高于Join,如果這兩個表一大一小,那么子查詢中,Exists用大表,In則用小表。這個,我沒有驗證過,放在這里讓大家討論吧。另,有一篇關于SQL Server的文章大家可以看看《IN vs JOIN vs EXISTS》

JOIN操作。有人說,Join表的順序會影響性能,只要Join的結果集是一樣,性能和join的次序無關。因為后臺的數據庫引擎會幫我們優化的。Join有三種實現算法,嵌套循環,排序歸并,和Hash式的Join。(MySQL只支持第一種)

嵌套循環,就好像是我們常見的多重嵌套循環。注意,前面的索引說過,數據庫的索引查找算法用的是B-Tree,這是O(log(n))的算法,所以,整個算法復法度應該是O(log(n)) * O(log(m)) 這樣的。

Hash式的Join,主要解決嵌套循環的O(log(n))的復雜,使用一個臨時的hash表來標記。

排序歸并,意思是兩個表按照查詢字段排好序,然后再合并。當然,索引字段一般是排好序的。

還是那句話,具體要看什么樣的數據,什么樣的SQL語句,你才知道用哪種方法是最好的。

部分結果集。我們知道MySQL里的Limit關鍵字,Oracle里的rownum,SQL Server里的Top都是在限制前幾條的返回結果。這給了我們數據庫引擎很多可以調優的空間。一般來說,返回top n的記錄數據需要我們使用order by,注意在這里我們需要為order by的字段建立索引。有了被建索引的order by后,會讓我們的select語句的性能不會被記錄數的所影響。使用這個技術,一般來說我們前臺會以分頁方式來顯現數據,Mysql用的是OFFSET,SQL Server用的是FETCH NEXT,這種Fetch的方式其實并不好是線性復雜度,所以,如果我們能夠知道order by字段的第二頁的起始值,我們就可以在where語句里直接使用>=的表達式來select,這種技術叫seek,而不是fetch,seek的性能比fetch要高很多。

  • 字符串。正如我前面所說的,字符串操作對性能上有非常大的惡夢,所以,能用數據的情況就用數字,比如:時間,工號,等。
  • 全文檢索。千萬不要用Like之類的東西來做全文檢索,如果要玩全文檢索,可以嘗試使用Sphinx。
  • 其它。
  • 不要select *,而是明確指出各個字段,如果有多個表,一定要在字段名前加上表名,不要讓引擎去算。
  • 不要用Having,因為其要遍歷所有的記錄。性能差得不能再差。
  • 盡可能地使用UNION ALL 取代 UNION。
  • 索引過多,insert和delete就會越慢。而update如果update多數索引,也會慢,但是如果只update一個,則只會影響一個索引表。
  • 等等。

四、內核性能調優實戰技巧

4.1內存相關參數調整

在 Linux 系統中,內存管理對于系統性能起著舉足輕重的作用。合理調整內存相關參數,能夠顯著提升系統的運行效率和穩定性。

vm.swappiness 是一個關鍵的內存參數,它主要用于控制系統在內存不足時將頁面交換到磁盤交換空間(swap)的傾向程度 。該參數的取值范圍是 0 - 100,默認值為 60。當 vm.swappiness 的值設置得較高時,比如接近 100,系統會更頻繁地使用磁盤交換空間。這在物理內存不足的情況下,雖然能暫時滿足系統對內存的需求,但由于磁盤 I/O 操作的速度遠遠慢于內存訪問速度,會導致系統性能大幅下降。相反,如果將 vm.swappiness 的值設置得較低,如 10 或 20,系統則會盡量避免使用交換空間,優先使用物理內存。這對于那些對性能要求較高、內存使用頻繁的應用場景來說非常重要。

例如,在一個運行著數據庫服務器的 Linux 系統中,如果數據庫操作頻繁且對響應速度要求極高,將 vm.swappiness 設置為 10,可以減少磁盤交換操作,提高數據庫的讀寫性能,從而提升整個系統的響應速度。調整 vm.swappiness 參數的方法很簡單,我們可以通過修改 /etc/sysctl.conf 文件來實現。在該文件中添加或修改 “vm.swappiness = [想要的值]” 這一行,然后執行 “sysctl -p” 命令使配置生效。

vm.overcommit_memory 參數則控制系統是否允許超額分配內存 。它有三個可選值:0、1 和 2。當取值為 0 時,這是系統的默認設置,內核會嘗試估算當前系統剩余的可用內存,只有在估算認為內存分配請求不會導致系統內存不足時,才會允許分配內存。當取值為 1 時,內核會允許超量使用內存,直到物理內存被耗盡為止。這種設置適用于那些對內存需求有明確預估,且在內存使用上比較保守的應用場景。比如在一些科學計算任務中,應用程序能夠準確控制自身的內存使用量,設置為 1 可以充分利用系統內存資源,提高計算效率。

當取值為 2 時,內核會采用一種嚴格的內存分配算法,確保系統的整個內存地址空間(包括物理內存和交換空間)不會超過 “swap + 50% 的 RAM 值”。這是一種非常保守的設置,能有效防止系統因內存過度分配而崩潰。調整 vm.overcommit_memory 參數同樣可以通過修改 /etc/sysctl.conf 文件來完成。在文件中添加或修改 “vm.overcommit_memory = [想要的值]”,然后執行 “sysctl -p” 命令使更改生效。

4.2網絡相關參數調整

在當今網絡互聯的時代,網絡性能的優劣直接影響著系統的整體表現。通過合理調整網絡相關的內核參數,能夠有效提升網絡的吞吐量、降低延遲,確保系統在網絡通信方面的高效穩定。

net.core.somaxconn 參數定義了 TCP 連接的最大排隊數量 ,也就是當服務器在監聽某個端口時,處于等待狀態的最大 TCP 連接請求數。其默認值通常為 128,在一些高并發的網絡應用場景中,這個值可能顯得過小。比如在一個大型的電商網站服務器上,在促銷活動期間,大量用戶同時訪問服務器,發起海量的 TCP 連接請求。如果 net.core.somaxconn 的值仍然保持默認的 128,那么當等待連接的請求數超過這個值時,后續的連接請求就可能會被丟棄,導致用戶無法正常訪問網站,嚴重影響用戶體驗和業務的正常開展。

為了應對這種高并發的情況,我們可以根據服務器的實際性能和預估的并發連接數,將 net.core.somaxconn 的值適當增大,比如設置為 1024 或更高。這樣可以讓服務器能夠容納更多的等待連接請求,避免因連接隊列溢出而造成的連接失敗問題。要調整 net.core.somaxconn 參數,可以編輯 /etc/sysctl.conf 文件,添加或修改 “net.core.somaxconn = [想要的值]” 這一行,之后執行 “sysctl -p” 命令使新的配置生效。

net.ipv4.tcp_syncookies 是一個用于應對 SYN 洪水攻擊的重要參數 。SYN 洪水攻擊是一種常見的網絡攻擊方式,攻擊者通過向目標服務器發送大量偽造的 SYN 請求,耗盡服務器的連接資源,從而使服務器無法正常處理合法的連接請求。當 net.ipv4.tcp_syncookies 設置為 1 時,系統啟用 syncookies 機制。在這種機制下,當服務器接收到 SYN 請求時,如果發現 SYN 隊列已滿,它不會直接丟棄該請求,而是根據接收到的 SYN 包中的信息計算出一個特殊的 cookie 值,并將其作為 SYN + ACK 包的序列號發送給客戶端。

客戶端在收到 SYN + ACK 包后,會將這個 cookie 值包含在 ACK 包中回傳給服務器。服務器通過驗證這個 cookie 值,來確認該連接請求的合法性,從而在不占用過多系統資源的情況下,有效地抵御 SYN 洪水攻擊。而當 net.ipv4.tcp_syncookies 設置為 0 時,系統則不啟用 syncookies 機制。對于那些面臨較高網絡安全風險,尤其是可能遭受 SYN 洪水攻擊的服務器來說,將 net.ipv4.tcp_syncookies 設置為 1 是一個非常必要的安全措施。與前面的參數調整方法類似,我們可以通過修改 /etc/sysctl.conf 文件,添加或修改 “net.ipv4.tcp_syncookies = 1” 這一行,并執行 “sysctl -p” 命令來使設置生效。

4.3文件系統相關參數調整

文件系統是 Linux 系統中數據存儲和管理的核心部分,其性能的好壞直接關系到系統對文件的讀寫效率,進而影響整個系統的運行速度。通過優化文件系統相關的內核參數,可以顯著提升文件系統的性能,滿足不同應用場景下對文件操作的高效需求。

fs.file - max 參數用于指定系統中所有進程總共能夠打開的最大文件句柄數量 。文件句柄是系統用于標識和管理打開文件的一種資源,每個進程在進行文件操作時,都需要獲取相應的文件句柄。在一些大規模的數據處理應用場景中,例如一個數據倉庫系統,可能需要同時處理大量的文件,包括讀取數據文件進行分析、寫入結果文件等操作。如果 fs.file - max 的值設置得過低,當進程打開的文件句柄數量達到這個上限時,后續的文件打開操作就會失敗,導致應用程序無法正常運行。

為了確保這類應用能夠順利進行,我們需要根據實際的業務需求和系統資源情況,合理地增大 fs.file - max 的值。例如,如果系統的內存資源充足,且預計在高峰時期需要同時打開數萬個文件句柄,那么可以將 fs.file - max 設置為一個較大的值,如 1048576。調整 fs.file - max 參數的方式是在 /etc/sysctl.conf 文件中添加或修改 “fs.file - max = [想要的值]” 這一行,然后執行 “sysctl -p” 命令,使新的配置生效,讓系統能夠支持更多的文件句柄打開操作。

fs.aio - max - nr 參數主要控制著系統中允許的并發異步 I/O 請求的最大數量 。異步 I/O 是一種高效的文件 I/O 操作方式,它允許應用程序在發起 I/O 請求后,無需等待 I/O 操作完成,就可以繼續執行其他任務,從而提高系統的并發處理能力和整體性能。在一些對 I/O 操作性能要求極高的場景中,如數據庫的讀寫操作、大數據的實時處理等,大量的并發異步 I/O 請求能夠充分利用系統資源,加快數據的傳輸速度。如果 fs.aio - max - nr 的值設置得過小,那么系統能夠同時處理的異步 I/O 請求數量就會受到限制,無法充分發揮異步 I/O 的優勢。

例如,在一個高性能的數據庫服務器中,可能需要同時處理成千上萬的并發異步 I/O 請求來滿足大量用戶的讀寫需求。此時,將 fs.aio - max - nr 設置為一個較大的值,如 102400,能夠確保系統有足夠的能力處理這些并發請求,提高數據庫的響應速度和吞吐量。要調整 fs.aio - max - nr 參數,同樣需要編輯 /etc/sysctl.conf 文件,在其中添加或修改 “fs.aio - max - nr = [想要的值]”,之后執行 “sysctl -p” 命令,使系統按照新的配置來管理并發異步 I/O 請求。

五、調優案例深度剖析

5.1案例背景介紹

某在線教育平臺,隨著業務的迅猛發展,用戶數量呈現爆發式增長。原本運行流暢的系統,在高并發的訪問壓力下,逐漸暴露出性能問題。用戶反饋在觀看課程視頻時,經常出現卡頓現象,視頻加載緩慢,甚至有時會出現長時間無法加載的情況。在進行課程互動,如提交作業、參與討論等操作時,響應時間也明顯變長,嚴重影響了用戶的學習體驗。

該平臺的服務器基于 Linux 系統搭建,采用了常見的 LAMP 架構(Linux + Apache + MySQL + PHP)。面對日益嚴峻的性能挑戰,平臺的技術團隊決定深入排查問題,并對 Linux 內核進行性能調優,以提升系統的整體性能和穩定性。

5.2問題排查過程

技術團隊首先對系統的運行日志進行了詳細分析。通過查看 Apache 服務器的日志,發現大量的請求超時記錄,這表明服務器在處理用戶請求時遇到了困難,無法及時響應。同時,MySQL 數據庫的日志中也出現了一些慢查詢記錄,這意味著數據庫的查詢性能可能受到了影響。

為了進一步確定性能瓶頸所在,團隊使用了 top 命令來實時監控系統的資源使用情況。結果發現,CPU 的使用率長時間保持在高位,尤其是在用戶訪問高峰期,幾乎達到了 100%。通過分析 top 命令的輸出,發現一些與視頻處理和數據庫查詢相關的進程占用了大量的 CPU 資源。

接著,團隊使用 iostat 命令來檢查磁盤 I/O 情況。從輸出結果可以看出,磁盤的讀寫速度較慢,尤其是在讀取視頻文件時,磁盤的繁忙程度(% util)接近 100%,這表明磁盤 I/O 可能成為了系統性能的瓶頸。

在網絡方面,團隊使用 iftop 命令來監控網絡帶寬的使用情況。發現網絡帶寬在高并發情況下被大量占用,尤其是視頻傳輸所占用的帶寬較大,導致其他業務的網絡請求受到影響。

5.3調優措施實施

針對排查出的問題,技術團隊采取了一系列針對性的調優措施。

在 CPU 方面,對一些與視頻處理相關的進程進行了優化,通過調整算法和代碼邏輯,減少了不必要的計算量。同時,啟用了 CPU 的多核特性,將一些任務分配到不同的核心上并行處理,提高了 CPU 的利用率。

對于磁盤 I/O 問題,將存儲視頻文件的磁盤更換為更高性能的固態硬盤(SSD),顯著提升了磁盤的讀寫速度。此外,對數據庫的查詢語句進行了優化,減少了不必要的磁盤訪問,并添加了適當的索引,加快了數據的檢索速度。

在網絡方面,對視頻傳輸進行了優化,采用了流媒體技術,實現了視頻的分段傳輸和緩存,減少了網絡帶寬的占用。同時,調整了網絡相關的內核參數,如增大了 net.core.somaxconn 的值,以提高服務器能夠處理的并發連接數。

5.4調優效果展示

經過一系列的調優措施實施后,系統的性能得到了顯著提升。視頻加載速度明顯加快,卡頓現象幾乎消失,用戶在觀看課程視頻時能夠享受到流暢的體驗。在課程互動方面,提交作業、參與討論等操作的響應時間大幅縮短,用戶能夠及時得到反饋。

從性能指標上看,系統的吞吐量得到了顯著提高,在相同的時間內能夠處理更多的用戶請求。系統延遲也明顯降低,平均響應時間從原來的數秒縮短到了 1 秒以內。CPU 的使用率在高并發情況下也能夠保持在合理范圍內,不再出現長時間滿載的情況。磁盤 I/O 的性能得到了極大改善,磁盤的繁忙程度(% util)始終保持在較低水平。網絡帶寬的使用更加合理,各業務之間的網絡請求能夠得到有效的保障。

通過這次 Linux 內核性能調優,該在線教育平臺成功應對了業務量增長帶來的挑戰,為用戶提供了更加優質的服務,同時也為平臺的持續發展奠定了堅實的基礎。

責任編輯:武曉燕 來源: 深度Linux
相關推薦

2019-11-05 10:35:57

SpringBoot調優Java

2025-06-26 02:15:00

2021-01-04 15:11:57

開發 IDEA代碼

2020-09-29 07:54:05

Express 飛起

2011-04-13 10:51:58

MATLAB

2024-06-12 12:28:23

2021-07-13 07:52:03

SQL面試COUNT(*)

2025-04-15 00:00:00

2024-11-27 09:46:34

2025-03-28 03:20:00

MySQL數據庫搜索

2013-01-07 09:34:43

CodeLoveBAT

2011-02-25 08:39:11

QFabric數據中心Juniper

2025-06-04 01:35:00

RocketMQ異步消息

2011-03-18 11:21:48

2022-10-09 18:14:31

訂單系統分庫分表

2023-03-01 23:59:23

Java開發

2011-09-27 13:25:05

Web

2024-11-25 18:00:00

C#代碼編程

2019-03-25 08:05:35

Elasticsear優化集群

2016-01-19 17:03:59

數據中心網絡華為
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产在线资源 | 日韩在线播放av | 久久av资源网 | 99精品一区 | 欧美精品电影一区 | 香蕉一区| 久久国产精品免费视频 | 日韩不卡在线 | 涩涩导航 | 日韩欧美在线观看 | 国产免费视频 | 欧美一区二区三区在线看 | 99视频在线 | 中文字幕成人在线 | 国产精品久久九九 | 亚洲三级在线观看 | 日韩成人精品一区二区三区 | 国产乱码精品1区2区3区 | 日本中文在线视频 | 亚洲视频一区二区三区四区 | 久久亚洲欧美日韩精品专区 | 国产成人在线视频播放 | 亚洲天堂日韩精品 | 性色av香蕉一区二区 | 久久激情五月丁香伊人 | 天天干天天想 | 91精品国产91久久久久久最新 | 四虎成人免费视频 | 一区二区三区在线免费观看 | 7777奇米影视 | 成人自拍视频网站 | 91黄色片免费看 | 99热最新网址 | 国产精品久久久乱弄 | 久久精品免费 | 欧美高清视频在线观看 | 男女啪啪高潮无遮挡免费动态 | 亚洲国产高清在线观看 | 精品久久久久久亚洲精品 | 国产在线视频一区二区 | 99久久精品视频免费 |