使用nginx的負載均衡機制實現用戶無感更新服務
- 2020 年 2 月 13 日
- 筆記

知識改變命運,擼碼使我快樂,2020繼續遊走在開源界 點贊再看,養成習慣 給我來個Star吧,點擊了解基於新一代接口服務框架 「ApiBoot」 的前後分離( 「Vue + ElementUI」 )管理平台基礎解決方案腳手架示例。
前言
用戶請求的轉發是接口服務在部署時必須要做的一步。
請求轉發的步驟大約分為如下幾步:
- 域名解析到轉發服務器
- 轉發服務器會根據權重(weight)、備用(backup)配置轉發到統一網關
- 如果統一網關存在灰度的配置,需要根據身份或者頭信息過濾請求
- 轉發到具體的業務服務
目前市面上優秀的請求轉發
有很多種,比如:Nginx
、F5
、Kong
、Tengine
等,其中Tengine
是阿里巴巴基於Nginx
進行封裝,我們本章的內容基於Nginx
進行講解,我們先來準備下nginx
的測試環境。
準備環境
如果你的測試環境沒有安裝Nginx
,下面我通過兩種方式來說下具體的安裝過程。
使用Brew安裝Nginx
如果你是OSX
系統,可以直接使用brew
管理工具進行安裝,這種方式比較簡單,自動從遠程服務器下載最新穩定的版本進行解壓、配置環境等。
# 安裝nginx ➜ ~ brew install nginx
靜靜等待~
安裝完成後,我們先來修改下端口號(brew安裝包把默認的監聽端口號改為了8080
,一般在使用解壓的方式安裝時監聽端口都是80
)。
我們需要先找到nginx.conf
這個文件的位置:
➜ ~ sudo find / -name nginx.conf /usr/local/etc/nginx/nginx.conf
找到文件後,我們通過sudo vi /usr/local/etc/nginx/nginx.conf
命令來修改默認的端口號,位置如下:
server { listen 80; server_name localhost; #... }
修改後保存退出。
最後不要忘記重啟Nginx
服務。
➜ ~ brew services restart nginx
解壓包方式
首先去nginx
官方提供 http://nginx.org/download 的下載地址去挑選自己中意的版本,下面以1.17.7
版本示例:
點擊下載完成後解壓安裝即可(注意編譯環境,可能會缺少一些依賴庫,本機安裝對應的依賴就可以了)
# 解壓nginx tar -xvf nginx-1.17.7.tar.gz # 進入目錄 cd nginx-1.17.7 # 配置 ./configure --prefix=/usr/local/nginx # 編譯 sudo make # 安裝 sudo make install # 進入nginx執行目錄 cd /usr/local/nginx/sbin # 啟動nginx ./nginx
安裝完成如果訪問 http://127.0.0.1 可以看到Welcome to nginx!
字樣,說明我們已經安裝成功了。
示例項目
為了演示更新服務用戶無痛感知,我們先來創建一個簡單的SpringBoot
示例項目,在項目內添加一個測試接口,項目pom.xml
依賴如下所示:
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies>
示例接口
創建一個名為TestController
的測試控制器,如下所示:
/** * 測試控制器 * * @author 恆宇少年 */ @RestController @RequestMapping(value = "/test") public class TestController { @Autowired private ServerProperties serverProperties; @GetMapping public String hello() { return "請求分發到了,端口號:" + serverProperties.getPort() + "的服務,接口訪問成功."; } }
配置轉發
我們測試所需要的請求接口已經準備好了,接下來需要在訪問nginx
時將請求轉發到我們測試的接口,配置轉發時需要用到nginx
的兩個關鍵字,分別是upstream
、location
。
- upstream:服務器組,配置請求分發到組內多台服務器。
- location:轉發的路徑前綴,如:"/user/",當我們訪問
http://127.0.0.1/user/1
時,就會執行該location
的轉發業務。
upstream轉發流程如下圖所示:

image
配置UpStream
在nginx.conf
文件http
內添加轉發的服務器組
(upstream),如下所示:
# 負載配置 upstream test { server 127.0.0.1:8080 weight=1; server 127.0.0.1:9090 weight=2; server 127.0.0.1:9000 backup; }
配置Location
在上面已經配置好了服務器組,我們需要把名為test
的服務器組作為代理的方式配置在location
,在location
的server
下新增一個location
,如下所示:
# 配置"/lb/"路徑的請求全部轉發到本地8080端口 location /lb/ { proxy_pass http://test/; 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_connect_timeout 50; proxy_read_timeout 50; proxy_send_timeout 50; }
重啟Nginx
我這裡是使用brew
的方式安裝的nginx
,所以重啟的命令如下所示:
brew services restart nginx
如果你是安裝包
的方式安裝:
# 進入安裝包目錄 cd /usr/local/nginx/sbin # 重載 ./nginx -s reload
權重配置
在nginx
中有一個權重的概念,根據權重值的大小來控制請求流量,當權重的配值越大時,流量分發就會越多,我們在test
服務器組內配置權重解釋:
-
server 127.0.0.1:8080 weight 1;
權重佔比為1/3
,每3次請求會轉發1次到這台服務器上。 -
server 127.0.0.1:9090 weight 2;
權重佔比為2/3
,每3次請求會轉發2次到這台服務器上。
備用配置
當我們在upstream
內的server
尾部添加backup
時,表示這台服務器是備用服務器,只有其他服務器都停機時才會啟用,我們更新時其實就利用的這一點。
運行測試
為了演示方便我們直接將本章測試項目package
打包後,通過--server.port
來指定運行的端口號來模擬多台服務器的場景。
# 啟動127.0.0.1:8080服務器 java -jar target/use-nginx-loadbalance-upgrade-service-0.0.1-SNAPSHOT.jar --server.port=8080 # 啟動127.0.0.1:9090服務器 java -jar target/use-nginx-loadbalance-upgrade-service-0.0.1-SNAPSHOT.jar --server.port=9090 # 啟動127.0.0.1:9000備用服務器 java -jar target/use-nginx-loadbalance-upgrade-service-0.0.1-SNAPSHOT.jar --server.port=9000
注意:使用多個終端窗口運行服務。
在nginx.conf
>server
中配置location
的轉發條件為/lb/
路徑前綴,所以我們訪問 http://127.0.0.1/lb/test (由於nginx
監聽的端口號是80,所以通過nginx
訪問轉發時不需要攜帶端口號)就會被轉發到test
服務器組內的服務器上。
測試點:權重轉發
curl http://localhost/lb/test 端口號:8080,接口訪問成功. curl http://localhost/lb/test 端口號:9090,接口訪問成功. curl http://localhost/lb/test 端口號:9090,接口訪問成功. curl http://localhost/lb/test 端口號:8080,接口訪問成功.
根據訪問的結果來看,8080
端口號的服務是每3次中請求了1次
,而9090
則是每3次中請求了2次
,這一點正是符合我們配置的權重(weight
),測試通過。
測試點:備用生效
我們把8080
、9090
這兩個服務都停掉,再次訪問 http://127.0.0.1/lb/test 。
curl http://localhost/lb/test 端口號:9000,接口訪問成功. curl http://localhost/lb/test 端口號:9000,接口訪問成功. curl http://localhost/lb/test 端口號:9000,接口訪問成功.
可以看到我們的備用服務器啟用了,已經把全部的請求流量轉發到9000
這台服務上,測試通過。
敲黑板,劃重點
當我們把8080
、9090
都停掉時,備用服務器會啟用,這時我們就可以來更新8080
、9090
這兩個服務的運行代碼,更新完成後重啟,只要8080
、9090
這兩台服務器有一台處於運行狀態,nginx
就不會把流量分發到備用的9000
,以此類推把全部的服務都更新完成。
代碼示例
如果您喜歡本篇文章請為源碼倉庫點個Star
,謝謝!!! 本篇文章示例源碼可以通過以下途徑獲取,目錄為use-nginx-loadbalance-upgrade-service
: