Saltstack 最大打開文件數問題之奇怪的 8192

来源:https://www.cnblogs.com/edisonfish/p/18090269
-Advertisement-
Play Games

哈嘍大家好,我是鹹魚。 今天分享一個在壓測過程中遇到的問題,當時排查這個問題費了我們好大的勁,所以我覺得有必要寫一篇文章來記錄一下。 問題出現 周末在進行壓測的時候,測試和開發的同事反映壓測有問題,請求打到 A 服務上被拒絕了。 我們登錄伺服器查看 A 服務的日誌,發現頻繁地報 Too many o ...


哈嘍大家好,我是鹹魚。

今天分享一個在壓測過程中遇到的問題,當時排查這個問題費了我們好大的勁,所以我覺得有必要寫一篇文章來記錄一下。

問題出現

周末在進行壓測的時候,測試和開發的同事反映壓測有問題,請求打到 A 服務上被拒絕了。

我們登錄伺服器查看 A 服務的日誌,發現頻繁地報 Too many open files 錯誤,可以看到壓測的時候該進程要處理大量的 socket,導致打開的文件描述符數量已經達到了操作系統允許的最大限制,因此無法再打開更多的文件。

java.io.IOException: Too many open files
	...

既然是系統資源相關的問題,我們先 ulimit -n 看一下系統中進程能夠使用的最大文件描述符是多少個:

[root@localhost ~]# ulimit -n 
100000

為了穩妥起見,我們還查看了 /etc/security/limits.conf 文件的內容:

[root@localhost ~]# cat /etc/security/limits.conf
*           soft    nofile          100000
*           hard    nofile          100000

可以看到系統限制進程能夠最多打開 100000 個文件(我們在伺服器初始化的時候設置的值)。但是壓測的量還沒上去,A 服務上的進程打開文件數就超過了 10 萬個嗎?

查看一下這個進程打開了多少個文件:

[root@localhost ~]# cat /proc/<該進程的 PID>/fd | wc -l
8295

我們發現該進程才打開了八千多個文件,遠遠沒有達到系統限制的 100000。

接著看下這個進程的文件描述符數量限制,通過 /proc/<Java 進程的 PID>/limits 文件來查看

[root@localhost ~]# cat /proc/<該進程的 PID>/limits
...
Max open files            8192               8192               files
...

奇怪,按理說每個進程的文件描述符使用限制應該是 100000,但是這裡卻顯示只有 8192,說明系統層面的資源限制在這個進程上沒有生效,而且這個 8192 是怎麼來的,為什麼是 8192 ?

我們重啟了一下這個服務,發現重啟之後該進程的資源限制生效了,Max open files 數量變成了 100000 !

# 重啟服務
[root@localhost ~]# sh spring-boot.sh restart

# 查看該進程的文件描述符數量限制
[root@localhost ~]# cat /proc/<該進程的 PID>/limits
...
Max open files            100000               100000               files
...

定位問題

發現了這個現象之後,我們接著排查了其他的服務,發現服務進程的 Max open files 數量都是 8192,而系統設置的卻是 100000。

如果我們一旦手動重啟服務,進程的 Max open files 數就變成了系統設置的 100000。

我們在初始化伺服器的時候,已經修改了進程的最大打開文件數為 100000,如果配置沒有生效,那也應該是系統的預設值 1024 ,而不是 8192。

就在一籌莫展的時候,我們註意到了一個細微差別:由於線上伺服器較多,平時我們都是通過 Saltstack 來管理服務(包括服務的啟動重啟停止),而今天是在終端上重啟服務的,所以會不會跟 Saltstack 相關?

然後我們為了驗證執行了下麵的步驟:

  1. 找到一臺伺服器,先查看了上面進程的最大打開文件數,發現是 8192。
  2. 手動重啟一下服務,發現進程的最大打開文件數變成 100000
  3. 我們在 salt-master 上遠程重啟這台服務,發現進程的最大打開文件數變成了 8192。

