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

配置UpStream
在nginx.conf文件http內(nèi)添加轉(zhuǎn)發(fā)的服務(wù)器組(upstream),如下所示:
# 負(fù)載配置
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
在上面已經(jīng)配置好了服務(wù)器組,我們需要把名為test的服務(wù)器組作為代理的方式配置在location,在location的server下新增一個(gè)location,如下所示:
# 配置"/lb/"路徑的請(qǐng)求全部轉(zhuǎn)發(fā)到本地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
如果你是安裝包的方式安裝:
# 進(jìn)入安裝包目錄
cd /usr/local/nginx/sbin
# 重載
./nginx -s reload
權(quán)重配置
在nginx中有一個(gè)權(quán)重的概念,根據(jù)權(quán)重值的大小來(lái)控制請(qǐng)求流量,當(dāng)權(quán)重的配值越大時(shí),流量分發(fā)就會(huì)越多,我們?cè)?code>test服務(wù)器組內(nèi)配置權(quán)重解釋:
-
server 127.0.0.1:8080 weight 1;權(quán)重占比為1/3,每3次請(qǐng)求會(huì)轉(zhuǎn)發(fā)1次到這臺(tái)服務(wù)器上。 -
server 127.0.0.1:9090 weight 2;權(quán)重占比為2/3,每3次請(qǐng)求會(huì)轉(zhuǎn)發(fā)2次到這臺(tái)服務(wù)器上。
備用配置
當(dāng)我們?cè)?code>upstream內(nèi)的server尾部添加backup時(shí),表示這臺(tái)服務(wù)器是備用服務(wù)器,只有其他服務(wù)器都停機(jī)時(shí)才會(huì)啟用,我們更新時(shí)其實(shí)就利用的這一點(diǎn)。
運(yùn)行測(cè)試
為了演示方便我們直接將本章測(cè)試項(xiàng)目package打包后,通過(guò)--server.port來(lái)指定運(yùn)行的端口號(hào)來(lái)模擬多臺(tái)服務(wù)器的場(chǎng)景。
# 啟動(dòng)127.0.0.1:8080服務(wù)器
java -jar target/use-nginx-loadbalance-upgrade-service-0.0.1-SNAPSHOT.jar --server.port=8080
# 啟動(dòng)127.0.0.1:9090服務(wù)器
java -jar target/use-nginx-loadbalance-upgrade-service-0.0.1-SNAPSHOT.jar --server.port=9090
# 啟動(dòng)127.0.0.1:9000備用服務(wù)器
java -jar target/use-nginx-loadbalance-upgrade-service-0.0.1-SNAPSHOT.jar --server.port=9000
注意:使用多個(gè)終端窗口運(yùn)行服務(wù)。
在nginx.conf>server中配置location的轉(zhuǎn)發(fā)條件為/lb/路徑前綴,所以我們?cè)L問(wèn) http://127.0.0.1/lb/test (由于nginx監(jiān)聽的端口號(hào)是80,所以通過(guò)nginx訪問(wèn)轉(zhuǎn)發(fā)時(shí)不需要攜帶端口號(hào))就會(huì)被轉(zhuǎn)發(fā)到test服務(wù)器組內(nèi)的服務(wù)器上。
測(cè)試點(diǎn):權(quán)重轉(zhuǎn)發(fā)
curl http://localhost/lb/test
端口號(hào):8080,接口訪問(wèn)成功.
curl http://localhost/lb/test
端口號(hào):9090,接口訪問(wèn)成功.
curl http://localhost/lb/test
端口號(hào):9090,接口訪問(wèn)成功.
curl http://localhost/lb/test
端口號(hào):8080,接口訪問(wèn)成功.
根據(jù)訪問(wèn)的結(jié)果來(lái)看,8080端口號(hào)的服務(wù)是每3次中請(qǐng)求了1次,而9090則是每3次中請(qǐng)求了2次,這一點(diǎn)正是符合我們配置的權(quán)重(weight),測(cè)試通過(guò)。
測(cè)試點(diǎn):備用生效
我們把8080、9090這兩個(gè)服務(wù)都停掉,再次訪問(wèn) http://127.0.0.1/lb/test 。
curl http://localhost/lb/test
端口號(hào):9000,接口訪問(wèn)成功.
curl http://localhost/lb/test
端口號(hào):9000,接口訪問(wèn)成功.
curl http://localhost/lb/test
端口號(hào):9000,接口訪問(wèn)成功.
可以看到我們的備用服務(wù)器啟用了,已經(jīng)把全部的請(qǐng)求流量轉(zhuǎn)發(fā)到9000這臺(tái)服務(wù)上,測(cè)試通過(guò)。
敲黑板,劃重點(diǎn)
當(dāng)我們把8080、9090都停掉時(shí),備用服務(wù)器會(huì)啟用,這時(shí)我們就可以來(lái)更新8080、9090這兩個(gè)服務(wù)的運(yùn)行代碼,更新完成后重啟,只要8080、9090這兩臺(tái)服務(wù)器有一臺(tái)處于運(yùn)行狀態(tài),nginx就不會(huì)把流量分發(fā)到備用的9000,以此類推把全部的服務(wù)都更新完成。
代碼示例
如果您喜歡本篇文章請(qǐng)為源碼倉(cāng)庫(kù)點(diǎn)個(gè)Star,謝謝?。。?br>
本篇文章示例源碼可以通過(guò)以下途徑獲取,目錄為use-nginx-loadbalance-upgrade-service: