Linux環境下Nginx及負載均衡

jxtxzzw發表於2019-05-15

Nginx 簡介

Nginx 是一個高效能的 HTTP 和反向代理 Web 伺服器,同時也提供了 IMAP/POP3/SMTP 服務。
前向代理作為客戶端的代理,服務端只知道代理的 IP 地址而不知道客戶端的 IP 地址。
1557749097576

Nginx 安裝

推薦使用 LNMP 一鍵安裝包,Ubuntu/CentOS 等各平臺都有提供,省去自己配置的過程。

如果需要單獨安裝 Nginx,可以去找各平臺的安裝包名稱。以 Ubuntu Desktop 19.04 為例,單獨安裝 Nginx 的命令如下:

sudo apt install nginx

1557750229828
Nginx 安裝後預設啟動,開啟瀏覽器輸入 http://127.0.0.1 檢查是否安裝成功。
1557750269605

練習 1

使用 tail -f /path/to/nginx/log/access.log 實時監控檔案變化,再分別本地訪問 127.0.01 和遠端訪問伺服器 IP 地址,比較兩次訪問的日誌有什麼不同?

Tips: Ubuntu Server 版預設沒有桌面,通過 SSH 連線到伺服器

  1. 開啟新終端,通過 SSH 連線到伺服器,再使用 curl 127.0.0.1 命令返回頁面原始檔
  2. 開啟客戶端瀏覽器,輸入伺服器 IP 地址
  3. 比較上面兩步對應的操作日誌有什麼區別
    剛才在 Ubuntu 預設的火狐瀏覽器開啟 127.0.0.1 時的訪問日誌如圖。
    1557750357418
    接下來換一臺電腦訪問 192.168.23.129。
    1557750398919
    1557750411791
    首先可以看到,UA 是不一樣的,這是因為我用了不同的瀏覽器,當然,訪問時間等也是不一樣的。
    最關鍵的一點,第一次訪問的 IP 是 127.0.0.1,是環回地址,而後一次訪問的 IP 是 192.168.23.1,這個是我 Windows 10 的 IP 地址。
    最後看一點實戰的內容——我的部落格的訪問日誌:
    1557750709656
    1557750722075
    從中可以看到類似的日誌記錄,不僅記錄了訪問者的 IP、UA,還記錄了訪問資源 URL 以及一些附加的資訊。
    同樣的,還有錯誤日誌,例如看一下 gitlab.error.log
    1557750810498
    有了這些日誌,管理員就方便排查問題了。

    Nginx 預設配置

    配置檔案:/etc/nginx/nginx.conf(如果是 LNMP 安裝的,則可能在 /usr/local/nginx/conf/nginx.conf)。
    可以用 less 檢視配置檔案,配置檔案預設的環境是全域性環境,即一個 main{},後面會定義使用者、工作程式等,以及 HTTP 服務、郵件服務。
    1557817139159
    下面主要講一下 HTTP 配置檔案。
    1557817159052
    首先在 HTTP{} 會有一些全域性的配置,包括訪問日誌、連線超時等資訊,隨後會給出一個或多個 server 表示多個虛擬主機。
    來看一下實戰的配置檔案。
    1557817278775
    1557817334696
    使用者和使用者組都是 www,配置了錯誤日誌的訪問路徑,工作模式是 epoll、IO 多路複用,單個程式的最大連線數是 51200。
    1557817394587
    配置了 fastcgi 相關資訊。

    Nginx 作為 HTTP 伺服器的配置

    Nginx 預設的靜態資原始檔夾為 /var/www/html(不同的安裝包可能有不同的預設路徑,例如可能為 /usr/local/nginx/www/html/default 或者其他目錄,也可以自己指定)。
    在預設目錄下,新建一個叫做 jxtxzzw.html 的檔案,隨便寫一點東西。
    1557817758381
    1557817709063
    然後在 nginx.conf 的 HTTP 結點中新增一個虛擬伺服器,並 sudo nginx -s reload 重新載入。
    1557817875799
    如圖,在 80 埠監聽,當使用者訪問的伺服器是 jxtxzzwtest.com 的時候,就定位到 /var/www/html/ 下,並當使用者沒有指定訪問的路徑的時候,預設訪問 jxtxzzw.html
    為了模擬域名解析的過程,修改 /etc/hosts 檔案,增加 jxtxzzwtest.com 的 IP 為 127.0.0.1
    1557818114250
    修改之後開啟瀏覽器訪問 jxtxzzwtest.com,可以看到剛才的頁面。
    1557818165684
    如何不購買新的二級域名和伺服器,利用該伺服器和已有的域名再做一個個人主頁呢?
    這就可以新增一個新的虛擬伺服器。
    重複上面的步驟,只是注意新增虛擬伺服器的時候取一個新的 server_name,例如 new.jxtxzzwtest.com,至於 location 寫什麼,就看個人主頁放在了哪個資料夾下面了。這些都可以根據自己需要修改。
    server {
    listen 80;
    server_name new.jxtxzzwtest.com;
    location / {
      index a_new_page.html;
      root /home/jxtxzzw/web/;
    }
    }
    
    隨後,在 hosts 模擬 DNS 解析,新增 127.0.0.1 new.jxtxzzwtest.com 之後就可以在瀏覽器訪問 new.jxtxzzwtest.com 來看到個人主頁了。

    練習 2

  4. 在配置檔案 nginx.conf 的 http 節點內新增一個虛擬伺服器,新建 /var/www/EXAMPLE.com 資料夾,該資料夾下新建 index.html 檔案寫入文字,重載入配置 sudo nginx -s reload (注:將本頁中的 EXAMPLE 替換成自己的名字拼音)
  5. 瀏覽器輸入 IP 地址,檢查是否生成 /var/log/nginx/EXAMPLE.access.log 檔案,同時檢查 /var/log/nginx/access.log 檔案是否有變化
  6. 修改自己客戶端電腦上的 hosts 檔案,新增兩行解析到伺服器 IP 地址
  7. 瀏覽器輸入 www.EXAMPLE.com,檢查是否生成 /var/log/nginx/EXAMPLE.access.log,同時監測 /var/log/nginx/access.log 和 /var/log/nginx/EXAMPLE.access.log 檔案的變化
    server {
    listen 80;
    server_name www.zzw.com;
    access_log /var/log/nginx/zzw.access.log;
    location / {
      index index.html;
      root /var/www/html/zzw.com/;
    }
    }
    
    1557818970811
    輸入 IP 地址,不論是本機訪問 127.0.0.1 還是另一臺電腦訪問 192.168.23.129,發現都只訪問了 Nginx 預設的安裝成功頁面,沒有進入 zzw.com。
    顯然的,只有 access.log 會有變化,記錄了本次訪問資訊。
    1557819148817
    而在新增了 hosts 以後,訪問 www.zzw.com 就會看到剛才輸入的資訊。
    1557819224946
    需要注意的是,在配置檔案中只定義了 www.zzw.com,沒有定義 zzw.com,所以,在訪問 zzw.com 的時候還是會跳轉到 Nginx 安裝成功的那個頁面。
    解決這個辦法可以在 server_name 後面增加一個別名。
    server_name www.zzw.com zzw.com;
    
    看到 zzw.access.log 和 access.log 都有了新的記錄。
    來看一些實戰的內容。
    1557819404635
    我的部落格,監聽了 80 埠,同時處理 www.jxtxzzw.comjxtxzzw.com 兩個伺服器名字,並對 80 埠的請求全部轉發到 443 埠。
    443 埠配置了一些關於 SSL 相關的資訊,並且匯入了 PHP 相關的配置。
    1557819497443
    同時,還有一個 gitlab.jxtxzzw.com 的虛擬主機,這個配置檔案將在下面詳述。

    負載均衡簡介

    1557900464912
    1557900479572
    1557900487750
    負載均衡轉發演算法:
    • 輪詢(Round Robin):為第一個請求選擇列表中的第一個伺服器,然後按順序向下移動列表直到結尾,然後迴圈
    • 最小連線(Least Connection):優先選擇連線數最少的伺服器,在普遍會話較長的情況下推薦使用
    • 雜湊(Hash):根據請求源的 IP 的雜湊來選擇要轉發的伺服器,這種方式可以一定程度上保證特定使用者能連結到相同的伺服器
      負載均衡演算法:
    • round:每個請求按時間順序逐一分配到不同的後端伺服器,如果後端伺服器當機,能自動刪除
    • weight:指定輪詢機率,weight 和訪問比率成正比,用於後端伺服器效能不均的情況
    • fiar(第三方):按後端伺服器的響應時間來分配請求,響應時間短的優先分配
    • ip_hash:每個請求按訪問 IP 的雜湊結果分配,每個訪客固定訪問一個後端伺服器,可以解決 session 的問題
    • url_hash(第三方):每個請求按 URL 的雜湊結果分配,不同訪客訪問相同的伺服器
      1557900812070
      預備 Web 伺服器環境:
    1. 配置兩臺 Apache(httpd) 作為 Web 伺服器,例如可以使用 XAMPP
    2. XAMPP 的訪問日誌在 /opt/lampp/logs/access.log
    3. 一臺 Ubuntu Desktop 的虛擬機器,192.168.23.129,作為 Nginx 伺服器
    4. 一臺 Ubuntu Desktop 的虛擬機器,192.168.23.128,作為第 1 臺 XAMPP 伺服器
    5. 一臺 Ubuntu Server 的虛擬機器,192.168.23.130,作為第 2 臺 XAMPP 伺服器
    6. 一臺 Windows 的物理機,192.168.23.1,用來訪問
      1557904366933
      1557904412893
      1557904436313
      在 nginx.conf 的 http 節點下新增以下程式碼後重新載入配置
      upstream first {
      server 192.168.23.128;
      server 192.168.23.130;
      }
      server {
      listen 80;
      server_name load.jxtxzzwtest.com;
      location / {
      proxy_pass http://first;
      }
      }
      
      修改電腦的 host 檔案,新增一個域名解析
      192.168.23.129 load.jxtxzzwtest.com
      
      1557904573224
      瀏覽器訪問 load.jxtxzzwtest.com,發現開啟了 XAMPP 的一個介面,說明代理成功了。
      但是到底訪問的是哪一個 XAMPP 呢?可以看一下日誌。
      在此之前,重新整理幾次,看看日誌會不會訪問了不同的頁面。
      日誌的觀察結果,可以看到 128 的那臺伺服器上收到了若干次來自 129 的轉發請求,而 130 的那臺伺服器上也收到了若干請求,但是觀察時間可以看到,兩臺伺服器上接受的請求是先後交替的,這意味著符合輪詢演算法的期望結果。
      更加直觀的方法,是可以修改其中一個 Apache 伺服器的主頁顯示。
      1557905255583
      簡單粗暴的方法,刪掉了 128 那臺伺服器的 index.html。
      然後重新整理頁面的效果就是交替出現 XAMPP 的 dashboard 和 Directory Listing。
      1557905322496
      重新整理以後變成下面這個頁面,兩個頁面在每次重新整理後交替顯示。
      1557905359160
      如果沒有交替顯示,有可能是瀏覽器做了快取,強制重新整理一下就好了。

      練習 3

  8. 在 nginx.conf 的 http 節點下新增 upstream second 方案,將 server 節點下的 proxy_pass 設為 second 後重載入配置,其中 IP 地址要換成自己伺服器的地址,瀏覽器訪問域名,監測 Nginx 伺服器的 /var/log/nginx/access.log 和兩臺 Web 伺服器的 /opt/lampp/logs/access.log 發現有什麼規律

    upstream second {
        server 192.168.1.102:80;
        server 192.168.1.103 weight=3;
    }
    
  9. 新增 upstream third 方案,重複上述實驗

    upstream third {
        ip_hash;
        server 192.168.1.102;
        server 192.168.1.103;
    }
    

    1557905657267
    1557905818420
    訪問日誌可以看出,交替比例變為 3:1。
    需要特別說明的是,瀏覽器可能存在快取,所以一定要去看日誌。
    換成 hash 以後,我只能刷出 Index of /dashboard 這個頁面,不論重新整理多少次,而檢視訪問日誌也確實發現我被轉發到了 130 這個伺服器上。
    換一臺裝置,可能(如果正好 hash 計算結果不同)就會被轉發到 128 的伺服器上。也可能還是訪問的 130 的伺服器。
    再來看一些關於 Nginx 代理的實戰的例子。
    第一個例子是 HTTPS 反向代理到 Docker,具體的配置過程可以看我的另一篇文章《Nginx代理HTTPS到Docker指定埠》(https://www.jxtxzzw.com/archives/4241),這裡只簡要的給出與反向代理、負載均衡相關的程式碼。
    1557906259949
    1557906274170
    第二個例子是 GitLab。
    如果不想用 GitLab 自帶的 Nginx 服務,而想要把 GitLab 作為一個虛擬主機統一在已有的 LNMP 服務中一起管理,可以用到反向代理。
    由於 GitLab 預設的是在 socket 中通訊,所以有點不太一樣。
    1557906387237
    1557906405665
    1557906423386
    這兩張截圖省略了 GitLab 中與 SSL 配置相關的程式碼。

    練習 4

  10. 利用 XAMPP,搭建一個能訪問資料庫的動態網站,並通過負載均衡伺服器訪問
  11. 比較 Nginx 伺服器和 Apache 伺服器的異同
    第一個練習,比較簡單,基本上只要復現本文內容即可,唯一的區別在於需要把本文中簡陋的 HTML 程式碼複雜化,加上與資料庫通訊的部分,例如,訪問資料庫並列出所有學生的姓名……
    由於上一次練習《MySQL備份與主備配置》已經配置了雙主結構,所以,在一個 PHP 頁面中加入增刪改查的功能,並把頁面複製到另一臺伺服器上就可以了,訪問會通過負載均衡,資料庫的訪問會通過雙主備份,保證了資料的一致。
    程式碼就不貼了。
    另外,歡迎訪問我的個人部落格呀,https://www.jxtxzzw.com/
    第二個練習,簡單說一下。
    Nginx 相對於 Apache 的優勢:
    • Apache 是同步多程式模型,一個連線對應一個程式,Nginx 是非同步的,多個連線(萬級別)可以對應一個程式
    • Nginx 的抗併發能力強很多,對資源需求更少
    • Nginx 支援反向代理
    • Nginx 支援 7 層負載均衡
      Apache 相對 Nginx 的優點:
    • Rewrite,比 Nginx 的 Rewrite 強大
    • 模組超多,基本想到的都可以找到
      一般來說,需要效能的 Web 服務,用 Nginx,如果不需要效能只求穩定,那就 Apache 吧。總之,就是看自己需求的。
      但是從個人使用經歷來看,我會推薦 Nginx 作為 Web 伺服器的首選。如果你是新手,什麼都沒接觸過,不妨先試試 Nginx?

相關文章