接著我們在 salt-master 上遠程執行 ulimit -a 命令

[root@salt-master ~]# salt <伺服器 ip> cmd.run 'ulimit -a'
...
open files                      (-n) 8192
...

排查到這裡,終於有點柳暗花明的感覺了,我們看一下這台伺服器上 salt-minion 進程的資源限制:

[root@localhost ~]# cat /proc/<salt-minion 進程的 PID>/limits
...
Max open files            8192                 8192                 files 
...

又因為 salt-minion 是通過 systemctl 來管理的,所以我們在這台伺服器上查看 salt-minion 的服務註冊文件:

[root@localhost ~]# cat /usr/lib/systemd/system/salt-minion.service 
[Unit]
...

[Service]
KillMode=process
Type=notify
NotifyAccess=all
LimitNOFILE=8192
ExecStart=/usr/bin/salt-minion

[Install]
...

果然,奇怪的 8192 出現在了這兩處地方!

關於 Linux 下 Ulimit 資源限制

首先,/etc/security/limits.conf 文件中的配置對於通過 PAM 認證登錄的用戶資源限制是有效的。

也就是說,登陸了系統的用戶,無論是互動式登錄還是非互動式登錄,其資源限制都會受到 limits.conf 中的配置影響。

但是,在 CentOS 7/RHEL 7 等系統中,預設採用 Systemd 作為 init 系統,取代了之前的 SysV init,對於 Systemd 啟動的服務(例如使用 systemctl 啟動的服務),limits.conf 中的配置對其資源限制是不生效的。

這是因為 Systemd 會忽略 limits.conf 中的設置,而是使用自己的資源管理機制。

這裡補充一下,在 CenOS 5/6 中,/etc/security/limits.conf/etc/security/limits.d 中的配置文件是為通過PAM登錄的用戶設置資源限制的。這些限制在用戶登錄時由PAM模塊載入並應用(什麼是 PAM ,你可以簡單理解為一般情況登陸了終端都會載入 PAM 模塊),因此僅在用戶會話期間生效。


所以就會出現某進程在機器重啟後資源限制設置與 /etc/security/limits.conflimits.d 下的文件不一致的問題,可能是因為進程是在系統啟動時自動啟動的,而不是通過用戶登錄而啟動的。因此不會受到 PAM 模塊載入的影響。在這種情況下,進程的資源限制可能受到系統級別的預設限制或其他配置文件的影響。

我們對某一臺 CentOS 6 的機器進行重啟後,發現上面設置了開機自啟動的進程的資源限制都發生了變化(變成了系統設置的預設值),一旦我們手動重啟,資源限制則設置成了跟 /etc/security/limits.conf 文件設置的一致

對於一些設置了開機自啟動的進程,如果在機器重啟後保持資源限制不發生變化,可以在進程的啟動腳本裡加上關於資源限制設置的命令,比如說 ulimit -SHn 10000

所以在 Systemd 中,可以通過在服務單元文件中設置 Limit* 選項來控制服務的資源限制,比如限制進程的最大打開文件數 LimitNOFILE 為 8192。

LimitNOFILE=8192

當我們通過 Salt-master 來管理遠程伺服器的時候(伺服器上面往往部署了 Salt-minion),即 Salt-master 發送命令給 Salt-minion 時,通常情況下,Salt-minion 會直接在自身進程中執行相應的操作。

如果是通過 Salt-minion 來啟動一個進程,這個進程則會繼承 Salt-minion 的資源限制配置。

這也就是為什麼通過 salt-minion 管理的進程的最大打開文件數都是 8192,因為 salt-minion 的最大打開文件數就是 8192。

解決問題

既然知道了這是關於 systemd services 的資源限制相關的問題,那就好解決了。

  • 針對所有的 service :

配置 systemd services 的資源限制可以在全局範圍內進行。這些配置文件分別位於 /etc/systemd/system.conf/etc/systemd/user.conf

