日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

背景

基于Springboot應用以war包的形式運行在Tomcat容器中,當更新war包時會有一段時間服務返回404,這對于線上服務是不可接受的。4層的負載均衡可以自動將80端口關閉的節點下線,但由于內網服務器位于堡壘機后方,根據公司規定不能自行配置SSH服務,所以無法執行遠程腳本。所以只能通過別的方式實現。

實驗素材

Nginx和Tomcat配合實現Java Web服務熱部署

 

  1. Nginx 作為web server和7層負載均衡
  2. tomcat * 2 作為應用后端
  3. gitlab-ce 代碼版本控制
  4. jenkins 發布平臺

基本原理

基本的原理就是讓Nginx后方有3個Tomcat容器,其中1個是active,1個是standby,正常情況下不會訪問到standby的容器,但可以通過額外的手段保證standby的容器是可以提供服務的,在發布前先更新所有的standby節點,驗證沒問題之后更新active的容器,來保證服務不會中斷。

實際操作

創建springboot項目

參考Springboot使用內置和獨立tomcat以及其他思考。

編寫同一個接口的不同版本

// tag v1
@RestControllerpublic class HelloController {    @GetMApping("/hello")
    public String hello() {        return "V1";
    }}
// tag v2
@RestControllerpublic class HelloController {    @GetMapping("/hello")
    public String hello() {        return "V2";
    }}

打包

mvn clean package -Dmaven.test.skip=true

創建兩個tomcat容器

Docker run -itd --name tomcat-active -v /tmp/tomcat/active:/usr/local/tomcat/webapps -p 32771:8080 tomcat
docker run -itd --name tomcat-standby -v /tmp/tomcat/standby:/usr/local/tomcat/webapps -p 32772:8080 tomcat

將war包拷貝到容器中

可能是docker toolbox的問題,無法掛載目錄,所以只好把war包手動拷貝進去。

docker cp ~/workspace/spring-demo/target/spring-demo-0.0.1-SNAPSHOT.war tomcat-active:/usr/local/tomcat/webapps/
docker cp ~/workspace/spring-demo/target/spring-demo-0.0.1-SNAPSHOT.war tomcat-standby:/usr/local/tomcat/webapps/

訪問兩個容器中的服務

稍等片刻兩個容器中的服務會自動部署,就可以分別通過相應的端口訪問了,簡單壓測一下QPS可以達到2000+且沒有報錯。

$ wrk -c 20 -d 10 -t 4 http://192.168.99.100:32771/spring-demo-0.0.1-SNAPSHOT/hello
Running 10s test @ http://192.168.99.100:32771/spring-demo-0.0.1-SNAPSHOT/hello
  4 threads and 20 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    10.20ms    8.70ms 122.66ms   81.20%
    Req/Sec   554.18    167.66     1.04k    63.25%
  22088 requests in 10.02s, 2.43MB read
Requests/sec:   2203.76
Transfer/sec:    247.89KB
$ wrk -c 20 -d 10 -t 4 http://192.168.99.100:32772/spring-demo-0.0.1-SNAPSHOT/hello
Running 10s test @ http://192.168.99.100:32772/spring-demo-0.0.1-SNAPSHOT/hello
  4 threads and 20 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    11.30ms   14.24ms 186.52ms   92.95%
    Req/Sec   557.54    207.91     1.24k    67.17%
  22025 requests in 10.03s, 2.42MB read
Requests/sec:   2196.36
Transfer/sec:    247.05KB

配置Nginx

upstream ha {
    server 192.168.99.100:32771;
    server 192.168.99.100:32772 backup;
}server {
    listen       80;
    server_name  _;
    location / {
        proxy_next_upstream http_502 http_504 http_404 error timeout invalid_header;
        proxy_pass   http://ha/spring-demo-0.0.1-SNAPSHOT/;
    }}

注意:默認情況下只會轉發GET/HEAD/PUT/DELETE/OPTIONS這種冪等的請求,而不會轉發POST請求,如果需要對POST請求也做轉發,就需要加上non_idempotent配置,整體配置如下

upstream ha {
    server 192.168.99.100:32771;
    server 192.168.99.100:32772 backup;
}server {
    listen       80;
    server_name  _;
    location / {
        proxy_next_upstream http_502 http_504 http_404 error timeout invalid_header non_idempotent;
        proxy_pass   http://ha/spring-demo-0.0.1-SNAPSHOT/;
    }}

注意proxy_next_upstream http_502 http_504 http_404 error timeout invalid_header;這行,這里就是表示把訪問當前的upstream返回了這些狀態碼的請求轉發到upstream中的下一臺機器,在我們現在的應用場景下,當war包發布時,正在更新war包的tomcat會返回404,也就是對應http_404,如果不配置這行,是不會做轉發的。

