Linux系統kernel參數優化

来源:https://www.cnblogs.com/will-space/archive/2018/08/05/9427480.html
-Advertisement-
Play Games

眾所周知在預設參數情況下Linux對高併發支持並不好,主要受限於單進程最大打開文件數限制、內核TCP參數方面和IO事件分配機制等。下麵就從幾方面來調整使Linux系統能夠支持高併發環境。 iptables相關 如非必須,關掉或卸載iptables防火牆,並阻止kernel載入iptables模塊。這 ...


目錄


眾所周知在預設參數情況下Linux對高併發支持並不好,主要受限於單進程最大打開文件數限制、內核TCP參數方面和IO事件分配機制等。下麵就從幾方面來調整使Linux系統能夠支持高併發環境。

iptables相關

如非必須,關掉或卸載iptables防火牆,並阻止kernel載入iptables模塊。這些模塊會影響併發性能。

單進程最大打開文件數限制

一般的發行版,限制單進程最大可以打開1024個文件,這是遠遠不能滿足高併發需求的,調整過程如下:
在#號提示符下敲入:ulimit–n 65535
將root啟動的單一進程的最大可以打開的文件數設置為65535個。如果系統回顯類似於“Operationnotpermitted”之類的話,說明上述限制修改失敗,實際上是因為在中指定的數值超過了Linux系統對該用戶打開文件數的軟限制或硬限制。因此,就需要修改Linux系統對用戶的關於打開文件數的軟限制和硬限制。

第一步,修改limits.conf文件,並添加:

vim /etc/security/limits.conf
* soft nofile 65536
* hard nofile 65536

其中'*'號表示修改所有用戶的限制;soft或hard指定要修改軟限制還是硬限制;65536則指定了想要修改的新的限制值,即最大打開文件數(請註意軟限制值要小於或等於硬限制)。修改完後保存文件。

第二步,修改/etc/pam.d/login文件,在文件中添加如下行:

vim /etc/pam.d/login
sessionrequired /lib/security/pam_limits.so

這是告訴Linux在用戶完成系統登錄後,應該調用pam_limits.so模塊來設置系統對該用戶可使用的各種資源數量的最大限制(包括用戶可打開的最大文件數限制),而pam_limits.so模塊就會從/etc/security/limits.conf文件中讀取配置來設置這些限制值。修改完後保存此文件。

第三步,查看Linux系統級的最大打開文件數限制,使用如下命令:

cat/proc/sys/fs/file-max
32568

這表明這台Linux系統最多允許同時打開(即包含所有用戶打開文件數總和)32568個文件,是Linux系統級硬限制,所有用戶級的打開文件數限制都不應超過這個數值。通常這個系統級硬限制是Linux系統在啟動時根據系統硬體資源狀況計算出來的最佳的最大同時打開文件數限制,如果沒有特殊需要,不應該修改此限制,除非想為用戶級打開文件數限制設置超過此限制的值。修改此硬限制的方法是修改/etc/sysctl.conf文件內fs.file-max= 131072
這是讓Linux在啟動完成後強行將系統級打開文件數硬限制設置為131072。修改完後保存此文件。

完成上述步驟後重啟系統,一般情況下就可以將Linux系統對指定用戶的單一進程允許同時打開的最大文件數限制設為指定的數值。如果重啟後用ulimit-n命令查看用戶可打開文件數限制仍然低於上述步驟中設置的最大值,這可能是因為在用戶登錄腳本/etc/profile中使用ulimit-n命令已經將用戶可同時打開的文件數做了限制。由於通過ulimit-n修改系統對用戶可同時打開文件的最大數限制時,新修改的值只能小於或等於上次ulimit-n設置的值,因此想用此命令增大這個限制值是不可能的。所以,如果有上述問題存在,就只能去打開/etc/profile腳本文件,在文件中查找是否使用了ulimit-n限制了用戶可同時打開的最大文件數量,如果找到,則刪除這行命令,或者將其設置的值改為合適的值,然後保存文件,用戶退出並重新登錄系統即可。

通過上述步驟,就為支持高併發TCP連接處理的通訊處理程式解除關於打開文件數量方面的系統限制。

內核TCP參數方面

Linux系統下,TCP連接斷開後,會以TIME_WAIT狀態保留一定的時間,然後才會釋放埠。當併發請求過多的時候,就會產生大量的TIME_WAIT狀態的連接,無法及時斷開的話,會占用大量的埠資源和伺服器資源。這個時候我們可以優化TCP的內核參數,來及時將TIME_WAIT狀態的埠清理掉。

下麵介紹的方法只對擁有大量TIME_WAIT狀態的連接導致系統資源消耗有效,如果不是這種情況下,效果可能不明顯。可以使用netstat命令去查TIME_WAIT狀態的連接狀態,輸入下麵的組合命令,查看當前TCP連接的狀態和對應的連接數量:

netstat-n | awk ‘/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}’

這個命令會輸出類似下麵的結果:

LAST_ACK16
SYN_RECV348
ESTABLISHED70
FIN_WAIT1229
FIN_WAIT230
CLOSING33
TIME_WAIT18098

我們只用關心TIME_WAIT的個數,在這裡可以看到,有18000多個TIME_WAIT,這樣就占用了18000多個埠。要知道埠的數量只有65535個,占用一個少一個,會嚴重的影響到後繼的新連接。這種情況下,我們就有必要調整下Linux的TCP內核參數,讓系統更快的釋放TIME_WAIT連接。

編輯配置文件:/etc/sysctl.conf,在這個文件中,加入下麵的幾行內容:

vim /etc/sysctl.conf
net.ipv4.tcp_syncookies= 1
net.ipv4.tcp_tw_reuse= 1
net.ipv4.tcp_tw_recycle= 1
net.ipv4.tcp_fin_timeout= 30

輸入下麵的命令,讓內核參數生效:

sysctl -p

簡單的說明上面的參數的含義:

net.ipv4.tcp_syncookies= 1
#表示開啟SYNCookies。當出現SYN等待隊列溢出時,啟用cookies來處理,可防範少量SYN攻擊,預設為0,表示關閉;   

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

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

net.ipv4.tcp_fin_timeout
#修改系統預設的TIMEOUT 時間。
在經過這樣的調整之後,除了會進一步提升伺服器的負載能力之外,還能夠防禦小流量程度的DoS、CC和SYN攻擊。

此外,如果你的連接數本身就很多,我們可以再優化一下TCP的可使用埠範圍,進一步提升伺服器的併發能力。依然是往上面的參數文件中,加入下麵這些配置:

net.ipv4.tcp_keepalive_time= 1200

net.ipv4.ip_local_port_range= 1024 65535

net.ipv4.tcp_max_syn_backlog= 8192

net.ipv4.tcp_max_tw_buckets= 5000

這幾個參數,建議只在流量非常大的伺服器上開啟,會有顯著的效果。一般的流量小的伺服器上,沒有必要去設置這幾個參數。

net.ipv4.tcp_keepalive_time= 1200
#表示當keepalive起用的時候,TCP發送keepalive消息的頻度。預設是2小時,改為20分鐘。

ip_local_port_range= 1024 65535
#表示用於向外連接的埠範圍。預設情況下很小,改為1024到65535。

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

net.ipv4.tcp_max_tw_buckets= 5000
#表示系統同時保持TIME_WAIT的最大數量,如果超過這個數字,TIME_WAIT將立刻被清除並列印警告信息。預設為180000,改為5000。此項參數可以控制TIME_WAIT的最大數量,只要超出了。

內核其他TCP參數說明

net.ipv4.tcp_max_syn_backlog= 65536
#記錄的那些尚未收到客戶端確認信息的連接請求的最大值。對於有128M記憶體的系統而言,預設值是1024,小記憶體的系統則是128。

net.core.netdev_max_backlog= 32768
#每個網路介面接收數據包的速率比內核處理這些包的速率快時,允許送到隊列的數據包的最大數目。

net.core.somaxconn= 32768
#例如web應用中listen函數的backlog預設會給我們內核參數的net.core.somaxconn限制到128,而nginx定義的NGX_LISTEN_BACKLOG預設為511,所以有必要調整這個值。

net.core.wmem_default= 8388608

net.core.rmem_default= 8388608

net.core.rmem_max= 16777216 #最大socket讀buffer,可參考的優化值:873200

net.core.wmem_max= 16777216 #最大socket寫buffer,可參考的優化值:873200

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

1

net.ipv4.tcp_synack_retries= 2
#為了打開對端的連接,內核需要發送一個SYN並附帶一個回應前面一個SYN的ACK。也就是所謂三次握手中的第二次握手。這個設置決定了內核放棄連接之前發送SYN+ACK包的數量。

net.ipv4.tcp_syn_retries= 2
#在內核放棄建立連接之前發送SYN包的數量。

# net.ipv4.tcp_tw_len= 1

net.ipv4.tcp_tw_reuse= 1
#開啟重用。允許將TIME-WAITsockets重新用於新的TCP連接。

net.ipv4.tcp_wmem= 8192 436600 873200
#TCP寫buffer,可參考的優化值:8192 436600 873200

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

net.ipv4.tcp_mem= 94500000 91500000 92700000
#同樣有3個值,意思是:
net.ipv4.tcp_mem[0]:低於此值,TCP沒有記憶體壓力。
net.ipv4.tcp_mem[1]:在此值下,進入記憶體壓力階段。
net.ipv4.tcp_mem[2]:高於此值,TCP拒絕分配socket。
#上述記憶體單位是頁,而不是位元組。可參考的優化值是:7864321048576 1572864

net.ipv4.tcp_max_orphans= 3276800
#系統中最多有多少個TCP套接字不被關聯到任何一個用戶文件句柄上。
#如果超過這個數字,連接將即刻被覆位並列印出警告信息。
#這個限制僅僅是為了防止簡單的DoS攻擊,不能過分依靠它或者人為地減小這個值,
#更應該增加這個值(如果增加了記憶體之後)。

net.ipv4.tcp_fin_timeout= 30
#如果套接字由本端要求關閉,這個參數決定了它保持在FIN-WAIT-2狀態的時間。對端可以出錯並永遠不關閉連接,甚至意外當機。預設值是60秒。2.2 內核的通常值是180秒,你可以按這個設置,但要記住的是,即使你的機器是一個輕載的WEB伺服器,也有因為大量的死套接字而記憶體溢出的風險,FIN-WAIT-2的危險性比FIN-WAIT-1要小,因為它最多只能吃掉1.5K記憶體,但是它們的生存期長些。

同時還涉及到一個TCP 擁塞演算法的問題,你可以用下麵的命令查看本機提供的擁塞演算法控制模塊:

sysctlnet.ipv4.tcp_available_congestion_control

對於幾種演算法的分析,詳情可以參考下:TCP擁塞控制演算法的優缺點、適用環境、性能分析,比如高延時可以試用hybla,中等延時可以試用htcp演算法等。

#如果想設置TCP 擁塞演算法為hybla
net.ipv4.tcp_congestion_control=hybla

#額外的,對於內核版高於於3.7.1的,我們可以開啟tcp_fastopen:
net.ipv4.tcp_fastopen= 3

IO事件分配機制

在Linux啟用高併發TCP連接,必須確認應用程式是否使用了合適的網路I/O技術和I/O事件分派機制。可用的I/O技術有同步I/O,非阻塞式同步I/O,以及非同步I/O。在高TCP併發的情形下,如果使用同步I/O,這會嚴重阻塞程式的運轉,除非為每個TCP連接的I/O創建一個線程。但是,過多的線程又會因系統對線程的調度造成巨大開銷。因此,在高TCP併發的情形下使用同步I/O是不可取的,這時可以考慮使用非阻塞式同步I/O或非同步I/O。非阻塞式同步I/O的技術包括使用select(),poll(),epoll等機制。非同步I/O的技術就是使用AIO。

