Nginx實現請求的負載均衡 + keepalived實現Nginx的高可用

後端高階工程師發表於2019-03-06

前言

使用叢集是網站解決高併發、海量資料問題的常用手段。當一臺伺服器的處理能力、儲存空間不足時,不要企圖去換更強大的伺服器,對大型網站而言,不管多麼強大的伺服器,都滿足不了網站持續增長的業務需求。這種情況下,更恰當的做法是增加一臺伺服器分擔原有伺服器的訪問及儲存壓力。

通過負載均衡排程伺服器,將來自瀏覽器的訪問請求分發到應用伺服器叢集中的任何一臺伺服器上,如果有更多的使用者,就在叢集中加入更多的應用伺服器,使應用伺服器的負載壓力不再成為整個網站的瓶頸。

摘自《大型網站技術架構_核心原理與案例分析》

環境準備

  • 192.168.0.221:nginx + keepalived master

  • 192.168.0.222:nginx + keepalived backup

  • 192.168.0.223:tomcat

  • 192.168.0.224:tomcat

  • 虛擬ip(VIP):192.168.0.200,對外提供服務的ip,也可稱作浮動ip

各個元件之間的關係圖如下:

Nginx實現請求的負載均衡 + keepalived實現Nginx的高可用

tomcat做應用伺服器

tomcat的安裝不在本部落格範圍之內,具體可參考virtualBox安裝centos,並搭建tomcat,tomcat的webapps下記得放自己的應用,我的是myWeb,如果大家也用我的myWeb,那麼index.jsp中的ip需要換成自己的


將192.168.0.223、192.168.0.224上的tomcat啟動起來,tomcat的路徑可能和我的不一致,需要寫成自己的

# cd /usr/local/tomcat7/bin
# ./startup.sh
複製程式碼

訪問myWeb如下

Nginx實現請求的負載均衡 + keepalived實現Nginx的高可用

nginx做負載均衡

nginx的安裝,本文就不講述了。

nginx.conf內容如下

user  root;            #執行使用者
worker_processes  1;        #啟動程式,通常設定成和cpu的數量相等

#全域性錯誤日誌及PID檔案
error_log  /usr/local/nginx/logs/error.log;
error_log  /usr/local/nginx/logs/error.log  notice;
error_log  /usr/local/nginx/logs/error.log  info;
pid        /usr/local/nginx/logs/nginx.pid;

# 工作模式及連線數上線
events 
{
    use epoll;            #epoll是多路複用IO(I/O Multiplexing)中的一種方式,但是僅用於linux2.6以上核心,可以大大提高nginx的效能

    worker_connections  1024;    #單個後臺worker process程式的最大併發連結數
}

#設定http伺服器,利用它的反向代理功能提供負載均衡支援
http 
{
    include       mime.types;
    default_type  application/octet-stream;

    #設定請求緩衝
    server_names_hash_bucket_size  128;
    client_header_buffer_size   32K;
    large_client_header_buffers  4 32k;
    # client_max_body_size   8m;

    #sendfile 指令指定 nginx 是否呼叫 sendfile 函式(zero copy 方式)來輸出檔案,對於普通應用,
    #必須設為 on,如果用來進行下載等應用磁碟IO重負載應用,可設定為 off,以平衡磁碟與網路I/O處理速度,降低系統的uptime.
    sendfile        on;
    tcp_nopush     on;
    tcp_nodelay    on;

    #連線超時時間
    keepalive_timeout  65;

    #開啟gzip壓縮,降低傳輸流量
    gzip  on;
    gzip_min_length    1k;
    gzip_buffers    4 16k;
    gzip_http_version  1.1;
    gzip_comp_level  2;
    gzip_types  text/plain application/x-javascript text/css  application/xml;
    gzip_vary on;

    #新增tomcat列表,真實應用伺服器都放在這
    upstream tomcat_pool 
    {
       #server tomcat地址:埠號 weight表示權值,權值越大,被分配的機率越大;
    server 192.168.0.223:8080 weight=4 max_fails=2 fail_timeout=30s;
      server 192.168.0.224:8080 weight=4 max_fails=2 fail_timeout=30s;
    }

    server 
    {
        listen       80;        #監聽埠    
        server_name  localhost;

    #預設請求設定
    location / {
        proxy_pass http://tomcat_pool;    #轉向tomcat處理
    }

    #所有的jsp頁面均由tomcat處理
    location ~ \.(jsp|jspx|dp)?$
    {
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_pass http://tomcat_pool;    #轉向tomcat處理
    }

    #所有的靜態檔案直接讀取不經過tomcat,nginx自己處理
    location ~ .*\.(htm|html|gif|jpg|jpeg|png|bmp|swf|ioc|rar|zip|txt|flv|mid|doc|ppt|pdf|xls|mp3|wma)$ 
    { 
        expires  30d;
    }
    location ~ .*\.(js|css)?$
    {
       expires  1h;
    }

    #定義錯誤提示頁面
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }

    }
}
複製程式碼

主從nginx的配置檔案完全一樣,nginx.conf配置可複雜可簡單,大家根據自己的情況自行配置,照搬上述配置也是可以的。

配置好後,啟動nginx,路徑要寫自己的

# cd /usr/local/nginx/sbin
# ./nginx
複製程式碼

訪問nginx,效果如下:

Nginx實現請求的負載均衡 + keepalived實現Nginx的高可用

Nginx實現請求的負載均衡 + keepalived實現Nginx的高可用

兩臺nginx伺服器服務正常,此時是沒有主從之分的,兩者級別一樣高,當配置keepalived之後就有了主從之分了。

keepalived實現nginx高可用(HA)

keepalived的安裝本文就不講述了。keepalived作用其實在第一張圖中已經有所體現,主要起到兩個作用:實現VIP到本地ip的對映; 以及檢測nginx狀態。

master上的keepalived.conf內容如下:

global_defs {
    notification_email {
        997914490@qq.com
    }
    notification_email_from sns-lvs@gmail.com
    smtp_server smtp.hysec.com
    smtp_connection_timeout 30
    router_id nginx_master        # 設定nginx master的id,在一個網路應該是唯一的
}
vrrp_script chk_http_port {
    script "/usr/local/src/check_nginx_pid.sh"    #最後手動執行下此指令碼,以確保此指令碼能夠正常執行
    interval 2                          #(檢測指令碼執行的間隔,單位是秒)
    weight 2
}
vrrp_instance VI_1 {
    state MASTER            # 指定keepalived的角色,MASTER為主,BACKUP為備
    interface eth0            # 當前進行vrrp通訊的網路介面卡(當前centos的網路卡)
    virtual_router_id 66        # 虛擬路由編號,主從要一直
    priority 100            # 優先順序,數值越大,獲取處理請求的優先順序越高
    advert_int 1            # 檢查間隔,預設為1s(vrrp組播週期秒數)
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    track_script {
    chk_http_port            #(呼叫檢測指令碼)
    }
    virtual_ipaddress {
        192.168.0.200            # 定義虛擬ip(VIP),可多設,每行一個
    }
}
複製程式碼

backup上的keepalived.conf內容如下:

global_defs {
    notification_email {
        997914490@qq.com
    }
    notification_email_from sns-lvs@gmail.com
    smtp_server smtp.hysec.com
    smtp_connection_timeout 30
    router_id nginx_backup              # 設定nginx backup的id,在一個網路應該是唯一的
}
vrrp_script chk_http_port {
    script "/usr/local/src/check_nginx_pid.sh"
    interval 2                          #(檢測指令碼執行的間隔)
    weight 2
}
vrrp_instance VI_1 {
    state BACKUP                        # 指定keepalived的角色,MASTER為主,BACKUP為備
    interface eth0                      # 當前進行vrrp通訊的網路介面卡(當前centos的網路卡)
    virtual_router_id 66                # 虛擬路由編號,主從要一直
    priority 99                         # 優先順序,數值越大,獲取處理請求的優先順序越高
    advert_int 1                        # 檢查間隔,預設為1s(vrrp組播週期秒數)
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    track_script {
        chk_http_port                   #(呼叫檢測指令碼)
    }
    virtual_ipaddress {
        192.168.0.200                   # 定義虛擬ip(VIP),可多設,每行一個
    }
}
複製程式碼

