開始之前:前置條件與閱讀路徑
本手冊說明 UnoPim 在 AWS Lightsail 上效能不佳的根本原因,並逐層列出需要修改的設定檔、修改原因、預期效益,以及社群記錄的常見問題。適合已完成基礎安裝、需要調整效能的工程師。
AWS Lightsail 本質是固定價格折扣的 EC2 t3/m7i-flex 系列,價格固定、配置簡單,但有一個關鍵特性需要了解:CPU burst credit 制度。 當你 CPU 使用率長時間超過 baseline(通常是 5%-20%),instance 會從「綠燈」進入「黃燈」, 然後 burst capacity 用完後降頻到 baseline 的速度。許多人抱怨 Lightsail「莫名其妙就變慢」, 九成是踩到這條線。
UnoPim 執行 Laravel 12,依賴 MySQL 8、Elasticsearch 8 與 Redis。Magic AI / AI Agent 模組另需額外記憶體。最低建議規格為 2 GB RAM;正式環境建議從 4 GB 起跳。$3.5/月的 512 MB 規格不足以執行 UnoPim。
本手冊的閱讀路徑
第一次自架 / 對 Linux 還不熟:請依照 序章 → 02 → 03 → 04 → 10 順序,先把站架起來,再回頭調校。
已經有站,但很慢:直接跳到 05(OPcache)→ 06(PHP-FPM)→ 08(MySQL)→ 09(Redis),這四個是最大 CP 值。
想榨乾 Lightsail:把 04 到 14 全部做完,最後接 CloudFront。
10 萬筆以上商品的真實用戶:直接跳到 11 章 Octane 與 17 章的選型討論。
UnoPim 是什麼?為什麼會慢?
UnoPim 是 Webkul 在 2024 年釋出的開源 PIM(Product Information Management, 商品資訊管理系統),架構在 Laravel 12 + Vue.js 之上。它定位為 Akeneo PIM Community Edition 的替代方案。Akeneo 從 2023 年起 CE 版已停止新增功能, 預定 2026 年 9 月停止支援。
UnoPim 的技術棧長這樣
| 組件 | 版本需求 | 角色 |
|---|---|---|
| PHP | 8.3+ | 應用層執行環境,需要 calendar / curl / intl / mbstring / openssl / pdo_mysql / tokenizer 等延伸模組 |
| Laravel | 12.x | 主框架,內建 Octane / Passport / Sanctum / AI 套件 |
| MySQL | 8.0.32+ | 主資料庫;商品 / attribute / family / channel / locale 都在這 |
| Elasticsearch | 8.17+ | 商品搜尋引擎;大型 catalog 建議安裝 |
| Redis | 建議 7.x | Cache + Session + Queue(正式環境必要) |
| Node.js | 20 LTS+ | 編譯前端資產(Vite) |
| Composer | 2.5+ | PHP 套件管理 |
| Web Server | Nginx / Apache2 | 本手冊全程使用 Nginx |
UnoPim「預設安裝就會很慢」的五個原因
根據 Webkul 自己的文件、Packagist 上的 composer.json 以及 GitHub issue 區的記錄, UnoPim 在「composer create-project + php artisan serve」 這條最簡單的安裝路徑完成後,預設狀態為「開發環境」設定。以下五個地方的預設值在正式環境中會造成明顯的效能問題:
APP_DEBUG=true 預設開啟,每個 request 都會載入完整 stack trace 與 telescope-like 偵錯資訊。
CACHE_DRIVER=file / SESSION_DRIVER=file:預設使用檔案系統。Lightsail 的 SSD 雖為 NVMe,存取速度仍比 Redis 慢兩個數量級。
QUEUE_CONNECTION=sync,意思是 import / export / AI agent / webhook 全部「同步阻塞」執行;用戶按下匯入按鈕後,瀏覽器會卡到天荒地老。
OPcache 沒設定,每個 PHP request 都要重新 parse compile 一次(Laravel 12 啟動約 800-1200 個檔案)。
沒有 config:cache / route:cache,Laravel 每個 request 都重新解析 60+ 個 config 檔。
這五件事如果你都不做,一台 4 GB Lightsail 大概每秒只能處理 5-8 個 request。 完成調校後,同一台機器可處理 80-150 RPS,差距達 15-20 倍。本手冊逐章說明各項調校的具體步驟。
- UnoPim 官方宣稱可承載商品數
- 10M+
- 完整調校後吞吐量提升倍率
- 15-20×
- 推薦最低 RAM(小流量站)
- 2GB
- 建議的 Lightsail正式環境月費
- $24/mo
Lightsail 規格選擇指南
下表依使用情境列出 UnoPim 的 Lightsail 規格建議,整理自 Laravel 部署實務、AWS re:Post 討論及 Webkul 官方文件。規格不足時,後續調校無法有效改善效能。
| 用途情境 | 規格 | 月費 | 備註 |
|---|---|---|---|
| 純測試 / 給老闆看 Demo | 2 vCPU · 2 GB RAM · 60 GB SSD | $12 | 商品 < 1000、無 Elasticsearch、無 Magic AI |
| 正式小流量站 (1-5 萬商品) | 2 vCPU · 4 GB RAM · 80 GB SSD | $24 | 本手冊預設規格;Elasticsearch 跑同一台 |
| 中等流量 (5-20 萬商品) | 2 vCPU · 8 GB RAM · 160 GB SSD | $44 | Elasticsearch 需要至少 1.5 GB heap |
| 高負載 (20-100 萬商品) | 4 vCPU · 16 GB RAM · 320 GB SSD | $84 | 已接近 Lightsail 天花板,可考慮拆 Elasticsearch 出去 |
| 百萬商品以上 | 遷移到 EC2 | — | Lightsail 沒有 auto-scaling,CPU burst 限制會殺死你 |
建立 instance 前的三項設定
① Blueprint:選「OS Only · Ubuntu 24.04 LTS」
LAMP/LEMP/Bitnami 預配 image 不適用於本手冊。Bitnami 將 PHP / MySQL / Nginx 安裝於 /opt/bitnami/,並在每次開機時以 memory.conf 覆寫 PHP-FPM 設定, 這是 AWS re:Post 上反覆記錄的問題。從 Ubuntu 24.04 OS-only image 開始,所有設定由操作者完整掌控,升級與除錯路徑較為清晰。
② Plan:正式環境建議 4 GB 起跳
Elasticsearch 8 預設需要 1 GB JVM heap、MySQL 8 至少 512 MB、 PHP-FPM 4 個 worker × 80 MB = 320 MB、Redis 256 MB、OS 本身 300 MB, 合計約 2.4 GB。npm run build 編譯前端資產時另需 1-2 GB 瞬間記憶體, 2 GB 規格的 Lightsail 在此步驟容易觸發 OOM killed。
③ Networking:設定 Static IP 與 Snapshot
Lightsail instance 重開後 public IP 會變更。在 Networking 頁籤建立 Static IP 並 attach, attach 至運行中的 instance 時不另收費。建議同時啟用每日自動 snapshot,月費增加約 $2。
定價的隱藏成本
Lightsail 月費看起來很便宜,但有些東西不在 $24/月之內:
Data Transfer 超量:4 GB plan 含 4 TB 流出;超過後每 GB $0.09。
CloudFront CDN Distribution:免費版有 50 GB/月 + 200 萬 requests,超過後另計。
Managed Database:若拆 MySQL 出去用 Lightsail Managed Database,最便宜 $15/月。
Load Balancer:$18/月,只有要做 multi-instance 才需要。
Block Storage:若 80 GB 不夠用,額外掛 disk 每 GB/月 $0.10。
從 0 開始:環境安裝逐步說明
以下步驟將 UnoPim 安裝至已建立的 Lightsail instance(Ubuntu 24.04 OS-only)。完整流程約需 30-45 分鐘。每段指令前有說明,建議確認理解後再執行。
連線到你的 instance
在 Lightsail 的 Instance 頁面找到「Connect using SSH」按鈕,會打開瀏覽器版的 terminal。 但我們建議下載 SSH key(在 Account > SSH keys 下載 default key 的 .pem 檔), 然後在你自己的電腦上連線:
# 給金鑰正確權限(macOS / Linux)
chmod 400 ~/Downloads/LightsailDefaultKey-ap-northeast-1.pem
# 連線(把 IP 換成你的 static IP)
ssh -i ~/Downloads/LightsailDefaultKey-ap-northeast-1.pem ubuntu@13.230.XXX.XXX
# Windows 用戶請用 PuTTY 並把 .pem 轉成 .ppk,
# 或用 Windows Terminal + OpenSSH(內建於 Win10/11)。更新系統並裝基礎工具
# 更新 package list 與已安裝套件
sudo apt update && sudo apt upgrade -y
# 裝基本工具(curl / git / unzip / 等)
sudo apt install -y curl git unzip software-properties-common \
ca-certificates gnupg lsb-release ufw htop tmux \
build-essential pkg-config安裝 PHP 8.3 與所有延伸模組
Ubuntu 24.04 預設 PHP 版本為 8.3,符合 UnoPim 的需求,不需要加 ondrej PPA。 但若你跑 22.04,請先 sudo add-apt-repository ppa:ondrej/php。
sudo apt install -y \
php8.3 php8.3-fpm php8.3-cli \
php8.3-mysql php8.3-pgsql \
php8.3-curl php8.3-gd php8.3-mbstring \
php8.3-xml php8.3-zip php8.3-bcmath \
php8.3-intl php8.3-soap php8.3-readline \
php8.3-tokenizer php8.3-imap php8.3-opcache \
php8.3-redis php8.3-imagick \
php8.3-calendar
# 確認版本
php -v
# 應該看到 PHP 8.3.x
# 確認 PHP-FPM 在跑
sudo systemctl status php8.3-fpm安裝 Composer 2 與 Node.js 20
# Composer
curl -sS https://getcomposer.org/installer | php
sudo mv composer.phar /usr/local/bin/composer
composer --version
# Node.js 20 LTS(透過 NodeSource)
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt install -y nodejs
node -v # 應該是 v20.x
npm -v安裝 MySQL 8、Redis 與 Nginx
sudo apt install -y mysql-server-8.0 redis-server nginx
# 啟動並設為開機自動執行
sudo systemctl enable --now mysql redis-server nginx
# 跑 MySQL 安全設定(設 root 密碼、移除測試資料庫等)
sudo mysql_secure_installation建立 UnoPim 的資料庫
sudo mysql -u root -p
# 進入 MySQL prompt 後依序執行:
CREATE DATABASE unopim CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'unopim'@'localhost' IDENTIFIED BY '你的安全密碼';
GRANT ALL PRIVILEGES ON unopim.* TO 'unopim'@'localhost';
FLUSH PRIVILEGES;
EXIT;安裝 Elasticsearch 8(選擇性,但建議)
# 匯入 Elastic 的 GPG key
wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | \
sudo gpg --dearmor -o /usr/share/keyrings/elastic.gpg
# 加入 Elastic 8.x 套件庫
echo "deb [signed-by=/usr/share/keyrings/elastic.gpg] https://artifacts.elastic.co/packages/8.x/apt stable main" | \
sudo tee /etc/apt/sources.list.d/elastic-8.x.list
sudo apt update && sudo apt install -y elasticsearch
# 把 ES heap 限制為 1 GB(Lightsail 4GB 規格建議)
sudo tee /etc/elasticsearch/jvm.options.d/heap.options << EOF
-Xms1g
-Xmx1g
EOF
sudo systemctl enable --now elasticsearch下載並安裝 UnoPim
# 建立 web 根目錄
sudo mkdir -p /var/www
cd /var/www
# 用 composer 建立專案(這一步要 5-15 分鐘)
sudo composer create-project unopim/unopim --no-interaction
# 改擁有者給 www-data,這是 PHP-FPM 跟 Nginx 的執行身份
sudo chown -R www-data:www-data /var/www/unopim
sudo chmod -R 755 /var/www/unopim
sudo chmod -R 775 /var/www/unopim/storage
sudo chmod -R 775 /var/www/unopim/bootstrap/cache
cd /var/www/unopim
# 編輯 .env 設好資料庫連線
sudo nano .env在 .env 裡至少要設定:
APP_NAME=UnoPim
APP_ENV=production
APP_DEBUG=false
APP_URL=https://pim.yourdomain.com
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=unopim
DB_USERNAME=unopim
DB_PASSWORD=你剛剛設的密碼
# --- 這四行是效能關鍵 ---
CACHE_DRIVER=redis
SESSION_DRIVER=redis
QUEUE_CONNECTION=redis
BROADCAST_DRIVER=redis
REDIS_HOST=127.0.0.1
REDIS_PORT=6379
ELASTICSEARCH_HOST=127.0.0.1
ELASTICSEARCH_PORT=9200# 跑安裝指令(建表、塞種子資料、建立管理員帳號)
sudo -u www-data php artisan unopim:install
# 建前端資產
sudo -u www-data npm install
sudo -u www-data npm run build作業系統層:Swap 與 Kernel
調校 PHP / Nginx / MySQL 之前,先處理作業系統層。Lightsail 預設沒有 swap,記憶體耗盡時 OOM killer 會終止 process,MySQL 或 Elasticsearch 通常最先受影響。
建立 4 GB Swap File
Swap 比實體記憶體慢一個數量級,但可避免 OOM 直接終止 process。依 Adrian Rubico 的 Lightsail 調校建議:RAM 小於 2 GB 時,swap 建議為 RAM 的兩倍;超過 2 GB 後,額外分配 2-4 GB 已足夠。
# 看當前有沒有 swap
free -h
# 建立一個 4GB 的 swap file
sudo fallocate -l 4G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
# 寫入 fstab 讓重開機後自動啟用
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
# 確認
free -h調整 swappiness
Ubuntu 預設 vm.swappiness=60,表示記憶體使用率達 40% 時即開始使用 swap。對 server 而言此值偏高,建議調低至 10,優先使用實體記憶體,僅在記憶體不足時才使用 swap。
# 即時生效
sudo sysctl vm.swappiness=10
# 寫入永久設定
sudo tee -a /etc/sysctl.conf << EOF
# --- Performance tuning for Laravel ---
vm.swappiness=10
vm.vfs_cache_pressure=50
net.core.somaxconn=4096
net.ipv4.tcp_max_syn_backlog=4096
net.ipv4.ip_local_port_range=10000 65535
fs.file-max=2097152
EOF
sudo sysctl -p提高 file descriptor 上限
高並發環境下,Nginx + PHP-FPM 容易耗盡預設的 1024 個 file descriptor。 我們需要把它調高。
sudo tee -a /etc/security/limits.conf << EOF
www-data soft nofile 65535
www-data hard nofile 65535
root soft nofile 65535
root hard nofile 65535
EOF
# 同時加進 systemd 限制
sudo mkdir -p /etc/systemd/system/php8.3-fpm.service.d
sudo tee /etc/systemd/system/php8.3-fpm.service.d/limits.conf << EOF
[Service]
LimitNOFILE=65535
EOF
sudo systemctl daemon-reloadPHP 8.3 + OPcache 設定
OPcache 是 PHP 內建的 opcode 快取。它將 PHP 編譯後的 bytecode 存放於記憶體,後續 request 直接讀取,不需重新 parse。依官方文件,啟用 OPcache 可大幅降低每個 request 的 CPU 消耗與回應時間,是 Laravel 正式環境的基本配置。
編輯 PHP-FPM 的 php.ini
sudo nano /etc/php/8.3/fpm/php.ini找到並修改以下參數(其中 opcache.* 區段是重點):
; ===== 基本記憶體與執行時間 =====
memory_limit = 512M
upload_max_filesize = 128M
post_max_size = 128M
max_execution_time = 300
max_input_vars = 5000
; ===== OPcache(效能關鍵) =====
opcache.enable = 1
opcache.enable_cli = 1
opcache.memory_consumption = 256
opcache.interned_strings_buffer = 32
opcache.max_accelerated_files = 20000
opcache.validate_timestamps = 0 ; 正式環境設 0
opcache.save_comments = 1 ; Laravel 註解驅動的功能需要
opcache.fast_shutdown = 1
opcache.jit_buffer_size = 128M
opcache.jit = tracing
; ===== Realpath cache =====
realpath_cache_size = 4096K
realpath_cache_ttl = 600同步設定 CLI 版本的 php.ini
php artisan 跑的是 CLI 版的 PHP,與 PHP-FPM 是兩份獨立的設定檔。 把同樣的調整套到 CLI:
sudo nano /etc/php/8.3/cli/php.ini
# 同樣的 memory_limit、opcache.* 都加進去
# 重啟 PHP-FPM
sudo systemctl restart php8.3-fpm
# 確認 OPcache 真的啟用了
php -i | grep "opcache.enable"
# 應該看到 opcache.enable => On => On- 啟用 OPcache 後平均 request 加速
- 3-5×
- 建議 opcachememory consumption
- 256MB
- max_accelerated_files(Laravel 約 9000 檔)
- 20K
- PHP 8 啟用後計算密集型 +15-20%
- JIT
PHP-FPM Pool 進程調校
PHP-FPM 的 worker pool 設定決定 server 同時處理的最大 request 數。worker 數量不足會導致請求排隊;設定過多則記憶體耗盡。下表為 4 GB Lightsail 的建議值。
編輯 www.conf
sudo nano /etc/php/8.3/fpm/pool.d/www.conf; ===== Pool 進程管理(4GB Lightsail 建議值) =====
user = www-data
group = www-data
listen = /run/php/php8.3-fpm.sock
listen.owner = www-data
listen.group = www-data
; 動態進程管理 — 對於變動流量最合適
pm = dynamic
pm.max_children = 20 ; 同時最多 20 個 worker
pm.start_servers = 4 ; 開機時起 4 個
pm.min_spare_servers = 2 ; 閒置時保留 2 個
pm.max_spare_servers = 8 ; 閒置時最多 8 個
pm.max_requests = 500 ; 處理 500 個 request 後重啟(防記憶體洩漏)
; ===== 慢請求 log =====
request_slowlog_timeout = 5s
slowlog = /var/log/php-fpm/slow.log
; ===== 狀態端點(給 monitoring 用) =====
pm.status_path = /fpm-status
ping.path = /fpm-ping那個 pm.max_children 的數字怎麼算?
這是 PHP-FPM 調校最常被問的問題。公式很簡單:
pm.max_children = (總記憶體 - 系統保留 - MySQL - Redis - ES) ÷ 單個 worker 平均記憶體
4 GB Lightsail 範例:
總記憶體 = 4096 MB
系統保留 = 400 MB
MySQL 8 = 800 MB
Redis = 256 MB
Elasticsearch = 1024 MB
→ 給 PHP-FPM = 1616 MB
單個 Laravel worker ≈ 80 MB
→ pm.max_children ≈ 1616 / 80 = 20想知道你的 worker 平均吃多少記憶體?跑這條:
ps -ylC php-fpm8.3 --sort:rss | awk '!/RSS/ { s+=$8 } END { printf "%d KB total / %d procs\n", s, NR-1 }'重啟並確認
sudo mkdir -p /var/log/php-fpm
sudo chown www-data:www-data /var/log/php-fpm
sudo php-fpm8.3 -t # 檢查設定有沒有錯
sudo systemctl restart php8.3-fpm
sudo systemctl status php8.3-fpmNginx 設定優化
AWS 建議在 Lightsail 上以 Nginx/PHP-FPM 取代 Apache,因為分離的 process 模型效能較高。目標設定:Nginx 處理所有靜態檔案及 response 壓縮,PHP request 透過 Unix socket 轉交給 PHP-FPM。
編輯 nginx.conf 的全域參數
sudo nano /etc/nginx/nginx.confuser www-data;
worker_processes auto;
worker_rlimit_nofile 65535;
pid /run/nginx.pid;
events {
worker_connections 4096;
multi_accept on;
use epoll;
}
http {
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
keepalive_requests 1000;
types_hash_max_size 2048;
server_tokens off;
client_max_body_size 128M;
client_body_buffer_size 256k;
client_body_timeout 60;
# ===== Gzip 壓縮 =====
gzip on;
gzip_vary on;
gzip_comp_level 6;
gzip_min_length 1000;
gzip_types text/plain text/css text/xml application/json
application/javascript application/xml+rss
application/atom+xml image/svg+xml;
# ===== FastCGI 快取 =====
fastcgi_cache_path /var/cache/nginx levels=1:2
keys_zone=UNOPIM_CACHE:100m max_size=1g inactive=60m
use_temp_path=off;
fastcgi_cache_key "$scheme$request_method$host$request_uri";
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}UnoPim 專屬的 Server Block
sudo nano /etc/nginx/sites-available/unopimserver {
listen 80;
listen [::]:80;
server_name pim.yourdomain.com;
root /var/www/unopim/public;
index index.php;
charset utf-8;
# Laravel 標準 rewrite
location / {
try_files $uri $uri/ /index.php?$query_string;
}
# 靜態資產:1 年快取 + immutable
location ~* \.(css|js|jpg|jpeg|png|gif|ico|svg|woff|woff2|ttf|webp|avif)$ {
expires 365d;
add_header Cache-Control "public, immutable";
access_log off;
}
# PHP 處理
location ~ \.php$ {
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_buffers 16 16k;
fastcgi_buffer_size 32k;
fastcgi_read_timeout 300;
}
# 鎖死敏感檔
location ~ /\.(?!well-known).* { deny all; }
location ~ /\.env { deny all; }
# 日誌
access_log /var/log/nginx/unopim_access.log;
error_log /var/log/nginx/unopim_error.log;
}# 啟用站點、移除預設、測試、reload
sudo ln -sf /etc/nginx/sites-available/unopim /etc/nginx/sites-enabled/
sudo rm -f /etc/nginx/sites-enabled/default
sudo nginx -t
sudo systemctl reload nginx裝 SSL(Let's Encrypt)
sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d pim.yourdomain.com
# 自動續約已經是 default 設好的,但驗證一下
sudo certbot renew --dry-runMySQL 8 緩衝池與索引
Lightsail 上 Laravel 效能瓶頸通常來自資料庫,而非 PHP。MySQL 8 預設 innodb_buffer_pool_size 僅 128 MB,對 PIM 規模的資料量明顯不足。
建立 UnoPim 專屬的 MySQL 設定檔
sudo nano /etc/mysql/mysql.conf.d/unopim.cnf[mysqld]
# ===== InnoDB 緩衝池(最重要) =====
# 4GB 機器:分 1.5GB 給 InnoDB
innodb_buffer_pool_size = 1536M
innodb_buffer_pool_instances = 2
innodb_log_file_size = 512M
innodb_flush_log_at_trx_commit = 2
innodb_flush_method = O_DIRECT
innodb_file_per_table = 1
innodb_io_capacity = 2000
innodb_io_capacity_max = 4000
# ===== 連線設定 =====
max_connections = 150
thread_cache_size = 32
wait_timeout = 600
interactive_timeout = 600
# ===== Query Cache(MySQL 8 已移除,這裡不用設) =====
# ===== 暫存檔與排序 =====
tmp_table_size = 64M
max_heap_table_size = 64M
sort_buffer_size = 2M
join_buffer_size = 2M
# ===== 慢查詢 log =====
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 2
log_queries_not_using_indexes = 1
# ===== 字元編碼 =====
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_cisudo mkdir -p /var/log/mysql
sudo chown mysql:mysql /var/log/mysql
sudo systemctl restart mysql
sudo systemctl status mysql找出 UnoPim 的慢查詢
服務運行一段時間後,查詢慢查詢 log 以定位效能問題:
# 用內建 mysqldumpslow 看 top 10 慢 query
sudo mysqldumpslow -t 10 /var/log/mysql/slow.log
# 進階:用 pt-query-digest(Percona Toolkit)
sudo apt install -y percona-toolkit
sudo pt-query-digest /var/log/mysql/slow.log | lessSHOW STATUS LIKE 'Innodb_buffer_pool%';
-- 命中率公式:
-- hit_rate = (1 - reads / read_requests) * 100Redis:快取、Session 與 Queue
將 Cache、Session、Queue、Broadcast 四個 driver 全部切換至 Redis,可將 file system I/O 降至接近零,是 Laravel 正式環境的標準配置。
設定 Redis
sudo nano /etc/redis/redis.conf# ===== 網路 =====
bind 127.0.0.1 # 只接受 localhost 連線
port 6379
protected-mode yes
# ===== 認證(強烈建議設密碼) =====
requirepass 你的安全 redis 密碼
# ===== 記憶體管理 =====
maxmemory 512mb
maxmemory-policy allkeys-lru
# 當記憶體滿時,刪除最少用到的 key
# ===== 持久化(cache 不需要太頻繁存檔) =====
save 900 1
save 300 10
save 60 10000
# ===== AOF(Queue 數據用) =====
appendonly yes
appendfsync everysec
# ===== 性能 =====
tcp-keepalive 300
timeout 0
tcp-backlog 511sudo systemctl restart redis-server
# 測試連線
redis-cli -a 你的密碼 ping
# 應該回應 PONG更新 UnoPim 的 .env 連 Redis
CACHE_DRIVER=redis
SESSION_DRIVER=redis
QUEUE_CONNECTION=redis
BROADCAST_DRIVER=redis
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=你的密碼
REDIS_PORT=6379
REDIS_DB=0
REDIS_CACHE_DB=1
REDIS_CLIENT=phpredis分離 Cache 與 Queue 的 DB
Redis 有 16 個 logical database(0-15),我們把 cache、session、queue 分開存: 這樣 php artisan cache:clear 時不會把佇列裡的 job 也炸掉。
| DB Number | 用途 | .env 設定 |
|---|---|---|
| DB 0 | Session | REDIS_DB=0 |
| DB 1 | Cache (config / view / route) | REDIS_CACHE_DB=1 |
| DB 2 | Queue jobs | REDIS_QUEUE_DB=2 |
Laravel 內建優化指令
Laravel 提供 optimize 指令,一次快取 config、events、routes、views 至單一編譯檔案。依官方文件,此指令應作為每次部署流程的一部分執行。
正式環境的部署指令清單
cd /var/www/unopim
# ===== 部署前清空舊快取 =====
sudo -u www-data php artisan optimize:clear
# ===== 啟用 production mode =====
sudo -u www-data php artisan optimize
# 上面這條相當於以下個別指令:
sudo -u www-data php artisan config:cache
sudo -u www-data php artisan route:cache
sudo -u www-data php artisan view:cache
sudo -u www-data php artisan event:cache
# ===== 重啟 PHP-FPM 以套用新 bytecode =====
sudo systemctl reload php8.3-fpmUnoPim 額外的優化指令
# Composer 的 autoloader 優化(重要!)
sudo -u www-data composer install --no-dev --optimize-autoloader
# 建立 storage symlink(首次部署需要)
sudo -u www-data php artisan storage:link
# 重新建立 Elasticsearch 索引(如果有跑 ES)
sudo -u www-data php artisan search:reindex建立一個 deploy.sh 自動化腳本
sudo nano /var/www/unopim/deploy.sh#!/bin/bash
# /var/www/unopim/deploy.sh
set -e
cd /var/www/unopim
echo "→ 進入 maintenance mode"
sudo -u www-data php artisan down
echo "→ 拉新 code"
sudo -u www-data git pull origin main
echo "→ 更新 composer"
sudo -u www-data composer install --no-dev --optimize-autoloader
echo "→ 跑 migration"
sudo -u www-data php artisan migrate --force
echo "→ 編譯前端"
sudo -u www-data npm install
sudo -u www-data npm run build
echo "→ 重建快取"
sudo -u www-data php artisan optimize:clear
sudo -u www-data php artisan optimize
echo "→ 重啟 services"
sudo systemctl reload php8.3-fpm
sudo supervisorctl restart unopim-worker:*
echo "→ 解除 maintenance mode"
sudo -u www-data php artisan up
echo "✓ Deploy 完成"sudo chmod +x /var/www/unopim/deploy.sh
# 之後每次部署只需跑:
sudo /var/www/unopim/deploy.shLaravel Octane 常駐模式(進階)
Laravel Octane 搭配 Swoole 或 RoadRunner,將應用程式啟動後常駐記憶體,request 之間不重啟,消除傳統 PHP 的冷啟動成本。依 Laravel 官方 benchmark,API 密集型工作負載吞吐量可提升 5-10 倍。完成前述各章調校後再評估是否啟用 Octane。
UnoPim 的 composer.json 已經包含 laravel/octane: ^2.3, 代表它原生支援 Octane。只是預設沒啟用。
Octane 的權衡
| 面向 | 傳統 PHP-FPM | Octane (Swoole) |
|---|---|---|
| 每次 request 啟動 | 重新 bootstrap Laravel(~50ms) | Bootstrap 一次,永久常駐 |
| RPS 上限 | 50-150 | 500-2000+ |
| 記憶體佔用 | 較低 | 每個 worker 持續吃 60-100 MB |
| 記憶體洩漏風險 | 無(每個 request 都全新環境) | 有;需要 watchdog 重啟 |
| 適合什麼站 | 後台、低-中流量、複雜邏輯 | API、高頻 read、SSR、PWA |
安裝 Swoole 並啟用 Octane
# 安裝 Swoole PHP extension
sudo apt install -y php8.3-swoole
# 確認 Swoole 已載入
php -m | grep swoole
# 在 UnoPim 啟用 Octane
cd /var/www/unopim
sudo -u www-data php artisan octane:install --server=swoole
# 啟動 Octane(測試用)
sudo -u www-data php artisan octane:start \
--server=swoole \
--host=127.0.0.1 \
--port=8000 \
--workers=4 \
--task-workers=2 \
--max-requests=500讓 Nginx 把 PHP request 導到 Octane
修改你剛剛建立的 Nginx server block,把 PHP location 改成 reverse proxy:
upstream octane {
server 127.0.0.1:8000;
}
server {
# ... 同前 ...
location / {
try_files $uri $uri/ @octane;
}
location @octane {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://octane;
proxy_http_version 1.1;
proxy_buffering off;
}
}用 Supervisor 守護 Octane 進程
sudo apt install -y supervisor
sudo nano /etc/supervisor/conf.d/octane.conf[program:unopim-octane]
process_name=%(program_name)s
command=php /var/www/unopim/artisan octane:start --server=swoole --host=127.0.0.1 --port=8000 --workers=4
autostart=true
autorestart=true
user=www-data
redirect_stderr=true
stdout_logfile=/var/log/octane.log
stopwaitsecs=60sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl start unopim-octaneElasticsearch 設定與記憶體
UnoPim 以 Elasticsearch 處理商品搜尋,這是其支援大規模 catalog 的核心機制。Elasticsearch 記憶體消耗較高,在 Lightsail 上必須明確限制 JVM heap 上限。
限制 JVM Heap Size
Elasticsearch 預設會佔用系統一半的記憶體。在 4 GB 的 Lightsail 上若不限制,會直接觸發 OOM。 我們已經在 STEP 07 把 heap 限制為 1 GB,這裡再確認一下:
cat /etc/elasticsearch/jvm.options.d/heap.options
# 應該看到:
# -Xms1g
# -Xmx1g
# Heap 與 max 必須一樣,否則 JVM 動態調整很消耗關閉不必要的功能
sudo nano /etc/elasticsearch/elasticsearch.ymlcluster.name: unopim-cluster
node.name: unopim-node-1
# 單機 cluster:禁止它去找其他 node
discovery.type: single-node
# 只接受本機連線
network.host: 127.0.0.1
http.port: 9200
# 關閉安全模組(內部網路才這樣設!)
xpack.security.enabled: false
xpack.security.enrollment.enabled: false
# 關閉 ML(除非你要用)
xpack.ml.enabled: false
# Bootstrap memory lock(防止被 swap)
bootstrap.memory_lock: true# 加上 systemd 的 mlockall 權限
sudo mkdir -p /etc/systemd/system/elasticsearch.service.d
sudo tee /etc/systemd/system/elasticsearch.service.d/override.conf << EOF
[Service]
LimitMEMLOCK=infinity
EOF
sudo systemctl daemon-reload
sudo systemctl restart elasticsearch
# 確認跑得起來
curl -X GET "localhost:9200/?pretty"Queue Worker + Supervisor
UnoPim 的商品匯入、匯出、AI agent、completeness 計算與 webhook 均為非同步任務。未啟動 queue worker 時,這些功能在 UI 操作後會報錯或持續等待,不會執行。
UnoPim 官方建議的 Queue 設定
依 UnoPim 官方文件,執行 imports/exports、AI agent tasks、completeness jobs 與 webhook deliveries 均需啟動 queue worker,指令為 php artisan queue:work --queue=webhooks,system,default,completeness。webhooks queue 必須包含在內,否則 webhook event 會持續堆積而不被處理。
用 Supervisor 跑 4 個 worker
sudo nano /etc/supervisor/conf.d/unopim-worker.conf[program:unopim-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /var/www/unopim/artisan queue:work redis \
--queue=webhooks,system,default,completeness \
--sleep=3 --tries=3 --max-time=3600 --max-jobs=1000
autostart=true
autorestart=true
stopasgroup=true
killasgroup=true
user=www-data
numprocs=4
redirect_stderr=true
stdout_logfile=/var/log/unopim-worker.log
stopwaitsecs=3600sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl start unopim-worker:*
# 確認 4 個 process 都在跑
sudo supervisorctl status為什麼 numprocs=4 而不是更多?
每個 queue worker 約吃 60-90 MB 記憶體。在 4 GB 機器上,PHP-FPM 已經 佔用約 1.6 GB。若再開 8 個 worker(720 MB),剩餘記憶體不足以支撐 OS 與其他服務。4 個 worker 對中小流量站已足夠,每秒可處理 20-30 個 job。
CloudFront CDN 全站加速
Lightsail 內建 CloudFront 分發功能,透過 Amazon CloudFront 基礎設施將內容分佈至全球邊緣節點以降低延遲。PIM 管理後台本身不需要 CDN 加速,但商品圖片與前端資產透過 CDN 傳遞速度可提升數倍。
建立 Distribution
到 Lightsail Console → Networking 頁籤 → Create distribution
Origin:選你的 Lightsail instance
Caching behavior:選 Custom(manual configuration)
把以下 path 設為「不要快取」:
/admin/*— 後台不快取/api/*— API 不快取/login,/logout
其他 path 可以放心快取
選擇最便宜的 plan($2.5/月 含 50 GB / 200 萬 requests)
點 Create
更新 UnoPim 的 ASSET_URL
# .env 增加:
ASSET_URL=https://d12345abcde.cloudfront.net
APP_URL=https://pim.yourdomain.com然後讓 Laravel 知道:所有 asset() helper 輸出的 URL 走 CloudFront、 但 url()(含路由)仍走自家 domain。
sudo -u www-data php artisan optimize:clear
sudo -u www-data php artisan optimizeCloudflare 作為替代
不想被 AWS 綁,可以用 Cloudflare 的免費 plan: 把網域的 nameserver 指向 Cloudflare,DNS 設 A record 指 Lightsail 的 static IP, 勾選「Proxied」(橘色雲)即可。Cloudflare 的 Free plan 已經包含 DDoS protection、 無限頻寬、TLS、global CDN。對 PIM 這種低-中流量場景非常划算。
監控、Log 與除錯
調校完成後,需要持續觀測以確認設定有效並及早發現問題。以下列出建議每週檢視一次的指標與工具。
Lightsail 內建 metrics
在 Instance 頁面有 5 張預設圖表:CPU utilization、Burst capacity、Network traffic、 Status check failed、Memory utilization(需安裝 CloudWatch agent)。
Burst capacity 圖表最為關鍵:若過去 24 小時曾降至 0%,表示 CPU 發生降頻。處理方式為重新檢查 PHP-FPM 與 MySQL 設定,或升級 instance 規格。
裝 htop + atop 看即時狀態
sudo apt install -y htop atop iotop
# 即時 process / CPU / 記憶體
htop
# 歷史 process(系統會背景紀錄)
atop
# 磁碟 I/O 熱點
sudo iotop -oLaravel 自帶的健康檢查
Laravel 12 內建 /up 健康檢查端點。依官方文件,此 route 在應用程式正常啟動時回傳 200 HTTP response,可供 uptime monitor 或 load balancer 使用。建議接至 UptimeRobot(免費方案)或 BetterStack:
# 測試健康端點
curl https://pim.yourdomain.com/up
# 應該回 200 + 一個簡單 HTML啟用 Laravel Horizon(Queue 監控)
cd /var/www/unopim
sudo -u www-data composer require laravel/horizon
sudo -u www-data php artisan horizon:install
# 修改 supervisor 跑 horizon 取代原本 queue worker
sudo nano /etc/supervisor/conf.d/horizon.conf安裝完成後,https://pim.yourdomain.com/horizon 提供 Redis-backed queue 的即時吞吐量指標與 worker scaling 設定,適合用於監控 queue 健康狀態與流量突增時的問題排查。
排錯三步驟
| 症狀 | 先查 | 常見原因 |
|---|---|---|
| 網頁 500 error | tail -f /var/www/unopim/storage/logs/laravel.log | 權限錯、.env 沒設好、migration 沒跑 |
| 網頁很慢 | htop 看 CPU;mysqldumpslow | 慢查詢、OPcache 沒開、burst credit 用完 |
| 502 Bad Gateway | sudo systemctl status php8.3-fpm | PHP-FPM 掛了、socket 路徑錯、記憶體爆掉 |
| 匯入卡住 | sudo supervisorctl status | queue worker 沒跑、Redis 沒連到 |
| 搜尋沒結果 | curl localhost:9200/_cat/indices | Elasticsearch 掛了、reindex 沒做 |
Reddit / 社群實戰祕技
以下整理自 r/aws、r/laravel、r/selfhosted、AWS re:Post 及多位部落客的實際部署經驗,記錄官方文件未涵蓋的常見問題與處理方式。
我用 1 vCPU / 512MB 跟 1 vCPU / 2GB 兩台分別架 Laravel。前面 1 小時都很快, 每頁 400ms 載完,然後突然就變成 120 秒以上。CPU 使用率明明很低、記憶體只有 400MB, 但每個頁面要「boot 兩分鐘」才開始載入。
解法
這是 burst credit 耗盡的典型症狀。AWS 工程師建議改用 Nginx + PHP-FPM、記憶體不低於 1 GB、並建立 swap。根本解法為升級至至少 2 GB / 2 vCPU 規格。
我改了 php-fpm.d/www.conf 的 pm.max_children,重啟伺服器後設定居然被還原了。 我是不是瘋了?
Bitnami 設定被覆寫的原因
Bitnami 的 /opt/bitnami/php/etc/php-fpm.d/www.conf 結尾有一行 include=/opt/bitnami/php/etc/memory.conf。memory.conf 是 symlink, 每次開機時依 instance 規格自動重新生成,覆寫手動修改的參數。 處理方式為註解掉該行 include,或改用 OS-only image 重新安裝。
升了 Octane 之後 RPS 從 80 飆到 600,老闆超開心。結果三天後有個用戶 A 在後台看到用戶 B 的訂單 — 我整個冷汗。
Octane Stateful Container 問題
Octane 的 Laravel container 在 request 之間常駐。任何 singleton service 或在 ServiceProvider 裡 bind 的 instance,均不會在 request 結束時自動 reset。 處理方式:將相關 service 改為 scoped(在 boot 裡使用 $this->app->scoped()), 或加入 config/octane.php 的 flush array 強制每次 request 重置。 PIM 或後台類系統建議先在 staging 環境運行一個月,確認無狀態洩漏後再部署至 production。
我的 Lightsail 一直 CPU 飆高、network 也飆高。後來發現是 fail2ban 沒裝, scrapers 跟 SSH brute force 把我網路頻寬都吃光, 導致我「以為的 Lightsail 效能不夠」其實是被攻擊。
建議安裝 fail2ban
sudo apt install fail2ban 安裝後,預設規則即可防護 SSH brute force。 Nginx 可另建 jail:在 /etc/fail2ban/jail.d/nginx.conf 中設定規則,阻擋 404 風暴、惡意爬蟲與驗證失敗嘗試。同時建議在 Lightsail firewall 關閉所有未使用的 port,僅開放 80/443/22。
我們團隊評估了 Akeneo CE、Pimcore 跟 UnoPim 三家。最後選 UnoPim, 因為它的學習曲線最平。但有個坑:Magic AI / AI agent 功能是吃 token 的、要接 OpenAI key, 免費版能用但要自己付 LLM 費用。
UnoPim 授權與 AI 功能費用說明
UnoPim 本體採 MIT 授權,自架免費。「Magic AI」、「AI Agent Chat」等 LLM 功能會呼叫外部 API(OpenAI / Anthropic / Gemini 等),費用由使用者自行負擔。 不需要此功能時,可在 admin 介面關閉 AI module,或改接本地執行的 Ollama(需自行修改 driver)。
我們用了 Lightsail + CloudFront 一個月。Lightsail 帳單是 $24, CloudFront 居然是 $63 — 後來才發現我們沒設 cache 規則,所有 request 都打回 origin。
CloudFront cache 命中率設定
建立 distribution 後需設定 cache behavior 與 TTL。PIM 場景中商品圖片更新頻率低,靜態資產 TTL 建議設 1 年(31536000 秒),HTML 設 5 分鐘至 1 小時。每月檢視一次 Cache Hit Rate,理想值 > 85%。低於 70% 時,檢查 cache key 是否包含過多 query string 參數。
我的 Lightsail 平常都很快,但每月特定一兩天會突然變慢,三天後又恢復 — 我以為是被駭客攻擊, 花了兩週查 log 找不到原因。
排程任務的 CPU 影響
每月對帳、重建索引、全站匯出等批次 cron job 是常見的 CPU 高峰來源。UnoPim 預設的 php artisan schedule:run 包含 completeness recalculation,商品數量多時此任務可能持續數小時。 處理方式:將此類任務改至週末凌晨執行、加 nice -n 19 降低 CPU 優先級,或移至第二台 Lightsail 執行批次作業。
Laravel + Lightsail 的真正瓶頸幾乎都不是 PHP — 是 MySQL。 innodb_buffer_pool_size 設好佔半個機器記憶體,效能會比換 Octane 還明顯。
效能改善的建議優先順序
依實務經驗,從效益明顯到實作複雜依序為:(1) MySQL innodb_buffer_pool_size (2) Redis 取代 file cache (3) OPcache (4) Nginx gzip + asset cache (5) artisan optimize (6) Octane (7) CloudFront。 完成前四項通常可獲得約 80% 的效能改善。Octane 效益顯著但需處理 stateful container 風險,建議最後評估。
UnoPim vs Akeneo vs Pimcore
下表整理自 AtroPIM 開源 PIM 比較研究、Akeneo 官方公告及 GitHub 活躍度數據,列出 UnoPim 與主要開源 PIM 的技術差異。
| 面向 | UnoPim | Akeneo CE | Pimcore | AtroPIM |
|---|---|---|---|---|
| 框架 | Laravel 12 (PHP) | Symfony (PHP) | Symfony (PHP) | AtroCore (PHP) |
| 授權 | MIT | OSL v3 | GPL v3 | GPL v3 |
| 學習曲線 | 簡單 | 中等 | 高 | 中等 |
| 商品上限(實測) | 10M+(官方宣稱) | 1M+ | 10M+ | 5M+ |
| AI 內建支援 | ✓ Magic AI / Agent | 需付費版 | 需付費版 | 部分 |
| DAM 整合 | ✓ Unopim DAM 模組 | 需額外模組 | ✓ 內建 | 需擴充 |
| 多語系 | ✓ | ✓ | ✓ | ✓ |
| 欄位級權限 | 無 | 無 | 需設定 | ✓ |
| 長期支援 | 活躍開發中 | 2023 起停加新功能 2026/9 EOL | 穩定 | 活躍 |
| 社群規模 (GitHub) | ~10K stars | ~3K stars | ~12K stars | ~500 stars |
各產品適用情境
UnoPim:小到中型 B2B / B2C,1 萬到百萬商品,需要 AI 內建、團隊熟悉 Laravel。
Akeneo CE:2026 後不建議新案使用,現存案場可繼續、新案請評估遷移。
Pimcore:需要 PIM + DAM + MDM + CMS 一站式、有專屬開發團隊、預算充足。
AtroPIM:需要 API-first、欄位級權限、複雜資料模型的製造業 / 經銷商。
部署檢查清單
公開站台前,依下列清單逐項確認。各項目均對應前述章節說明。
上線前 · Pre-Launch Checklist
A · 基礎建設
- 未完成:
Lightsail 規格至少 2 vCPU / 4 GB RAM / 80 GB SSD
- 未完成:
Static IP 已 attach 到 instance
- 未完成:
Daily snapshot 已啟用
- 未完成:
Firewall 只開 80 / 443 / 22
- 未完成:
fail2ban 已安裝並啟動
- 未完成:
SSH 已關閉 password 登入,只允許 key
B · 作業系統
- 未完成:
4 GB Swap file 已建立並寫進 /etc/fstab
- 未完成:
vm.swappiness=10 已寫進 /etc/sysctl.conf
- 未完成:
ulimit / file descriptor 提高到 65535
- 未完成:
時區設成 Asia/Taipei(或符合用戶所在地)
- 未完成:
unattended-upgrades 已啟用安全更新
C · PHP 與應用層
- 未完成:
PHP 8.3 + 所有 UnoPim 需要的 ext 模組
- 未完成:
OPcache 啟用且 validate_timestamps=0
- 未完成:
OPcache JIT 啟用
- 未完成:
PHP-FPM pm.max_children 已依公式計算
- 未完成:
composer install --no-dev --optimize-autoloader
- 未完成:
artisan optimize 已執行
D · 資料庫與快取
- 未完成:
MySQL innodb_buffer_pool_size 至少 1.5 GB
- 未完成:
MySQL slow_query_log 已開啟
- 未完成:
Redis 已設密碼、bind 127.0.0.1
- 未完成:
Redis maxmemory + allkeys-lru policy
- 未完成:
Elasticsearch heap 限制為 1 GB
- 未完成:
UnoPim .env: CACHE/SESSION/QUEUE 全部設成 redis
E · Nginx 與 SSL
- 未完成:
Nginx server_tokens off
- 未完成:
Gzip 壓縮已啟用
- 未完成:
靜態資產 Cache-Control: 1 year + immutable
- 未完成:
Let's Encrypt SSL 已安裝
- 未完成:
certbot renew --dry-run 通過
- 未完成:
HTTP 自動 redirect 到 HTTPS
- 未完成:
.env 與 .git 被 deny 規則擋住
F · 佇列與背景任務
- 未完成:
Supervisor 已安裝
- 未完成:
queue:work --queue=webhooks,system,default,completeness
- 未完成:
numprocs 至少 2-4 個 worker
- 未完成:
cron job 跑 schedule:run
- 未完成:
Laravel Horizon 已安裝(建議)
G · 監控與備份
- 未完成:
UptimeRobot / BetterStack 監控 /up 端點
- 未完成:
每日 MySQL dump 自動備份到 S3 / 外部儲存
- 未完成:
storage/app/public 也有定期備份
- 未完成:
Laravel log 有 rotate(避免 1 個檔案上百 GB)
- 未完成:
設好 admin email 告警
H · 應用層設定
- 未完成:
APP_DEBUG=false
- 未完成:
APP_ENV=production
- 未完成:
已建立管理員帳號(並換掉預設密碼 admin123)
- 未完成:
時區、語系、貨幣已在 admin 後台設定
- 未完成:
Magic AI 不用就關掉,省 token 費用
- 未完成:
已測試匯入、匯出、API 三個關鍵 flow
完整服務架構圖
完成本手冊所有章節後,Lightsail 4 GB 機器上的服務佈局如下圖所示。所有服務透過 localhost 互通,記憶體分配標示於圖中。
┌──────────────────────────┐
│ CloudFront / Cloudflare │
│ (Static asset cache) │
└────────────┬─────────────┘
│ HTTPS
▼
┌─────────────────────────────────────────────────────────────┐
│ AWS LIGHTSAIL · ap-northeast-1 │
│ 4 GB RAM · 2 vCPU · 80 GB SSD │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ Nginx 1.24 :80 / :443 │ │
│ │ ─ gzip · http2 · static cache 1yr │ │
│ └────────────────────┬─────────────────────────────────┘ │
│ │ Unix socket │
│ ▼ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ PHP-FPM 8.3 · pm=dynamic · 20 workers ~1600 MB │ │
│ │ ─ OPcache 256 MB · JIT enabled │ │
│ │ ─ Laravel 12 · UnoPim │ │
│ └────┬──────────────┬──────────────┬───────────────────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌─────────┐ ┌─────────┐ ┌──────────────┐ │
│ │ MySQL 8 │ │ Redis 7 │ │ Elasticsearch │ │
│ │ ~800 MB │ │ ~256 MB │ │ ~1024 MB │ │
│ └─────────┘ └────┬────┘ └──────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ Supervisor │ │
│ │ ─ queue:work × 4 (webhooks,system,default,...) │ │
│ │ ─ schedule:run (cron-based, 1/min) │ │
│ └──────────────────────────────────────────────────────┘ │
│ │
│ Swap: 4 GB · vm.swappiness=10 │
└─────────────────────────────────────────────────────────────┘— 圖. 一台 4 GB Lightsail 完整調校後的服務佈局 —
結語
完成這 18 章後,UnoPim 在 $24/月的 Lightsail 上可承載 5-10 萬商品、每秒 80-150 個 request、p95 延遲約 200-400ms。此效能水準符合中型 PIM 正式環境需求。
所有調校設定均有時效性。Laravel 升版、UnoPim 新功能、AWS burst 政策調整,以及 MySQL 版本更新,都可能影響現有設定的有效性。建議每半年重新檢視本手冊各章節,尤其 PHP 升至 8.4 後,OPcache 與 JIT 相關參數可能需要調整。
當 Lightsail 頂規仍無法滿足需求時,可從 Lightsail 直接 export snapshot 至 EC2 AMI,再建立 EC2 + Auto Scaling Group 架構,無需從頭重新安裝。
CloudFront / Cloudflare
(Static asset cache)
- HTTPS
AWS LIGHTSAIL · ap-northeast-1
4 GB RAM · 2 vCPU · 80 GB SSD
Nginx 1.24 :80 / :443
- ─ gzip · http2 · static cache 1yr
- Unix socket
PHP-FPM 8.3 · pm=dynamic · 20 workers ~1600 MB
- ─ OPcache 256 MB · JIT enabled
- ─ Laravel 12 · UnoPim
MySQL 8
~800 MB
Redis 7
~256 MB
Elasticsearch
~1024 MB
Supervisor
- ─ queue:work × 4 (webhooks,system,default,...)
- ─ schedule:run (cron-based, 1/min)
Swap: 4 GB · vm.swappiness=10
— 圖. 一台 4 GB Lightsail 完整調校後的服務佈局 —
本手冊
本手冊以 Fraunces、Noto Serif TC、Noto Sans TC 與 JetBrains Mono 字體排印。 內容整合自 UnoPim 官方文件、AWS re:Post 社群案例、Laravel 12 官方部署指南、 及 r/aws、r/laravel、r/selfhosted 多年實戰討論。 所有指令均在 Ubuntu 24.04 LTS / Lightsail 4 GB plan 上實機驗證。