使用nginx的負(fù)載均衡機(jī)制實(shí)現(xiàn)用戶無(wú)感更新服務(wù)

知識(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ā)的步驟大約分為如下幾步:

  1. 域名解析到轉(zhuǎn)發(fā)服務(wù)器
  2. 轉(zhuǎn)發(fā)服務(wù)器會(huì)根據(jù)權(quán)重(weight)、備用(backup)配置轉(zhuǎn)發(fā)到統(tǒng)一網(wǎng)關(guān)
  3. 如果統(tǒng)一網(wǎng)關(guān)存在灰度的配置,需要根據(jù)身份或者頭信息過(guò)濾請(qǐng)求
  4. 轉(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ā)流程如下圖所示:

image

配置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,在locationserver下新增一個(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)行代碼,更新完成后重啟,只要80809090這兩臺(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

作者個(gè)人 博客
使用開源框架 ApiBoot 助你成為Api接口服務(wù)架構(gòu)師

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Nginx (engine x)是一個(gè)高性能的HTTP和反向代理服務(wù)器,也是一個(gè)IMAP/POP3/SMTP服務(wù)器...
    hhf_Engineer閱讀 2,292評(píng)論 0 1
  • Nginx實(shí)現(xiàn)負(fù)載均衡的原理: 負(fù)載均衡在服務(wù)端開發(fā)中算是一個(gè)比較重要的特性。因?yàn)镹ginx除了作為常規(guī)的Web服...
    Java機(jī)械師閱讀 864評(píng)論 0 1
  • 《老男孩Linux運(yùn)維》Nginx Documentation 集群簡(jiǎn)介 集群就是指一組(若干)相互獨(dú)立的計(jì)算機(jī),...
    Zhang21閱讀 3,511評(píng)論 0 51
  • Nginx實(shí)現(xiàn)負(fù)載均衡的原理: 負(fù)載均衡在服務(wù)端開發(fā)中算是一個(gè)比較重要的特性。因?yàn)镹ginx除了作為常規(guī)的Web服...
    java伯爵閱讀 304評(píng)論 0 0
  • 據(jù)說(shuō)讀詩(shī)要先讀李杜,我十分憤然。 杜甫先不說(shuō),單就一個(gè)李白已經(jīng)占據(jù)了我古詩(shī)詞課文中多少篇幅。 靜...
    胡若不歸閱讀 374評(píng)論 0 1

友情鏈接更多精彩內(nèi)容