system.conf 文件適用於系統級實例,而 user.conf 文件適用於用戶級實例。一般建議在 system.conf 中配置服務的資源限制,但如果在 /etc/systemd/system.conf 文件中修改配置,則需要重啟系統才能使更改生效。

此外,還可以通過在 /etc/systemd/system.conf.d//etc/systemd/user.conf.d/ 目錄中放置 .conf 文件進行配置。

需要註意的是,system.conf.d/*.conf 中的配置會覆蓋 system.conf 中的配置。

如果你打算修改所有通過 systemctl 管理的服務進程的資源限制(比如修改最大文件打開數量)

那可以修改/etc/systemd/system.conf

[root@localhost ~]# vim /etc/systemd/system.conf
DefaultLimitNOFILE=100000
  • 針對單個 service:

這次案例的解決方法就是要修改單個 service (即 salt-minion)的資源限制配置。

# 修改 salt-minion 的 service 文件,改成和系統一樣的資源限制配置
[root@localhost ~]# cat /usr/lib/systemd/system/salt-minion.service 
...
[Service]
LimitNOFILE=100000
...

修改完之後別忘了重啟。

[root@localhost ~]# systemctl daemon-reload

[root@localhost ~]# systemctl restart salt-minion.service 

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

-Advertisement-
Play Games
更多相關文章
  • Linq的學習 這裡繼續使用之前文章創建的學生類,首先簡單介紹一下linq的使用。 Student.cs public class Student { public int Id { get; set; } public int ClassId { get; set; } public string ...
  • 前言 從.Net Core 開始,.Net 平臺內置了一個輕量,易用的 IOC 的框架,供我們在應用程式中使用,社區內還有很多強大的第三方的依賴註入框架如: Autofac DryIOC Grace LightInject Lamar Stashbox Simple Injector 內置的依賴註入 ...
  • 新建項目 在建項目的時候要註意,選擇Windows 窗體應用(.NET Framework)或者wpf項目,然後打開 安裝包 在解決方案資源管理器中,選擇剛纔的項目名,滑鼠右鍵找到並打開管理NuGet包,然後在瀏覽選項卡裡,輸入一個Costura.Fody並查找,有就點安裝,安裝前需要註意選擇支持的 ...
  • TagProvider [LogProperties] 與 [LogPropertyIgnore] 如果用在DTO不存在任何問題,如果用在Domain實體上,可能有點混亂。 您可能不希望因日誌記錄問題而使您的域模型變得混亂。對於這種情況,可以使用[TagProvider]屬性來豐富日誌。 我們仍然使 ...
  • 概述:本指南詳細解釋了在C#中如何在創建控制項的線程以外的線程中訪問GUI。基礎功能使用`Control.Invoke`(WinForms)或`Dispatcher.Invoke`(WPF),高級功能則利用`SynchronizationContext`實現線程間通信,確保代碼清晰可讀。 在C#中,要 ...
  • 概述:.NET應用程式以管理員身份運行的方法包括修改清單文件、項目文件,或在運行時動態請求管理員許可權。清單文件和項目文件通過聲明UAC請求,而動態請求管理員許可權則在程式啟動時檢查並重新啟動。選擇適當的方法取決於項目需求和配置。 在.NET應用程式中強制以管理員身份運行,可以通過清單文件、項目文件或者 ...
  • Nginx的location匹配順序是Nginx配置中非常核心且重要的概念,它決定了Nginx如何處理進入伺服器的請求。理解location匹配順序不僅有助於優化Nginx的性能,還能確保網站或應用的正確運行。下麵將詳細闡述Nginx的location匹配順序,並通過實例加以說明。 Nginx lo ...
  • 來自chatGPT 在CentOS 7.9系統上安裝Docker,你可以遵循以下步驟: 更新你的系統:首先,確保你的系統是最新的。這可以通過運行下麵的命令來實現: sudo yum update 安裝必要的包:為了使得yum源支持https,你需要安裝幾個必要的包: sudo yum install ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...