但這樣簡單的配置還會有一個問題,那就是Nginx不會把出問題的后端從upstream中摘除,也就是說請求還會訪問到這個正在更新中的realserver,只是Nginx會再把請求轉發到下一臺好的realserver上,這樣會增加一些耗時。目前有三種方式可以實現對Nginx負載均衡的后端節點服務器進行健康檢查,具體參考Nginx負載均衡

通過Nginx壓測

基本測試

  1. 兩個tomcat節點均正常的情況下壓測
$ wrk -c 20 -d 10 -t 4 http://192.168.99.100:32778/hello
Running 10s test @ http://192.168.99.100:32778/hello
  4 threads and 20 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    57.36ms   32.06ms 335.36ms   71.29%
    Req/Sec    89.29     48.20   390.00     85.25%
  3577 requests in 10.05s, 562.30KB read
Requests/sec:    355.77
Transfer/sec:     55.93KB

和上面沒有經過Nginx的壓測相比,最明顯的變化就是QPS下降了84%,平均響應時間增加了5倍,猜測可能是因為Nginx使用的默認配置中worker_processes 1;的問題。

  1. 在開始壓測后立即刪除tomcat-active容器中的war包和目錄,結果如下
$ wrk -c 20 -d 10 -t 4 http://192.168.99.100:32778/hello
Running 10s test @ http://192.168.99.100:32778/hello
  4 threads and 20 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    57.29ms   28.69ms 181.88ms   67.38%
    Req/Sec    87.93     39.51   240.00     75.25%
  3521 requests in 10.05s, 553.50KB read
Requests/sec:    350.22
Transfer/sec:     55.05KB

同樣沒有非200的響應,而且整體和正常情況相當。

  1. 只有standby節點工作的情況下壓測
$ wrk -c 20 -d 10 -t 4 http://192.168.99.100:32778/hello
Running 10s test @ http://192.168.99.100:32778/hello
  4 threads and 20 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    72.12ms   35.99ms 240.89ms   68.34%
    Req/Sec    70.04     31.84   180.00     76.50%
  2810 requests in 10.05s, 441.71KB read
Requests/sec:    279.48
Transfer/sec:     43.93KB

可以看到,響應時間有明顯的增加,QPS也有明顯的下降,也驗證了上面說的響應是404的請求會被轉發到正常工作的節點,但有問題的節點不會被摘除導致的響應時間變長的問題。

進一步測試

為了消除上面測試中可能存在war包刪除后對服務的影響還沒有生效,壓測就已經結束的可能,將壓測時間調長,增加至60s。

  1. 兩個節點都正常的情況
$ wrk -c 20 -d 60 -t 4 http://192.168.99.100:32778/hello
Running 1m test @ http://192.168.99.100:32778/hello
  4 threads and 20 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    55.53ms   28.10ms 306.58ms   70.07%
    Req/Sec    91.52     39.35   300.00     69.23%
  21906 requests in 1.00m, 3.36MB read
Requests/sec:    364.66
Transfer/sec:     57.32KB

整體情況和上面10s的測試相同。查看日志發現backup節點沒有接收到任何請求。為了驗證是否是worker_processes配置導致的,把這個值改成4之后重新測試,結果如下

$ wrk -c 20 -d 60 -t 4 http://192.168.99.100:32778/hello
Running 1m test @ http://192.168.99.100:32778/hello
  4 threads and 20 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    41.55ms   24.92ms 227.15ms   72.21%
    Req/Sec   125.06     46.88   373.00     71.76%
  29922 requests in 1.00m, 4.59MB read
Requests/sec:    498.11
Transfer/sec:     78.29KB

可以看到,有了將近20%的提升,但還是不太符合預期。

  1. 開始測試后立即更新active節點的war包
$ wrk -c 20 -d 60 -t 4 http://192.168.99.100:32778/hello
Running 1m test @ http://192.168.99.100:32778/hello
  4 threads and 20 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    54.40ms   33.76ms 329.73ms   70.53%
    Req/Sec    95.85     56.28   420.00     81.60%
  22914 requests in 1.00m, 3.52MB read
Requests/sec:    381.42
Transfer/sec:     59.95KB

沒有明顯變化,測試開始后有一段時間standby節點收到請求,后面請求又全部指向了active節點。可能是因為服務太簡單,重新加載的太快,只有很少量(5750)的請求轉發到了standby節點,所以對整體結果影響不大。 3. 開始測試后立即刪除active節點的war包

