LAMP (Linux + Apache + MySQL + PHP) 是經典 Web 架構,但預設配置往往無法榨乾硬件性能。本文從硬件、內核、Web 服務器、PHP、數據庫、架構六個維度,提供系統性優化指南與具體配置參數。
硬件層優化
| 組件 | 瓶頸特徵 | 優化方向 |
| CPU | PHP 計算密集、加密、壓縮 | 高主頻 > 多核;開啟 AES-NI、AVX2 |
| 內存 | Apache 進程、PHP 操作碼緩存、MySQL 緩衝池 | 盡量大 (64GB+),關閉 Swap 或設 swappiness=1 |
| 磁盤 | MySQL 數據/日誌、靜態文件、Session | NVMe SSD;RAID 10;noatime 掛載;分離數據/日誌盤 |
| 網絡 | 靜態資源傳輸、API 響應、CDN 回源 | 萬兆內網;啟用 BBR;CDN 邊緣緩存 |
磁盤調度優化
# 查看調度器
cat /sys/block/nvme0n1/queue/scheduler
# 設置為 none (NVMe) 或 mq-deadline (SSD)
echo none > /sys/block/nvme0n1/queue/scheduler
# 關閉訪問時間更新
# /etc/fstab
/dev/nvme0n1p1 / ext4 defaults,noatime,nodiratime 0 1
Linux 內核參數調優
# /etc/sysctl.d/99-lamp.conf
# TCP 連接佇列
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 65535
# 連接復用與快速回收
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 15
# 緩衝區擴大
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216
# 文件描述符
fs.file-max = 1000000
fs.nr_open = 1000000
# 內存管理
vm.swappiness = 1
vm.dirty_ratio = 15
vm.dirty_background_ratio = 5
# 生效
sysctl --system
Apache (httpd) 優化
MPM 選擇:Event > Worker > Prefork
# httpd.conf - Event MPM (推薦,支援 HTTP/2)
LoadModule mpm_event_module modules/mod_mpm_event.so
StartServers 4
MinSpareThreads 25
MaxSpareThreads 75
ThreadsPerChild 25
MaxRequestWorkers 400
MaxConnectionsPerChild 10000
ServerLimit 16
# 關鍵:關閉 KeepAlive 或降低超時 (高併發短連接)
KeepAlive Off
# 或
KeepAlive On
KeepAliveTimeout 2
MaxKeepAliveRequests 100
模組精簡
# 僅保留必要模組
LoadModule authz_core_module modules/mod_authz_core.so
LoadModule dir_module modules/mod_dir.so
LoadModule mime_module modules/mod_mime.so
LoadModule log_config_module modules/mod_log_config.so
LoadModule setenvif_module modules/mod_setenvif.so
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_fcgi_module modules/mod_proxy_fcgi.so # PHP-FPM
LoadModule rewrite_module modules/mod_rewrite.so
LoadModule headers_module modules/mod_headers.so
LoadModule deflate_module modules/mod_deflate.so
LoadModule expires_module modules/mod_expires.so
LoadModule http2_module modules/mod_http2.so
壓縮與緩存
# Gzip/Deflate
AddOutputFilterByType DEFLATE text/html text/css application/javascript application/json
DeflateCompressionLevel 6
# 靜態資源長期緩存
ExpiresActive On
ExpiresByType image/* "access plus 1 year"
ExpiresByType text/css "access plus 1 month"
ExpiresByType application/javascript "access plus 1 month"
# 安全頭
Header always set X-Content-Type-Options nosniff
Header always set X-Frame-Options DENY
Header always set Referrer-Policy strict-origin-when-cross-origin
PHP (PHP-FPM) 優化
OPcache 必開配置
; php.ini / php-fpm.d/opcache.ini
zend_extension=opcache.so
opcache.enable=1
opcache.enable_cli=1
opcache.memory_consumption=512
opcache.interned_strings_buffer=64
opcache.max_accelerated_files=20000
opcache.revalidate_freq=60 ; 生產環境 60s 或 0 (需重啟刷新)
opcache.validate_timestamps=1
opcache.fast_shutdown=1
opcache.save_comments=1
opcache.huge_code_pages=1 ; 需內核支援 huge pages
PHP-FPM 進程池配置
; www.conf
pm = dynamic
pm.max_children = 200 # 根據內存:總內存 / 單進程內存 (約 30-50MB)
pm.start_servers = 20
pm.min_spare_servers = 10
pm.max_spare_servers = 50
pm.max_requests = 1000 # 防止內存洩漏,定期回收
pm.status_path = /fpm-status
ping.path = /fpm-ping
; 慢日誌
request_slowlog_timeout = 5s
slowlog = /var/log/php-fpm/slow.log
; 安全
security.limit_extensions = .php
php_admin_value[disable_functions] = exec,passthru,shell_exec,system,proc_open,popen
php_admin_value[open_basedir] = /var/www/:/tmp/
MySQL (InnoDB) 核心參數
# /etc/my.cnf.d/innodb.cnf
[mysqld]
# 緩衝池 (專用機 70-80% 內存)
innodb_buffer_pool_size = 32G
innodb_buffer_pool_instances = 16
# 日誌
innodb_log_file_size = 2G
innodb_log_files_in_group = 2
innodb_log_buffer_size = 64M
innodb_flush_log_at_trx_commit = 1 # ACID;極致性能可設 2
# 並發
innodb_thread_concurrency = 0 # 0=自動
innodb_read_io_threads = 16
innodb_write_io_threads = 16
# 表空間
innodb_file_per_table = 1
innodb_open_files = 4000
# 連接
max_connections = 2000
thread_cache_size = 100
table_open_cache = 4000
# 查詢緩存 (MySQL 5.7+ 已廢棄,8.0 移除)
# query_cache_type = 0
# query_cache_size = 0
# 慢查詢
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 1
log_queries_not_using_indexes = 1
架構層優化:分層與分離
- 靜態資源分離:Nginx 反向代理靜態文件,Apache/PHP-FPM 只處理動態請求
- 數據庫讀寫分離:主庫寫、從庫讀,中間件 (ProxySQL/MaxScale) 路由
- 緩存層:Redis/Memcached 緩存熱點數據、Session、頁面片段
- 隊列異步:RabbitMQ/Redis Stream 處理郵件、導出、推送等耗時任務
- CDN 加速:靜態資源、API 緩存推送到邊緣節點
- 水平擴展:負載均衡 (LVS/HAProxy/Nginx) + 無狀態應用節點
監控與壓測工具鏈
| 類別 | 工具 | 用途 |
| 系統監控 | Prometheus + Grafana + Node Exporter | 全棧指標採集可視化 |
| 應用性能 | Xdebug + Webgrind / Blackfire / Tideways | PHP 代碼級性能分析 |
| 數據庫 | pt-query-digest / MySQL Explain / sys schema | 慢查詢分析、索引優化 |
| 壓力測試 | wrk / ab / locust / k6 / JMeter | 並發壓測、瓶頸定位 |
| 日誌分析 | ELK / Loki + Promtail | 集中式日誌檢索分析 |
壓測基準命令
# wrk 現代 HTTP 壓測
wrk -t8 -c200 -d60s --latency https://your.domain/api/endpoint
# ab 簡易測試
ab -n 10000 -c 100 -H "Accept: application/json" https://your.domain/
# 關注指標:QPS、P99 延遲、錯誤率、CPU/內存/磁盤/網絡飽和度
總結:優化優先級矩陣
| 優先級 | 動作 | 投入產出比 |
| P0 | 開啟 OPcache、MySQL 緩衝池、慢查詢日誌 | 極高 (分鐘級見效) |
| P1 | PHP-FPM 進程池、Apache MPM Event、Gzip/Expires | 高 |
| P2 | 內核參數、磁盤調度、Nginx 靜態代理 | 中高 |
| P3 | 讀寫分離、Redis 緩存、CDN | 中 (架構變更) |
| P4 | 水平擴展、隊列異步、微服務化 | 低 (長期投入) |
核心原則:測量 → 找到瓶頸 → 驗證假設 → 優化 → 複測。盲目調參不如一次 top + iostat + slow log 實在。