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
  • PasteSpider是什麼? 一款使用.net編寫的開源的Linux容器部署助手,支持一鍵發佈,平滑升級,自動伸縮, Key-Value配置,項目網關,環境隔離,運行報表,差量升級,私有倉庫,集群部署,版本管理等! 30分鐘上手,讓開發也可以很容易的學會在linux上部署你得項目! [從需求角度介 ...
  • SQLSugar是什麼 **1. 輕量級ORM框架,專為.NET CORE開發人員設計,它提供了簡單、高效的方式來處理資料庫操作,使開發人員能夠更輕鬆地與資料庫進行交互 2. 簡化資料庫操作和數據訪問,允許開發人員在C#代碼中直接操作資料庫,而不需要編寫複雜的SQL語句 3. 支持多種資料庫,包括但 ...
  • 在C#中,經常會有一些耗時較長的CPU密集型運算,因為如果直接在UI線程執行這樣的運算就會出現UI不響應的問題。解決這類問題的主要途徑是使用多線程,啟動一個後臺線程,把運算操作放在這個後臺線程中完成。但是原生介面的線程操作有一些難度,如果要更進一步的去完成線程間的通訊就會難上加難。 因此,.NET類 ...
  • 一:背景 1. 講故事 前些天有位朋友在微信上丟了一個崩潰的dump給我,讓我幫忙看下為什麼出現了崩潰,在 Windows 的事件查看器上顯示的是經典的 訪問違例 ,即 c0000005 錯誤碼,不管怎麼說有dump就可以上windbg開幹了。 二:WinDbg 分析 1. 程式為誰崩潰了 在 Wi ...
  • CSharpe中的IO+NPOI+序列化 文件文件夾操作 學習一下常見的文件、文件夾的操作。 什麼是IO流? I:就是input O:就是output,故稱:輸入輸出流 將數據讀入記憶體或者記憶體輸出的過程。 常見的IO流操作,一般說的是[記憶體]與[磁碟]之間的輸入輸出。 作用 持久化數據,保證數據不再 ...
  • C#.NET與JAVA互通之MD5哈希V2024 配套視頻: 要點: 1.計算MD5時,SDK自帶的計算哈希(ComputeHash)方法,輸入輸出參數都是byte數組。就涉及到字元串轉byte數組轉換時,編碼選擇的問題。 2.輸入參數,字元串轉byte數組時,編碼雙方要統一,一般為:UTF-8。 ...
  • CodeWF.EventBus,一款靈活的事件匯流排庫,實現模塊間解耦通信。支持多種.NET項目類型,如WPF、WinForms、ASP.NET Core等。採用簡潔設計,輕鬆實現事件的發佈與訂閱。通過有序的消息處理,確保事件得到妥善處理。簡化您的代碼,提升系統可維護性。 ...
  • 一、基本的.NET框架概念 .NET框架是一個由微軟開發的軟體開發平臺,它提供了一個運行時環境(CLR - Common Language Runtime)和一套豐富的類庫(FCL - Framework Class Library)。CLR負責管理代碼的執行,而FCL則提供了大量預先編寫好的代碼, ...
  • 本章將和大家分享在ASP.NET Core中如何使用高級客戶端NEST來操作我們的Elasticsearch。 NEST是一個高級別的Elasticsearch .NET客戶端,它仍然非常接近原始Elasticsearch API的映射。所有的請求和響應都是通過類型來暴露的,這使得它非常適合快速上手 ...
  • 參考delphi的代碼更改為C# Delphi 檢測密碼強度 規則(仿 google) 仿 google 評分規則 一、密碼長度: 5 分: 小於等於 4 個字元 10 分: 5 到 7 字元 25 分: 大於等於 8 個字元 二、字母: 0 分: 沒有字母 10 分: 全都是小(大)寫字母 20 ...