$ wrk -c 20 -d 60 -t 4 http://192.168.99.100:32778/hello
Running 1m test @ http://192.168.99.100:32778/hello
  4 threads and 20 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    72.11ms   34.33ms 346.24ms   69.54%
    Req/Sec    70.16     29.78   191.00     67.23%
  16813 requests in 1.00m, 2.58MB read
Requests/sec:    279.84
Transfer/sec:     43.99KB

刪除節點后,所有的請求都會先請求active,然后被Nginx轉發至standby,所以吞吐量有明顯下降,延遲也有明顯的提升。

效果測試

  1. 直接訪問active
$ wrk -c 20 -d 60 -t 4 http://10.75.1.42:28080/web-0.0.1-SNAPSHOT/hello
Running 1m test @ http://10.75.1.42:28080/web-0.0.1-SNAPSHOT/hello
  4 threads and 20 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency     5.56ms   25.16ms 203.83ms   95.82%
    Req/Sec     7.54k     0.91k    8.31k    84.44%
  1803421 requests in 1.00m, 217.03MB read
Requests/sec:  30006.18
Transfer/sec:      3.61MB

服務器的性能果然還是比本地強太多。

  1. 在進行性能壓測期間發布新版本
$ wrk -c 20 -d 60 -t 4 http://10.75.1.42:28080/web-0.0.1-SNAPSHOT/hello
Running 1m test @ http://10.75.1.42:28080/web-0.0.1-SNAPSHOT/hello
  4 threads and 20 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency     4.47ms   22.31ms 401.95ms   96.67%
    Req/Sec     7.58k     0.88k    8.26k    87.12%
  1811240 requests in 1.00m, 285.84MB read
  Non-2xx or 3xx responses: 72742
Requests/sec:  30181.93
Transfer/sec:      4.76MB

發布新版本導致4%的請求失敗。

  1. 通過Nginx訪問服務
$ wrk -c 20 -d 60 -t 4 http://10.75.1.42:28010/web/hello
Running 1m test @ http://10.75.1.42:28010/web/hello
  4 threads and 20 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency     2.94ms   16.21ms 248.18ms   98.01%
    Req/Sec     6.02k   551.52     6.92k    83.38%
  1437098 requests in 1.00m, 260.33MB read
Requests/sec:  23948.20
Transfer/sec:      4.34MB

雖然服務器配置的worker_processes auto,實際上開了40個進程,但仍然達不到直接訪問JAVA服務的吞吐量。

  1. 通過Nginx壓測期間發布新版本
$ wrk -c 20 -d 60 -t 4 http://10.75.1.42:28010/web/hello
Running 1m test @ http://10.75.1.42:28010/web/hello
  4 threads and 20 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency     4.09ms   20.50ms 402.11ms   97.12%
    Req/Sec     5.89k   733.62     6.86k    84.85%
  1404463 requests in 1.00m, 253.67MB read
Requests/sec:  23401.54
Transfer/sec:      4.23MB

可以看到,延遲明顯變大了,但總體的QPS沒有明顯下降,還是因為存在一些轉發。

思考

原來是一臺機器上運行一個tomcat容器,現在要運行兩個,那么會對機器的負載造成多大的影響呢?可以通過visualvm連接上遠程tomcat來觀察對內存和CPU的占用

Nginx和Tomcat配合實現Java Web服務熱部署

 


Nginx和Tomcat配合實現Java Web服務熱部署

 

可以看到正常情況下,backup容器對服務器的負載基本可以忽略不計。即便是在發布期間,backup容器也只是在active容器重新載入期間承擔職責,之后馬上就恢復了。

Nginx和Tomcat配合實現Java Web服務熱部署

 


Nginx和Tomcat配合實現Java Web服務熱部署

 

新版本在線上正式運行之后為保證下一次發布新版本時backup版本是最新的,需要再發布一下backup版本,當然這時流量都在active節點上,對backup節點的發布更新操作不會對負載有什么影響。

Nginx和Tomcat配合實現Java Web服務熱部署

 

總結

可以通過Nginx的backup機制可以保證服務不中斷的情況下發布新版本。總體的發布流程如下:

  1. 發布新版本到active容器
  2. 確認發布的新版本穩定后發布新版本到backup容器

優勢

  1. 任意一臺機器上在任意時刻都保證有一個tomcat容器是可用的,保證服務不中斷
  2. 從直觀上的分機器上線改為直接全量上線,并且保證如果上線的新版本有問題時也不會影響線上服務

劣勢

  1. 需要上線兩次
  2. 需要在tomcat容器所在的機器上安裝Nginx和作為backup的tomcat的容器
  3. backup容器在“待機”時的消耗


鏈接:https://juejin.im/post/6867088509245603854
來源:掘金

分享到:
標簽:部署 服務
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定