故障排除
本文件提供 AppFuse 應用系統常見問題的診斷與解決方案。
診斷流程
日誌位置速查
| 服務 | 日誌位置 | 用途 |
|---|---|---|
| app-server | /opt/appfuse/logs/app-server.log | 應用程式日誌 |
| Systemd | journalctl -u appfuse.service | 服務啟動日誌 |
| Nginx access | /var/log/nginx/access.log | HTTP 請求記錄 |
| Nginx error | /var/log/nginx/error.log | Nginx 錯誤 |
| Tomcat | $CATALINA_HOME/logs/catalina.out | WAR 部署日誌 |
| MySQL | /var/log/mysql/error.log | 資料庫錯誤 |
啟動問題
問題:服務啟動失敗
症狀:
$ sudo systemctl status appfuse.service
● appfuse.service - AppFuse Application Server
Active: failed (Result: exit-code)
診斷步驟:
-
查看詳細錯誤:
sudo journalctl -u appfuse.service -n 50 --no-pager -
查看 Tomcat 日誌:
tail -100 $CATALINA_HOME/logs/catalina.out -
比對正常啟動日誌: 如果不確定錯誤訊息的意義,可參考下方的正常啟動日誌範例。
點擊查看:正常 Tomcat 啟動日誌範例 (catalina.out)
06-May-2024 13:53:00.884 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Server version name: Apache Tomcat/11.0.18
06-May-2024 13:53:00.888 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Server built: Apr 16 2024 12:17:18 UTC
06-May-2024 13:53:00.888 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Server version number: 11.0.18.0
06-May-2024 13:53:00.889 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log OS Name: Linux
06-May-2024 13:53:00.889 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log OS Version: 5.15.0-101-generic
06-May-2024 13:53:00.889 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Architecture: amd64
06-May-2024 13:53:00.889 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Java Home: /usr/lib/jvm/java-25-openjdk-amd64
06-May-2024 13:53:00.889 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log JVM Version: 25+...
06-May-2024 13:53:00.890 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log JVM Vendor: Ubuntu
06-May-2024 13:53:00.890 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log CATALINA_BASE: /home/appmgr/opt/apache-tomcat-11.0.18
...
06-May-2024 13:53:02.293 INFO [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler ["http-nio-8080"]
06-May-2024 13:53:02.310 INFO [main] org.apache.catalina.startup.Catalina.start Server startup in [963] milliseconds
注意:若未看到
Server startup in [...] milliseconds,通常代表啟動過程中斷或失敗。
常見原因與解決方案:
原因 1:Java 版本不正確
$ java -version
# 確認是 JDK 25+
解決:安裝正確的 JDK 版本
sudo apt install openjdk-25-jdk
原因 2:埠號被佔用
$ netstat -tlnp | grep 8080
tcp 0 0 0.0.0.0:8080 0.0.0.0:* LISTEN 1234/java
解決:停止佔用埠號的程序或更改配置
# 找出佔用程序
sudo lsof -i :8080
# 或修改 application.properties
server.port=8081
原因 3:配置檔錯誤
解決:檢查 properties 檔案是否有語法錯誤
cat /opt/appfuse/conf/application.properties
問題:資料庫連線失敗
症狀:
org.springframework.jdbc.CannotGetJdbcConnectionException: Failed to obtain JDBC Connection
診斷步驟:
# 1. 確認資料庫服務運行中
sudo systemctl status mysql
# 2. 測試資料庫連線
mysql -h localhost -u appfuse -p appdb
# 3. 檢查連線字串
grep datasource /opt/appfuse/conf/application.properties
常見原因與解決方案:
原因 1:資料庫服務未啟動
sudo systemctl start mysql
原因 2:連線資訊錯誤
確認 application.properties 中的設定:
spring.datasource.url=jdbc:mysql://localhost:3306/appdb
spring.datasource.username=appfuse
spring.datasource.password=correct-password
原因 3:防火牆阻擋
# 檢查防火牆規則
sudo ufw status
# 允許 MySQL 連線(如需遠端連線)
sudo ufw allow 3306/tcp
原因 4:MySQL 使用者權限
-- 檢查使用者權限
SHOW GRANTS FOR 'appfuse'@'localhost';
-- 授權
GRANT ALL PRIVILEGES ON appdb.* TO 'appfuse'@'localhost';
FLUSH PRIVILEGES;
連線問題
問題:無法透過瀏覽器存取
診斷步驟:
- 檢查後端服務:
curl http://localhost:8080/actuator/health - 檢查 Nginx:
curl http://localhost/ - 檢查 Nginx 狀態:
sudo systemctl status nginx
詳細診斷:
如果簡單的 curl 無法釐清問題(例如 502 Bad Gateway 或 CORS 錯誤),可使用詳細模式檢查 HTTP Header。
點擊查看:詳細連線測試範例 (含 Header)
使用 curl -v (verbose) 查看完整的請求與回應資訊:
$ curl -v http://localhost/app-server/actuator/health
* Trying 127.0.0.1:80...
* Connected to localhost (127.0.0.1) port 80 (#0)
> GET /app-server/actuator/health HTTP/1.1
> Host: localhost
> User-Agent: curl/7.81.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Server: nginx/1.18.0 (Ubuntu)
< Date: Thu, 27 Nov 2025 02:30:00 GMT
< Content-Type: application/vnd.spring-boot.actuator.v3+json
< Transfer-Encoding: chunked
< Connection: keep-alive
< Access-Control-Allow-Origin: * <-- 檢查 CORS 設定
<
{"status":"UP"}
* Connection #0 to host localhost left intact
若要查看經過反向代理後的後端實際回應(例如檢查 X-Forwarded-* 標頭是否生效),可建立一個測試端點或使用 json_pp 格式化輸出:
$ curl --user admin:password http://localhost:8080/app-server/api/me | json_pp
問題:API 回應 502 Bad Gateway
症狀:Nginx 回應 502 錯誤
原因:後端服務未運行或無法連線
解決:
# 1. 確認後端服務運行中
sudo systemctl status appfuse.service
# 2. 檢查 Nginx 代理配置
cat /etc/nginx/sites-enabled/appfuse.conf
# 3. 確認代理目標正確
# proxy_pass http://localhost:8080/api/;
問題:API 回應 504 Gateway Timeout
症狀:請求逾時
原因:後端處理時間過長
解決:調整 Nginx 逾時設定
location /api/ {
proxy_pass http://localhost:8080/api/;
proxy_read_timeout 120s;
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
}
問題:CORS 錯誤
症狀:瀏覽器控制台顯示 CORS 錯誤
解決:確認後端 CORS 配置或在 Nginx 加入標頭
location /api/ {
# CORS 標頭
add_header 'Access-Control-Allow-Origin' '*' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type' always;
if ($request_method = 'OPTIONS') {
return 204;
}
proxy_pass http://localhost:8080/api/;
}
效能問題
問題:系統回應緩慢
診斷步驟:
# 1. 檢查 CPU 使用率
top -p $(pgrep -f catalina)
# 2. 檢查記憶體使用
free -h
# 3. 檢查 JVM 記憶體
curl http://localhost:8080/actuator/metrics/jvm.memory.used
# 4. 檢查磁碟 I/O
iostat -x 1
# 5. 檢查資料庫慢查詢
# MySQL
sudo tail -f /var/log/mysql/mysql-slow.log
問題:OutOfMemoryError
症狀:
java.lang.OutOfMemoryError: Java heap space
解決:調整 JVM 記憶體設定
# 編輯 systemd 服務檔
sudo nano /etc/systemd/system/appfuse.service
# 調整 JAVA_OPTS
Environment="JAVA_OPTS=-server -Xms1024m -Xmx4096m"
# 重新載入並重啟
sudo systemctl daemon-reload
sudo systemctl restart appfuse.service
問題:Too many open files
症狀:
java.io.IOException: Too many open files
解決:增加檔案描述符限制
# 編輯 limits.conf
sudo nano /etc/security/limits.conf
# 加入
appfuse soft nofile 65536
appfuse hard nofile 65536
# 或在 systemd 服務檔中
[Service]
LimitNOFILE=65536
前端問題
問題:頁面顯示空白
診斷步驟:
# 1. 檢查靜態檔案是否存在
ls -la /opt/appfuse/app-web/
# 2. 檢查 index.html
cat /opt/appfuse/app-web/index.html
# 3. 瀏覽器開發者工具查看網路請求和控制台錯誤
常見原因:
- 靜態檔案未部署
- Nginx root 路徑錯誤
- JavaScript 載入失敗
問題:路由刷新後 404
症狀:SPA 路由直接存取或刷新時顯示 404
原因:Nginx 未配置 SPA 路由支援
解決:
location / {
root /opt/appfuse/app-web;
index index.html;
try_files $uri $uri/ /index.html; # 關鍵設定
}
問題:靜態資源 404
診斷:
# 檢查檔案是否存在
ls -la /opt/appfuse/app-web/assets/
# 檢查 Nginx 錯誤日誌
sudo tail -f /var/log/nginx/error.log
解決:確認 Nginx 配置的 root 路徑正確
資料庫問題
問題:中文亂碼
診斷:
-- 檢查資料庫編碼
SELECT DEFAULT_CHARACTER_SET_NAME, DEFAULT_COLLATION_NAME
FROM INFORMATION_SCHEMA.SCHEMATA
WHERE SCHEMA_NAME = 'appdb';
解決:
-- 修改資料庫編碼
ALTER DATABASE appdb CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- 確認 JDBC 連線字串包含編碼設定
-- jdbc:mysql://localhost:3306/appdb?useUnicode=true&characterEncoding=UTF-8
問題:連線數耗盡
症狀:
Too many connections
解決:
-- 檢查當前連線數
SHOW STATUS LIKE 'Threads_connected';
-- 檢查最大連線數
SHOW VARIABLES LIKE 'max_connections';
-- 增加連線數限制
SET GLOBAL max_connections = 300;
同時檢查應用程式連線池設定:
# HikariCP 設定
spring.datasource.hikari.maximum-pool-size=20
spring.datasource.hikari.minimum-idle=5
系統時間與時區問題
系統時間不同步會導致 JWT Token 驗證失敗(SignatureException)或日誌時間錯亂。
檢查時間同步狀態
使用 timedatectl 檢查:
$ timedatectl
Local time: Tue 2024-05-07 14:35:38 CST
Universal time: Tue 2024-05-07 06:35:38 UTC
System clock synchronized: no <-- 注意此項
NTP service: inactive <-- 注意此項
故障排除步驟
如果發現 System clock synchronized: no 或 NTP service: inactive:
方法 1:啟用 systemd-timesyncd (Ubuntu 預設)
# 啟用自動同步
sudo timedatectl set-ntp on
如果出現 Failed to set ntp: NTP not supported,代表系統環境(如某些 Container 或虛擬機)不支援,請改用方法 2。
方法 2:安裝傳統 NTP 服務
1. 停用 timesyncd 避免衝突
sudo timedatectl set-ntp no
2. 安裝 NTP 套件
sudo apt update
sudo apt install ntp -y
3. 檢查 NTP 同步狀態
ntpq -p
點擊查看:NTP 同步狀態詳細輸出說明
預期輸出範例:
remote refid st t when poll reach delay offset jitter
==============================================================================
0.ubuntu.pool.n .POOL. 16 p - 64 0 0.000 +0.000 0.000
+39.118.108.234 180.69.46.108 3 u 22 64 377 3.892 -0.310 1.399
*193.123.243.2 125.185.190.74 2 u 14 64 377 2.636 +2.130 2.014
-106.247.248.106 17.253.68.253 2 u 20 64 377 2.767 -0.384 1.279
符號說明:
*:目前正在使用的主同步伺服器(最重要)。+:候選的同步伺服器,狀態良好。-:被剔除的伺服器,不予使用。remote:NTP 伺服器位址。reach:連線成功率(八進位),377 代表最近 8 次嘗試皆成功。offset:本地時間與伺服器時間的偏差(毫秒)。
4. 再次驗證
timedatectl
# 確認 System clock synchronized: yes
快速診斷腳本
建立 /opt/appfuse/bin/diagnose.sh:
#!/bin/bash
echo "=========================================="
echo "AppFuse 系統診斷報告"
echo "時間: $(date)"
echo "=========================================="
echo ""
echo "=== 系統資源 ==="
echo "CPU 負載: $(uptime | awk -F'load average:' '{print $2}')"
echo "記憶體使用: $(free -h | grep Mem | awk '{print $3 "/" $2}')"
echo "磁碟使用: $(df -h /opt/appfuse | tail -1 | awk '{print $5}')"
echo ""
echo "=== 服務狀態 ==="
echo -n "appfuse.service: "
systemctl is-active appfuse.service
echo -n "nginx.service: "
systemctl is-active nginx.service
echo -n "mysql.service: "
systemctl is-active mysql.service 2>/dev/null || echo "N/A"
echo ""
echo "=== 網路埠號 ==="
netstat -tlnp 2>/dev/null | grep -E ':80|:443|:8080|:3306' || ss -tlnp | grep -E ':80|:443|:8080|:3306'
echo ""
echo "=== 健康檢查 ==="
echo -n "後端 API: "
curl -s -o /dev/null -w "%{http_code}" http://localhost:8080/actuator/health
echo ""
echo -n "前端頁面: "
curl -s -o /dev/null -w "%{http_code}" http://localhost/
echo ""
echo ""
echo "=== 最近錯誤日誌 ==="
echo "--- app-server (最近 5 筆錯誤) ---"
grep -i "error\|exception" /opt/appfuse/logs/app-server.log 2>/dev/null | tail -5 || echo "無"
echo ""
echo "--- nginx error (最近 5 筆) ---"
tail -5 /var/log/nginx/error.log 2>/dev/null || echo "無"
echo ""
echo "=========================================="
echo "診斷完成"
echo "=========================================="
使用方式:
chmod +x /opt/appfuse/bin/diagnose.sh
/opt/appfuse/bin/diagnose.sh
取得協助
如果以上方案無法解決問題:
- 收集資訊:執行診斷腳本並保存輸出
- 檢查日誌:收集相關日誌檔案
- 描述問題:記錄重現步驟和錯誤訊息
- 提交問題:至專案 Issue 追蹤系統回報
問題回報範本
## 問題描述
簡述遇到的問題
## 重現步驟
1. ...
2. ...
## 預期行為
應該發生什麼
## 實際行為
實際發生什麼
## 環境資訊
- 作業系統:
- Java 版本:
- 部署方式:
## 相關日誌
(貼上錯誤日誌)