當我們在服務器部署Java程序,特別是使用了 Spring Boot 生成單一 Jar 文件部署的時候,單一文件為我們開發單來的極大的便利性,保障程序的完整性。但同時對我們修改程序中的任何一處都帶來重啟服務的麻煩。如何解決這個問題呢?

1 問題分析
為了能夠解決這個問題,我們來分析下,為什么要重啟服務,因為 Jar 中的內容發生了改變,大部分應用程式都加載了內存中,需要重新啟動服務才能使用新的內容生效。實際上就是修改前訪問的老版本的,修改后訪問了新版本。我們使用 nginx 能夠很好的解決這個問題。
2 nginx 解決方案
在 nginx 中使用 upstream 負載均衡機制實現熱部署,也叫灰度發布,即在不停止用戶訪問的前提下進行系統更新。
2.1 nginx upstream 分發策略
upstream 機制使得 nginx 以反向代理的方式運行,因此Nginx接受客戶端的請求,並根據客戶端的請求,Nginx選擇合適的后端服務器來處理改請求。
-
輪詢
每個請求按時間順序逐一分配到不同的后端服務器,如果后端服務器down掉,會自動剔除;upstream hotstart{ server 127.0.0.1:8085; server 127.0.0.1:8086; } -
權重
指定輪詢幾率,weight和訪問比率成正比,用於后端服務器性能不均的情況;upstream hotstart{ server 127.0.0.1:8085 weight=2; server 127.0.0.1:8086 weight=1; } -
ip哈希算法
每個請求按訪問ip的hash結果分配,這樣每個訪客固定訪問一個后端的服務器,可以解決session問題;upstream hotstart{ ip_hash; server 127.0.0.1:8085; server 127.0.0.1:8086; }
2.2 nginx 配置負載均衡和分發
在服務器建立兩個一模一樣的站點分為為
- 127.0.0.1:8085
- 127.0.0.1:8086
配置 nginx.conf 文件
注意 hotstart.fishpro.com.cn 是我配置的,你可以配置為你自己的域名
upstream hotstart{
server 127.0.0.1:8085;
server 127.0.0.1:8086;
}
server{
listen 80;
server_name hotstart.fishpro.com.cn;
location / {
proxy_pass http://hotstart;
index index.html index.htm;
}
}
執行 nignx 更新命令
>ningx -s reload
nginx 詳細配置
- weight 訪問權重
- max_fails 最大失敗次數
- fail_timeout 最大失敗等待時間
upstream hotstart{
server 127.0.0.1:8085 weight=1 max_fails=3 fail_timeout=20s;
server 127.0.0.1:8086 weight=1 max_fails=3 fail_timeout=20s;
}
server{
listen 80;
server_name hotstart.fishpro.com.cn;
location / {
proxy_pass http://hotstart;
index index.html index.htm;
}
}
編寫測試用代碼
執行
java -Xms256m -Xmx512m -jar hotstart-0.0.1-SNAPSHOT.jar --server.port=8085
java -Xms256m -Xmx512m -jar hotstart-0.0.1-SNAPSHOT.jar --server.port=8086
訪問站點 hotstart.fishpro.com.cn
查看結果后,我們關閉當前查看結果的站點 再次刷新,我們可以看出當一個站點停止服務,nginx 則訪問另一個站點,這樣我們就可以逐個站點來實現不需要中斷用戶訪問來更新服務。
問題
多個站點如何共享會話 session
- 通過 redis 等 nosql 中間件實現 session 共享
- 通過配置 tomcat 服務實現
- 其他解決方案
3 其他優化點
3.1 利用 nginx 把靜態文件獨立 jar 文件之外
我們知道靜態文件使用 nginx 直接提供服務則更快更穩定,所以我們構件站點的時候直接把靜態文件包括 css、js、image 等放在 jar 文件夾之外使用域名獨立訪問。也可以理解為 動靜分離