nginx檢測指令碼check_nginx_pid.sh內容如下:

#!/bin/bash
A=`ps -C nginx --no-header |wc -l`        
if [ $A -eq 0 ];then                            
    /usr/local/nginx/sbin/nginx                #重啟nginx
    if [ `ps -C nginx --no-header |wc -l` -eq 0 ];then    #nginx重啟失敗
        exit 1
    else
        exit 0
    fi
else
    exit 0
fi
複製程式碼

啟動keepalived

# service keepalived start
複製程式碼

訪問VIP,效果如下:

Nginx實現請求的負載均衡 + keepalived實現Nginx的高可用

我們來看下keepalived的日誌資訊

master(192.168.0.221):

Nginx實現請求的負載均衡 + keepalived實現Nginx的高可用

backup(192.168.0.222):

Nginx實現請求的負載均衡 + keepalived實現Nginx的高可用

當我們把master上的keepalived停掉(模擬當機),再來看下keepalived日誌

原master(192.168.0.221):

Nginx實現請求的負載均衡 + keepalived實現Nginx的高可用

原backup(192.168.0.222):

Nginx實現請求的負載均衡 + keepalived實現Nginx的高可用

通過VIP可以正常訪問服務,前端請求感受不到後端nginx的切換;重新喚醒原master(192.168.0.221)的測試這裡就不進行了,大家自行測試

注意點

1、執行指令碼時報錯:/bin/sh^M: bad interpreter: 沒有那個檔案或目錄

因為作業系統是windows,我在windows下編輯的指令碼,所以有可能有不可見字元。指令碼檔案是DOS格式的, 即每一行的行尾以回車符和換行符來標識, 其ASCII碼分別是0x0D, 0x0A。可以有很多種辦法看這個檔案是DOS格式的還是UNIX格式的, 還是MAC格式的

解決方法:

vim filename
:set ff? #可以看到dos或unix的字樣. 如果的確是dos格式的。
:set ff=unix #把它強制為unix格式的, 然後存檔退出。
複製程式碼

再次執行指令碼。

從windows編輯檔案再拷貝到linux時要特別注意,另外,指令碼需要賦予可執行許可權才能執行,可執行檔案的一種直觀表現就是檔案本身呈綠色。

2、負載均衡最好進行多瀏覽器測試,有些瀏覽器會快取,會產生沒有負載均衡的效果。

例如我這次測試中谷歌瀏覽器就出現了類似的情況(還沒搞清楚是否是快取的原因),火狐,360、IE瀏覽器都是正常的負載均衡效果。

3、請求走向

訪問虛擬IP(VIP),keepalived將請求對映到本地nginx,nginx將請求轉發至tomcat,例如:http://192.168.0.200/myWeb/,被對映成http://192.168.0.221/myWeb/,埠是80,而221上nginx的埠正好是80;對映到nginx上後,nginx再進行請求的轉發。

keepalived伺服器的ip情況

Nginx實現請求的負載均衡 + keepalived實現Nginx的高可用

VIP總會在keepalived伺服器中的某一臺上,也只會在其中的某一臺上;VIP繫結的伺服器上的nginx就是master,當VIP所在的伺服器當機了,keepalived會將VIP轉移到backup上,並將backup提升為master。

4、VIP也稱浮動ip,是公網ip,與域名進行對映,對外提供服務; 其他ip一般而言都是內網ip, 外部是直接訪問不了的


相關文章