我常用的一個場景是一台Linux底下有多個Spring Application,可以透過Linux systemd控制他們,然後使用Nginx的反向代理產生唯一對外窗口,讓外界透過Nginx與Spring Application溝通。以下教學在Debian與Ubuntu都是可以使用的。CentOS可能也可以,但自從RedHat宣布準備停止支援後我就沒再用CentOS了,所以沒測試過。

Spring Boot設置

Spring Application可以用gradle bootJar產生jar檔案,給Linux系統執行。或是讓Linux執行gradle bootRun也可以。

新增使用者

我習慣增加一個不可登入的使用者,名為springboot,專門給Spring Boot使用。如果更嚴謹一點,也可以為每個不同的Spring Boot都新增一個使用者。

sudo useradd -r -s /bin/false springboot
  • 參數 -r:建立系統使用者
  • 參數 -s:指定Login Shell為不能登入

建立Service設置

建立一個檔案「/etc/systemd/system/spring-app.service」,其中檔案名稱「spring-app」可以替換成你的服務的名稱。檔案內的「ExecStart」設置可以依照個人需求調整,也可以改成啟動一個shell腳本,將詳細的啟動指令寫在腳本內。

[Unit]
Description=Spring Application Name
After=syslog.target

[Service]
Restart=always
RestartSec=3
User=springboot
ExecStart=/usr/bin/java -Xmx1024m -Xms1024m -jar /home/springboot/app.jar --spring.profiles.active=prod

[Install]
WantedBy=multi-user.target

Linux Systemd

systemd由systemctl控制,需要最高權限,所以要使用sudo,或是直接轉成root身份喔。

讀取Service設置

每次新增或是修改systemd內的.service檔案後,要呼叫systemctl重新讀取設置。

sudo systemctl daemon-reload

控制方式

sudo systemctl start spring-app    # 啟動服務
sudo systemctl stop spring-app     # 停止服務
sudo systemctl restart spring-app  # 重新啟動服務
sudo systemctl enable spring-app   # 開機後自動啟動
sudo systemctl disable spring-app  # 開機後不要自動啟動

檢查執行狀況

sudo systemctl status spring-app      # 檢查服務狀態,可以順便看見一些服務輸出的訊息
sudo systemctl is-active spring-app   # 檢查是否正在啟動著,如果是會回傳active
sudo systemctl is-enabled spring-app  # 檢查是否在開機後會自動啟動,如果是會回傳enabled
sudo systemctl is-failed  spring-app  # 檢查是否啟動失敗,如果不是會回傳active
sudo journalctl -u spring-app         # 觀看Spring Application輸出的訊息,包含Stdout與Stderr等。

最後一行提到的journalctl,參數-u spring-app是篩選只要觀看spring-app的輸出。的還可以加上-f參數,會顯示最後數行訊息,而且會在有新訊息時自動更新。還可以用-r參數將訊息反向排序輸出,但是-r不可與-f一同使用。

Nginx設置

安裝方式

sudo systemctl disable --now apache2  # 避免已經有apache會衝突,先將其關閉
sudo apt install nginx -y

反向代理Spring服務

新增一個設定檔案放在「/etc/nginx/conf.d/spring-app.conf」,一樣檔案名稱「spring-app」的部分可以改成自己需要的名字。

server {
  listen 80;
  server_name _;  # domain name 依需求自行修改

  # 一些靜態資源可以不經過反向代理,由Nginx直接返回
  location ~ ^/(|css|ext|img|js)/ {
    root /opt/Spring-App/src/main/resources/static/;
  }

  # 需要反向代理的部分
  location / {
    proxy_pass http://localhost:8080;  # 依需求自行修改
    proxy_set_header Host $http_host;  # 這些是Nginx傳給Spring的HTTP Header
    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 $http_x_forwarded_proto;
  }
}

檢查Nginx設置是否正確

sudo nginx -t

每次更改Nginx內的設定檔後,先不要急著生效,可以先用nginx -t來檢查是否有錯誤。

呼叫Nginx重新讀取設置

sudo systemctl reload nginx

Nginx多一個reload指令可以使用,可以不重啟Nginx就讓新的設定生效,是很方便的功能。但Nginx的重啟速度,平時使用restart指令也沒什麼感覺。