從I/O事件分派機制來看,使用select()是不合適的,因為它所支持的併發連接數有限(通常在1024個以內)。如果考慮性能,poll()也是不合適的,儘管它可以支持的較高的TCP併發數,但是由於其採用“輪詢”機制,當併發數較高時,其運行效率相當低,並可能存在I/O事件分派不均,導致部分TCP連接上的I/O出現“饑餓”現象。而如果使用epoll或AIO,則沒有上述問題(早期Linux內核的AIO技術實現是通過在內核中為每個I/O請求創建一個線程來實現的,這種實現機制在高併發TCP連接的情形下使用其實也有嚴重的性能問題。但在最新的Linux內核中,AIO的實現已經得到改進)。

綜上所述,在開發支持高併發TCP連接的Linux應用程式時,應儘量使用epoll或AIO技術來實現併發的TCP連接上的I/O控制,這將為提升程式對高併發TCP連接的支持提供有效的I/O保證。

經過這樣的優化配置之後,伺服器的TCP併發處理能力會顯著提高。以上配置僅供參考,用於生產環境請根據自己的實際情況調整觀察再調整。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • NET特性類都有個特點類名+Attribute,繼承基類Attribute,我們看下微軟自帶的特性類:DescriptionAttribute namespace System.ComponentModel { // 摘要: // 指定屬性或事件的說明。 [AttributeUsage(Attrib ...
  • 什麼是單點登錄統一認證:假如某公司旗下有10個網站(比如各種管理網站:人事系統啊,財務系統啊,業績系統啊等),我是該公司一管理員或者用戶,按照傳統網站模式是這樣:我打開A網站 輸入賬號密碼 然後進入到A網站辦點事,辦完之後,我有需要到B網站去辦點事,這個時候又需要輸入賬號密碼,假如你還要到C網站辦點 ...
  • 接著 前面,前面的過程是普遍常用的依賴註入解析過程,我們正常都是在startup類中註入依賴服務,但是,筆者這周開發的時候遇到個問題,不同服務的生命周期不同,不能調用服務。舉個例子,AddDbContext註入資料庫上下文,生命周期預設是scoped,但是我有個需求註入的服務是單例的,因此我註入的單 ...
  • 0.背景 在開發項目的過程當中,生產環境與調試環境的配置肯定是不一樣的。拿個最簡單的例子來說,比如連接字元串這種東西,調試環境肯定是不能連接生產資料庫的。在之前的話,這種情況只能說是你 COPY 兩個同名的配置文件來進行處理。然後你在本地就使用本地的配置,生產環境就使用生產環境的配置文件,十分麻煩。 ...
  • 阻止併發下的產品超賣思路是利用redis串列處理數據,但又有高併發處理數據的能力 產品表(product) class Product { public int Id{get;set} //自增Id public string Name{get;set}//產品名稱 public int Numbe ...
  • 轉載一篇文章,很有用 (一)、企業站 搜狐: http://mirrors.sohu.com/ 網易: http://mirrors.163.com/ 阿裡雲: http://mirrors.aliyun.com/ 騰訊: http://android-mirror.bugly.qq.com:808 ...
  • 首先我們的使用的是linux的 centOS6 版本 安裝mysql: 1、查看有沒有安裝包 2、進行安裝mysql:一般我們在伺服器端安裝的都是服務端( mysql-server 或 mysql-devel) 或者你也可以安裝客戶端 運行後會進入安裝界面,一頓操作之後,安裝完成。 3、進行字元集和 ...
  • 軟體操作命令 1. 軟體包管理器: yum 2. 安裝軟體: yum install xxx 3. 卸載軟體: yum remove xxx 4. 搜索軟體: yum serach xxx 5. 清理緩存: yum clear packages 6. 列出已安裝: yum list 7. 軟體包: ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...