跳转到帖子
在手机APP中查看

一个更好的浏览方法。了解更多

PHP论坛人

主屏幕上的全屏APP,带有推送通知、徽章等。

在iOS和iPadOS上安装此APP
  1. 在Safari中轻敲分享图标
  2. 滚动菜单并轻敲添加到主屏幕
  3. 轻敲右上角的添加按钮。
在安卓上安装此APP
  1. 轻敲浏览器右上角的三个点菜单 (⋮) 。
  2. 轻敲添加到主屏幕安装APP
  3. 轻敲安装进行确认。

系統資源限制調校 Part 2

精选回复

系統資源限制調校 Part 2


**************************************************
之前Debian 13配置時,已做了 Part 1

現在LNMP設置完,接續 Part 2
**************************************************




前提:已完成 Part 1(基礎系統調校),LNMP 各服務已安裝並能正常啟動

目標環境:Debian 13

VPS規格:2 vCPU/2GB RAM

服務組合:MariaDB + Nginx + PHP-FPM 8.3


--------------------------
架構概念與調校邊界
--------------------------

為什麼需要兩層調校?

Linux的資源限制分為兩個獨立層次,兩者必須同時設定,缺一不可


層次:核心層(全域)
設定位置:/etc/sysctl.d/*.conf
控制範圍:整個作業系統的上限,是所有服務的天花板


層次:服務層(行程)
設定位置:systemd override.conf
控制範圍:單一服務的資源配額,不得超過核心層上限


常見誤區:只設定 /etc/security/limits.conf 對 systemd 管理的服務完全無效

MariaDB、Nginx、PHP-FPM 均由 systemd 啟動,行程資源限制必須透過各自的 override.conf 設定




systemd Override 機制說明

不直接修改套件提供的 .service 檔案,而是使用 override 目錄,原因如下:

套件更新時,系統不會覆蓋 override 目錄下的自訂設定

原始 .service 檔案仍保持乾淨,升級後可直接 diff 比較差異




systemd 讀取設定的優先順序

/etc/systemd/system/<service>.service.d/*.conf   優先於   /lib/systemd/system/<service>.service



override 檔案的設定會「疊加」而非全部取代原始設定

若需清空某個原始的清單型參數(例如 ExecStartPre),必須先以空值重置,再寫入新值

ExecStartPre=
ExecStartPre=/your/new/command



----------------------------------------
全域核心 sysctl 調校
----------------------------------------

為什麼使用獨立設定檔?

直接修改 /etc/sysctl.conf 有兩個風險:套件更新可能覆蓋它,且難以追蹤哪些設定從何而來

Debian 支援將獨立設定檔放置於 /etc/sysctl.d/ 目錄,是生產環境的最佳實踐


常見錯誤:將所有 sysctl 設定堆進 /etc/sysctl.conf,升級或排查問題時難以管理

建立 專用設定檔

vi /etc/sysctl.d/99-lnmp-optimization.conf

貼上以下內容

99-lnmp-optimization.conf.txt

儲存檔案並離開vi編輯器

按 Esc,輸入 :wq,按 Enter


----------------------------
立即生效
----------------------------

立即生效

sysctl --system






-------------------------
驗證是否已套用
-------------------------


預期輸出 fs.file-max = 2097152
sysctl fs.file-max



預期輸出:fs.nr_open = 2097152
sysctl fs.nr_open











------------------------------------------
服務級別限制調校 systemd Override
------------------------------------------

以下設定以 2 vCPU / 2GB RAM VPS 為基準

請務必依實際監控數據進行微調,勿照單全收





----------------------
MariaDB 資料庫
----------------------

建立目錄
mkdir -p /etc/systemd/system/mariadb.service.d/

編輯

vi /etc/systemd/system/mariadb.service.d/override.conf

貼入以下內容(檔案內已有部分設定,此為額外補充)

mariadb.service.d---override.conf.txt

儲存檔案並離開vi編輯器

按 Esc,輸入 :wq,按 Enter

-----------------------
Nginx 網頁伺服器
-----------------------

建立目錄
mkdir -p /etc/systemd/system/nginx.service.d/

編輯

vi /etc/systemd/system/nginx.service.d/override.conf

貼上以下內容

nginx.service.d---override.conf.txt

儲存檔案並離開vi編輯器

按 Esc,輸入 :wq,按 Enter

------------------------
PHP-FPM
------------------------

注意:PHP-FPM 的套件預設 .service 檔案通常已包含部分安全設定。
此 override 為額外疊加,不會覆蓋原有設定。
若有重複的鍵值,override 的值會優先生效。
建議執行 systemctl cat php8.3-fpm 先查看原始設定,確認無衝突。




建立目錄
mkdir -p /etc/systemd/system/php8.3-fpm.service.d/

編輯

vi /etc/systemd/system/php8.3-fpm.service.d/override.conf

貼上以下內容

php8.3-fpm.service.d---override.conf.txt

儲存檔案並離開vi編輯器

按 Esc,輸入 :wq,按 Enter


------------------------
套用、驗證與監控
------------------------

完成所有 override.conf 後,必須依序執行  以下步驟:


----------------------------
重新載入 systemd 配置
----------------------------

此步驟讓 systemd 讀取新增或修改的 override 檔案。每次修改 override.conf 後都必須執行,否則設定不會生效


重新載入

systemctl daemon-reload





--------------------------
重啟並驗證各服務
--------------------------

在重啟服務前,建議先驗證設定語法,確認無誤後再啟動,避免生產環境服務中斷。


-------------------------------
MariaDB
-------------------------------

停止服務  後驗證
systemctl stop mariadb



MariaDB  驗證設定語法
mariadbd --help --verbose > /dev/null



輸出說明:

無任何輸出 → 設定檔完全正確,可以啟動服務

顯示 [Warning] → 有警告,需確認是否影響運作

顯示 [ERROR] → 有錯誤,不可啟動服務,須先修正





確認無誤後再啟動
systemctl restart mariadb



查看狀態
systemctl status mariadb



------------------------------------
Nginx
------------------------------------

Nginx  驗證設定語法
nginx -t



重啟服務
systemctl restart nginx



查看狀態
systemctl status nginx




--------------------------------
PHP-FPM
--------------------------------


PHP-FPM  驗證設定語法
php-fpm8.3 -t



重啟服務
systemctl restart php8.3-fpm



查看狀態
systemctl status php8.3-fpm






--------------------------------
驗證資源限制是否真正生效
--------------------------------

查看 /proc/<PID>/limits 才是確認設定是否真正生效的唯一標準,不應只看設定檔本身

驗證各服務的 Max open files 應顯示為 65535



MariaDB 應顯示為 65535

cat /proc/$(pgrep -o mariadbd)/limits | grep "Max open files"




Nginx (取 master process PID) 應顯示為 65535

cat /proc/$(pgrep -o nginx)/limits | grep "Max open files"




PHP-FPM (取 master process PID) 應顯示為 65535

cat /proc/$(pgrep -o php-fpm)/limits | grep "Max open files"




----------------------------------------
使用 systemd 指令查看詳細屬性
----------------------------------------

systemctl show mariadb | grep -E "(LimitNOFILE|MemoryMax|CPUQuota)"



systemctl show nginx | grep -E "(LimitNOFILE|MemoryMax|CPUQuota)"



systemctl show php8.3-fpm | grep -E "(LimitNOFILE|MemoryMax|CPUQuota)"



------------------------------------
查看核心檔案描述符使用狀況
------------------------------------

查看

cat /proc/sys/fs/file-nr


輸出格式:已使用數      未使用數      最大值







------------------
安裝監控工具
------------------

安裝監控工具
apt update -y && apt install -y htop iotop iftop nethogs lsof sysstat


即時查看 CPU / 記憶體
htop


監控磁碟 I/O(按 o 排序)
iotop

即時網路流量(需指定網卡,如 eth0)
iftop -i eth0


依行程分類網路流量
nethogs eth0


計算特定行程目前開啟的檔案數
lsof -p <PID> | wc -l


查看 nginx master process 開啟了多少檔案
lsof -p $(pgrep -o nginx) 2>/dev/null | wc -l



歷史效能數據收集
sysstat




進階建議:生產環境應考慮部署 Prometheus + node_exporter 或 Netdata,實現長期監控與告警,而非僅依賴即時工具








----------------------
設定日誌輪替
----------------------

避免日誌檔案無限增長而佔滿磁碟空間,這是生產環境容易忽略的維運重點



建立
vi /etc/logrotate.d/lnmp


貼入以下內容



/var/log/mysql/*.log
/var/log/nginx/*.log
/var/log/php8.3-fpm.log {
    daily
    rotate 30

    missingok
    notifempty

    compress
    delaycompress

    dateext
    dateformat -%Y%m%d

    create 0640 root adm
    su root adm

    sharedscripts

    postrotate
        [ -s /run/nginx.pid ] && kill -USR1 $(cat /run/nginx.pid) 2>/dev/null || true

        if [ -x /usr/bin/mariadb-admin ]; then
            /usr/bin/mariadb-admin flush-logs >/dev/null 2>&1 || true
        fi
    endscript
}



儲存檔案並離開vi編輯器
按 Esc,輸入 :wq,按 Enter




-------------------------
測試 logrotate 設定
-------------------------

-d 為 debug mode 模式,不會實際輪替,僅顯示操作預覽,確認設定無誤


logrotate -d /etc/logrotate.d/lnmp


確認輸出無錯誤後,設定即完成







補充說明:

rotate 30 表示保留 30份(天),視磁碟容量調整

delaycompress 讓昨天的日誌今天才壓縮,方便查看最近的未壓縮日誌



----------------------------
重開機驗證
----------------------------

重開機
reboot


重開機後,確認各服務自動啟動且資源限制仍正確套用


確認服務狀態,每個服務都應顯示 active (running)

systemctl status mariadb



systemctl status nginx



systemctl status php8.3-fpm







重新驗證資源限制(值應為 65535)

cat /proc/$(pgrep -o mariadbd)/limits | grep "Max open files"


cat /proc/$(pgrep -o nginx)/limits | grep "Max open files"


cat /proc/$(pgrep -o php-fpm)/limits | grep "Max open files"





查看 systemd 實際讀取結果(確認 override 有被載入)

systemctl cat mariadb


systemctl cat nginx


systemctl cat php8.3-fpm






查看 MemoryMax

systemctl show mariadb | grep MemoryMax








------------------------------------------
VPS 2 vCPU/2GB RAM 記憶體配置建議
------------------------------------------

MariaDB
1024 MB
記憶體大戶,innodb_buffer_pool_size 建議 768M


PHP-FPM
768 MB
依 worker 數量與 memory_limit 決定


Nginx
256 MB
極低,事件驅動架構


Redis
128 MB
用於 Session 或頁面快取

系統及其他
約 384 MB
OS 核心、SSH、Cron 等

合計 約 2560 MB


重要提醒:systemd 的 MemoryMax 設定值總和可以略高於實體記憶體(因為服務不會同時達到尖峰),
但若所有服務同時達到峰值,仍可能觸發 OOM Killer 強制終止行程。請務必根據實際監控數據進行微調。

建議執行壓力測試(如 ApacheBench、wrk)後,觀察 free -h 與 vmstat 1 30 的輸出,再決定最終配置。




---------------
常見問題
---------------

Q1:修改了 /etc/security/limits.conf,重啟 MariaDB 後查看 /proc/<PID>/limits 仍未改變?

因為 MariaDB 由 systemd 管理,啟動時不會讀取 limits.conf

必須在對應的 systemd override.conf 中設定 LimitNOFILE,並在修改後執行 systemctl daemon-reload 再重啟服務




Q2:如何快速確認系統或特定服務開啟了多少檔案?

系統整體(已使用 / 未使用 / 總上限)
cat /proc/sys/fs/file-nr


特定服務(以 nginx master process 為例)
lsof -p $(pgrep -o nginx) 2>/dev/null | wc -l




Q3:修改 systemd override 並 daemon-reload 重啟後,服務無法啟動?

查看詳細錯誤日誌
journalctl -u mariadb -xe --no-pager


確認服務狀態
systemctl status mariadb


驗證 systemd 讀取到的限制值
systemctl show mariadb | grep -i "limitnofile\|memory"


常見原因:

override.conf 語法錯誤(如多餘空格、缺少區段標頭 [Service])

設定了不支援的參數名稱

MemoryMax 設定過小,服務啟動即因超限被終止

ProtectSystem=full 與服務寫入路徑衝突(改用 ProtectSystem=strict + ReadWritePaths=)

MemoryDenyWriteExecute=true 與 OPcache JIT 衝突(PHP-FPM)





Q4:CPUQuota 的百分比是相對於什麼?

CPUQuota=80% 表示允許使用最多 80% 的  單顆CPU核心  時間。

若 VPS 有2顆 vCPU,則 CPUQuota=160% 才等於充分利用兩顆核心。

請依 VPS 實際核心數調整。





Q5:MemoryMax 和 MemoryHigh 有什麼差別?

參數:MemoryHigh
行為:軟性高水位。超過後系統積極嘗試回收該服務記憶體,但  不會 強制終止服務


參數:MemoryMax
行為:絕對硬上限。超過後行程會被 OOM Killer 立即終止


建議將 MemoryHigh 設為 MemoryMax 的 80~85%,讓系統有空間提前介入,避免直接觸發 OOM





Q6:MariaDB 無法啟動

查看最近 50 行錯誤日誌
journalctl -u mariadb -n 50


驗證設定檔語法
mariadbd --help --verbose > /dev/null


若調整 innodb_log_file_size 後發生錯誤,刪除舊 redo log 讓 MariaDB 重建

systemctl stop mariadb

rm /var/lib/mysql/ib_logfile*

systemctl start mariadb


檢查資料目錄權限
ls -la /var/lib/mysql

chown -R mariadb:mariadb /var/lib/mysql







Q7:Too many connections 錯誤

暫時調高連線數(立即生效,重啟後失效)
mariadb -e "SET GLOBAL max_connections = 150;"


查看目前連線狀況
mariadb -e "SHOW PROCESSLIST;"


終止閒置過久的連線
mariadb -e "SHOW PROCESSLIST;" | grep Sleep | awk '{print "KILL "$1";"}' | mariadb


永久調整請修改 /etc/mysql/mariadb.conf.d/50-server.cnf 中的 max_connections 後重啟服務

提示:應用端建議實作連線池(如 PHP PDO persistent connection),可大幅降低連線開銷






Q8:磁碟空間持續增加

檢查磁碟使用
df -h

du -sh /var/lib/mysql/


檢查 Binary Log 使用狀況
mariadb -e "SHOW BINARY LOGS;"


手動清除 7 天前的 Binary Log
mariadb -e "PURGE BINARY LOGS BEFORE DATE_SUB(NOW(), INTERVAL 7 DAY);"


檢查日誌大小
ls -lh /var/log/mysql/


若完全不需要主從複製,可在 50-server.cnf 中將 log-bin 相關行全部註解掉






Q9:innodb_buffer_pool_size 設定後發生 OOM

檢查記憶體使用
free -h

top -o %MEM


2GB 總記憶體建議 innodb_buffer_pool_size = 768M,並為系統及其他服務保留至少 512 MB。

若系統頻繁使用 Swap,應考慮升級記憶體或降低 buffer pool 大小。






Q10:設定檔改了但未生效

顯示目前生效的所有設定
mariadbd --print-defaults

改為這樣,比較好讀
mariadbd --print-defaults 2>/dev/null | tr ' ' '\n' | grep '^--'



找出所有載入的設定檔路徑
mariadbd --help --verbose 2>/dev/null | grep -A 1 "Default options"


確認特定參數值
mariadb -e "SHOW VARIABLES LIKE 'innodb_buffer_pool_size';"


重新載入並重啟
systemctl daemon-reload

systemctl restart mariadb




Q11:PHP-FPM 啟動後 worker 被 OOM Killer 終止


查看 OOM Killer 記錄
dmesg | grep -i "oom\|killed"

journalctl -k | grep -i "oom\|killed"




調整策略:

1. 降低 pm.max_children(PHP-FPM pool 設定)

2. 降低 php.ini 的 memory_limit(如 128M → 96M)

3. 提高 systemd MemoryMax(前提是整體記憶體配置允許)




Q12:如何確認 override.conf 的設定有被正確讀取(而非使用舊設定)?

查看 systemd 實際讀取到的完整設定(含 override 疊加後的結果)

systemctl cat mariadb

systemctl cat nginx

systemctl cat php8.3-fpm


輸出最後一段即為你的 override.conf 內容,確認存在且數值正確即可

本帖最后于,由Jack编辑

创建帐户或登录后发表意见

帐户

导航

搜索

搜索

配置浏览器推送通知

Chrome (安卓)
  1. 轻敲地址栏旁的锁形图标。
  2. 轻敲权限 → 通知。
  3. 调整你的偏好。
Chrome (台式电脑)
  1. 点击地址栏中的挂锁图标。
  2. 选择网站设置。
  3. 找到通知选项并调整你的偏好。