跳至主要内容

故障排除

本文件提供 AppFuse 應用系統常見問題的診斷與解決方案。

診斷流程

日誌位置速查

服務日誌位置用途
app-server/opt/appfuse/logs/app-server.log應用程式日誌
Systemdjournalctl -u appfuse.service服務啟動日誌
Nginx access/var/log/nginx/access.logHTTP 請求記錄
Nginx error/var/log/nginx/error.logNginx 錯誤
Tomcat$CATALINA_HOME/logs/catalina.outWAR 部署日誌
MySQL/var/log/mysql/error.log資料庫錯誤

啟動問題

問題:服務啟動失敗

症狀

$ sudo systemctl status appfuse.service
● appfuse.service - AppFuse Application Server
Active: failed (Result: exit-code)

診斷步驟

  1. 查看詳細錯誤:

    sudo journalctl -u appfuse.service -n 50 --no-pager
  2. 查看 Tomcat 日誌:

    tail -100 $CATALINA_HOME/logs/catalina.out
  3. 比對正常啟動日誌: 如果不確定錯誤訊息的意義,可參考下方的正常啟動日誌範例。

點擊查看:正常 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;

連線問題

問題:無法透過瀏覽器存取

診斷步驟

  1. 檢查後端服務:curl http://localhost:8080/actuator/health
  2. 檢查 Nginx:curl http://localhost/
  3. 檢查 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. 瀏覽器開發者工具查看網路請求和控制台錯誤

常見原因

  1. 靜態檔案未部署
  2. Nginx root 路徑錯誤
  3. 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: noNTP 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

取得協助

如果以上方案無法解決問題:

  1. 收集資訊:執行診斷腳本並保存輸出
  2. 檢查日誌:收集相關日誌檔案
  3. 描述問題:記錄重現步驟和錯誤訊息
  4. 提交問題:至專案 Issue 追蹤系統回報

問題回報範本

## 問題描述
簡述遇到的問題

## 重現步驟
1. ...
2. ...

## 預期行為
應該發生什麼

## 實際行為
實際發生什麼

## 環境資訊
- 作業系統:
- Java 版本:
- 部署方式:

## 相關日誌
(貼上錯誤日誌)