Nginx 詳細教程

若塵發表於2022-03-16

Nginx

1. 基本概念

概述

  • Nginx 是一個高效能的 HTTP 和反向代理伺服器
  • 特點是佔有記憶體少,併發能力強
  • 專為效能優化而開發,效能是其最最要的考量

反向代理

  • 談反向代理之前我們先來了解一下正向代理,比如現在我們要訪問 www.google.com,谷歌大陸目前是不能直接訪問的,那麼我們就可以通過在瀏覽器配置代理伺服器進行訪問(如下圖)
    在這裡插入圖片描述
  • 接下來我們介紹反向代理,客戶端對代理無感知,客戶端不需要任何配置,我們只需要將請求傳送到反向代理伺服器,然後由反向代理伺服器去選擇目標伺服器獲取資料後,再返回給客戶端。此時反向代理伺服器和目標伺服器對外就是一個伺服器。顯然,反向代理對外暴露的是反向代理伺服器,隱藏了真實伺服器
  • 比如下圖中,我們想目標伺服器發出請求時,由反向代理伺服器選擇 tomcat 伺服器 8001 埠,獲取資料後,再將資料返回給客戶端
    在這裡插入圖片描述

負載均衡

  • 客戶端傳送多個請求到伺服器,伺服器與資料庫互動處理請求,處理完畢後,再將結果返回給客戶端
    在這裡插入圖片描述
  • 這種架構模式適用於早期系統單一簡單,併發較少的情況。隨著資訊數量的不斷增長,訪問量和請求量的飛速增長,伺服器效能就會達到瓶頸,此時我們應該如何解決?
  • 首先想到的是提升伺服器的配置,但是隨著摩爾定律的日益失效,硬體的效能提升已經不能滿足日益提升的效能需求。另外一個方法是我們可以增加伺服器的數量,將請求分發到各個伺服器上,這就是我們說的 負載均衡
  • 如下圖,將 15 個請求分發到三臺伺服器上,理想狀態是每臺伺服器 3 個請求
    在這裡插入圖片描述

動靜分離

  • 為了加快網站的解析速度,可以把動態頁面和靜態頁面由不同的伺服器來解析,加快解析速度,降低原來單個伺服器的壓力
    在這裡插入圖片描述

2. Nginx 安裝、命令和配置檔案

Linux 中安裝 Nginx

  • 安裝 PCRE

    PCRE 作用是讓 Nginx 支援 Rewrite 功能。
    cd /usr/src/
    wget http://downloads.sourceforge.net/project/pcre/pcre/8.37/pcre-8.37.tar.gz

    在這裡插入圖片描述

    tar zxvf pcre-8.37.tar.gz

    在這裡插入圖片描述

    cd pcre-8.37/
    ./configure
    make && make install

    在這裡插入圖片描述

    pcre-config --version

    在這裡插入圖片描述

  • 安裝編譯工具及庫檔案

    yum -y install make zlib zlib-devel gcc-c++ libtool  openssl openssl-devel

    在這裡插入圖片描述

  • 安裝 Nginx

    cd /usr/src/
    wget http://nginx.org/download/nginx-1.12.2.tar.gz

    在這裡插入圖片描述

    tar zxvf nginx-1.12.2.tar.gz

    在這裡插入圖片描述

    cd nginx-1.12.2/
    ./configure
    make && make install

    在這裡插入圖片描述

     /usr/local/nginx/sbin/nginx -v

    在這裡插入圖片描述

  • 安裝成功後,在 usr 多出來一個資料夾 local/nginx,啟動指令碼為 /nginx/sbin/nginx
  • 測試

    cd /usr/local/nginx/sbin
    ./nginx
    ps -ef | grep nginx

    在這裡插入圖片描述
    直接訪問 IP 地址可以看到如下介面
    在這裡插入圖片描述

    防火牆相關操作

    • 檢視開放的埠號:firewall-cmd --list-all
    • 設定開放的埠號:firewall-cmd --add-service=http --permanent
      eg:sudo firewall-cmd --add-port=80/tcp --permanent
    • 重啟防火牆:firewall-cmd --reload
    • 關閉防火牆:systemctl stop firewalld
    • 永久關閉防火牆:systemctl disable firewalld

Nginx 常用命令

使用 nginx 命令前要進入 nginx 目錄:cd /usr/local/nginx/sbin
  • 檢視 nginx 版本號:./nginx -v
    在這裡插入圖片描述
  • 啟動 nginx:./nginx
    在這裡插入圖片描述
  • 關閉 nginx:./nginx -s stop
    在這裡插入圖片描述
  • 過載 nginx:./nginx -s reload
    在這裡插入圖片描述
  • 配置 systemctl

    配置 systemctl 後的啟動方式

    • 狀態:ssytemctl status nginx
    • 啟動:systemctl start nginx
    • 關閉:systemctl stop nginx
    • 重啟:systemctl restart nginx

    配置方法

    • nginx.service

      cd /usr/lib/systemd/system
      vim nginx.service
    • 將以下內容複製進去<font color="red">(註釋的內容不要放進去!!!)</font>

      [Unit]  //對服務的說明
      Description=nginx - high performance web server  //描述服務
      After=network.target remote-fs.target nss-lookup.target  //描述服務型別
      
      [Service]  //服務的一些具體執行引數的設定
      Type=forking  //後臺執行的形式
      PIDFile=/usr/local/nginx/logs/nginx.pid  //PID檔案的路徑
      ExecStartPre=/usr/local/nginx/sbin/nginx -t -c /usr/local/nginx/conf/nginx.conf  //啟動
      準備
      ExecStart=/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf  //啟動命令
      ExecReload=/usr/local/nginx/sbin/nginx -s reload  //重啟命令
      ExecStop=/usr/local/nginx/sbin/nginx -s stop  //停止命令
      ExecQuit=/usr/local/nginx/sbin/nginx -s quit  //快速停止
      PrivateTmp=true  //給服務分配臨時空間
      
      [Install]
      WantedBy=multi-user.target  //服務使用者的模式
    • 賦予許可權:chmod +x /usr/lib/systemd/system/nginx.service
    • 啟動服務

      // 啟動服務之前,需要先過載 systemctl 命令
      systemctl daemon-reload
      systemctl start nginx.service
      報錯直接 kill -9 殺死重新拉起即可

Nginx 配置檔案

Nginx 配置檔案位置:/usr/local/nginx/conf/nginx.conf

配置檔案由三部分組成

  • 第一部分:全域性塊(從配置檔案開始到 events 塊之間的內容)

    • 主要設定一些影響 Nginx 伺服器整體執行的配置指令,主要包括配置執行 Nginx 伺服器的使用者(組)、允許生成的 worker process 數、程式 PID 存放路徑、日誌存放路徑和型別以及配置檔案的引入等
    • worker_processes 1:Nginx 伺服器併發處理的值,worker_processes 值越大,可以支援的併發處理數量越多
  • 第二部分:events 塊

    events {
        worker_connections  1024;
    }
    • events 塊涉及的指令主要影響 Nginx 伺服器與使用者的網路連線,比如 worker_connections 1024; 表示 Nginx 支援的最大連線數為 1024
  • 第三部分:http 塊(http 塊也可以包括 http 全域性塊、server 塊)

    • http 全域性塊:http 全域性塊配置的指令包括檔案引入、MIME-TYPE 型別、日誌自定義、連線超時時間、單連結請求數上限等
    • server 塊:這塊和虛擬主機有密切聯絡,每個 http 塊可以包括多個 server 塊,每個 server 塊就相當於一個虛擬主機,每個 server 塊也分為全域性 server 塊,以及可以同時包含多個 location 塊

      • 全域性 server 塊:最常見的配置是本虛擬主機的監聽配置和本虛擬主機的名稱或 IP 配置
      • location 塊:主要作用的是基於 Nginx 伺服器接收到的請求字串(eg:server_name/uri-string),對虛擬主機名稱(也可以是 IP 別名)之外的字串(eg:/uri-string)進行匹配,對特定的請求進行處理。地址定向、資料快取和應答控制等功能,還有許多第三方模組的配置也在這裡進行

3. Nginx 配置例項

<0> 準備工作

  • 安裝 tomcat,使用預設埠號 8080

    cd /usr/src
    wget https://mirrors.cnnic.cn/apache/tomcat/tomcat-8/v8.5.73/bin/apache-tomcat-8.5.73.tar.gz
    tar zxvf apache-tomcat-8.5.73.tar.gz 

    在這裡插入圖片描述

  • 安裝 jdk:可參考此教程 Linux 安裝和配置 JDK13
  • 啟動 tomcat

    cd /usr/src/apache-tomcat-8.5.73/bin/
    ./startup.sh 

    在這裡插入圖片描述

  • 訪問 tomcat(伺服器要開放 8080 埠)
    在這裡插入圖片描述

    <1> 反向代理 • 例項一

  • 實現效果:開啟瀏覽器,在瀏覽器地址輸入地址 www.123.com,跳轉到 Linux 系統 tomcat 主頁面中
  • 過程分析:Windows 瀏覽器不能直接訪問t omcat,要通過 nginx 反向代理到 tomcat
    在這裡插入圖片描述
  • 具體配置

    • 在 Windows 系統的 host 檔案進行域名和 ip 對應關係的配置 C:\Windows\System32\drivers\etc\hosts
      在這裡插入圖片描述
      在這裡插入圖片描述
    • 在 nginx 進行請求轉發的配置(反向代理)

      cd /usr/local/nginx/conf/
      vim nginx.conf

      在這裡插入圖片描述

    • 測試

      //啟動 nginx
      cd /usr/local/nginx/sbin
      ./nginx

      在這裡插入圖片描述

<2> 反向代理 • 例項二

  • 實現效果:使用 nginx 反向代理,根據訪問的路徑跳轉到不同埠的服務中,nginx 監聽埠為 9001

    • 訪問 http://118.195.179.192:9001/edu/ 直接跳轉到 127.0.0.1:8080
    • 訪問 http://118.195.179.192/vod/ 直接跳轉到 127.0.0.1:8081
  • 準備工作

    • 準備兩個 tomcat 伺服器,一個 8080 埠,一個 8081 埠

      cd /usr/src
      mkdir tomcat8008
      mkdir tomcat8081
      cp apache-tomcat-8.5.73.tar.gz tomcat8080
      cp apache-tomcat-8.5.73.tar.gz tomcat8081
      ps -ef | grep tomcat
      kill -9 埠號
      cd tomcat8080
      tar zxvf apache-tomcat-8.5.73.tar.gz
      cd ..
      cd tomcat8081
      tar zxvf apache-tomcat-8.5.73.tar.gz
      cd ..
      cd tomcat8080
      cd apache-tomcat-8.5.73/
      cd bin/
      ./startup.sh
      cd ..
      cd ..
      cd ..
      cd tomcat8081
      cd apache-tomcat-8.5.73/
      cd conf
      vim server.xml 

      shutdown 埠隨便改一下,我這裡改成 8015
      在這裡插入圖片描述

    • 埠改成 8081
      在這裡插入圖片描述
      啟動 tomcat8081

      ./startup.sh

      可以看到我們啟動了兩個 tomcat,一個是 8080,一個是 8081
      在這裡插入圖片描述
      我們可以訪問看一下
      在這裡插入圖片描述

    在這裡插入圖片描述

  • 建立資料夾和測試頁面

    • /usr/src/tomcat8080/apache-tomcat-8.5.73/webapps 下建立 edu 資料夾,並在資料夾下建立 a.html 檔案,內容為 <h1>8080!!!</h1>
      在這裡插入圖片描述
    • 同樣的,在 /usr/src/tomcat8081/apache-tomcat-8.5.73/webapps 下建立 vod 資料夾,並在資料夾下建立 a.html 檔案,內容為 <h1>8081!!!</h1>
      在這裡插入圖片描述
  • 具體配置

    • 找到 nginx 配置檔案進行反向代理配置

      cd /usr/local/nginx/conf
      vim nginx.conf

      新增一個 server

      server {
          listen       9001;
          server_name  118.195.179.192;
      
          location ~ /edu/ {
              proxy_pass http://127.0.0.1:8080;
          }
      
          location ~ /vod/ {
              proxy_pass http://127.0.0.1:8081;
          }
      }

      在這裡插入圖片描述

      開放埠號 9001、8080、8081
      重新載入 nginx

      cd /usr/local/nginx/sbin
      ./nginx --s stop 
      ./nginx 
  • 最終測試
    在這裡插入圖片描述
    在這裡插入圖片描述
  • location 指令說明

    • 該指令用於匹配 URL ,語法如下:

      location [ = | ~ | ~* | ^~] uri {
      
      }
    • =:用於不含正規表示式的 uri 前,要求請求字串與 uri 嚴格匹配,如果匹配成功,就停止繼續向下搜尋並立即處理該請求
    • ~:用於表示 url 包含正規表示式,並且區分大小寫
    • ~*:用於表示 uri 包含正規表示式,並且不區分大小寫
    • ^~:用於不含正規表示式的 uri 前,要求 nginx 伺服器找到標識 uri 和請求字串匹配度最高的 location 後,立即使用此 location 處理請求,而不再使用 location 塊中的正則 uri 和請求字串做匹配

<3> 負載均衡

  • 實現效果:通過瀏覽器位址列輸入地址 http://118.195.179.192/edu/a.html,負載均衡效果,平均 8080 和 8081 埠
  • 準備工作

    • 準備兩臺 tomcat 伺服器,一臺 8080,一臺 8081(上一個例項已經準備過)
    • 在兩臺 tomcat 的 webapps 目錄下,建立名稱為 edu 資料夾,在 edu 資料夾建立 a.html 頁面,用於測試
  • 在 nginx 的配置檔案中進行負載均衡的配置

    cd /usr/local/nginx/conf
    vim nginx.conf

    在這裡插入圖片描述

  • 測試
    在這裡插入圖片描述在這裡插入圖片描述
  • 負載均衡分配策略

    • 輪詢(預設):每個請求按時間順序逐一分配到不同的後端伺服器,如果後端伺服器 down 掉,能自動剔除
    • weight

      • weight 代表權重,預設為1,權重越高被分配的客戶端越多
      • 指定輪詢機率,weight 和訪問比率成正比,用於後端伺服器效能不均的情況

        upstream myserver {
            server 118.195.179.192:8080 weight=5;
            server 118.195.179.192:8081 weight=10;
            }
    • ip_hash :每個請求按訪問 ip 的 hash 結果分配,這樣每個訪問固定訪問一個後端伺服器,可以解決 session 問題,eg

      upstream myserver {
          ip_hash;
          server 118.195.179.192:8080;
          server 118.195.179.192:8081;
          }
    • fair(第三方):按後端伺服器的響應時間來分配請求,響應時間短的優先分配

      upstream myserver {
          server 118.195.179.192:8080;
          server 118.195.179.192:8081;
          fair;
          }

<4> 動靜分離

動靜分離從目前實現角度來講大致分為兩種

  • 一種是純粹把靜態檔案獨立成到單獨的域名,放在獨立的伺服器上
  • 另一種方法就是動態跟靜態檔案混合在一起釋出,通過 nginx 來分開
     

通過 location 指定不同的字尾名實現不同的請求轉發。通過 expires 引數設定,可以使瀏覽器快取過期期間,減少與伺服器之前的請求和流量。具體 expires 定義:是給一個資源設定一個過期時間,也就是說無需去服務端驗證,直接通過瀏覽器自身確認是否過期即可,所以不會產生額外的流量。此種方法非常適合不經常變動的資源。(如果經常更新的檔案,不建議使用 Expires 來快取)。比如:設定 3d,表示在 3 天之內訪問這個 URL,傳送一個請求,比對伺服器該檔案最後更新時間沒有變化,則不會從伺服器抓取,返回狀態碼 304,如果有修改,則直接從伺服器重新下載,返回狀態碼 200

  • 準備工作

    • 在 Linux 系統中準備靜態資源,用於進行訪問

      cd /
      mkdir static
      cd static
      mkdir www
      mkdir image

      www 資料夾中建立檔案 a.html ,內容為 <h1>test html</h1>
      image 資料夾中隨便放一張圖片,我這裡放的是 01.jpg

  • 實現效果:瀏覽器訪問 www 下 a.html 和 image 下 01.jpg(不是通過 tomcat,而是通過 nginx 靜態資源配置訪問)
  • 具體配置

    cd /usr/local/nginx/conf
    vim nginx.conf

    在這裡插入圖片描述
    啟動/重啟 nginx

    cd /usr/local/nginx/sbin
    ./nginx
  • 測試

    • 瀏覽器輸入地址 http://118.195.179.192/image/01.jpg
      在這裡插入圖片描述
      在這裡插入圖片描述
    • 瀏覽器輸入地址 http://118.195.179.192/www/a.html
      在這裡插入圖片描述

<5> 高可用叢集

  • 什麼是高可用?

    • 有一臺主伺服器和一臺備份伺服器,一般請求時都是根據主伺服器傳送請求,當主伺服器的 Nginx 掛掉時,會自動切換到備份伺服器,通過備份伺服器進行訪問,此時備份伺服器作為主伺服器的位置來處理請求,這就是高可用

    在這裡插入圖片描述

  • 準備工作

    • 需要兩臺 Nginx 伺服器
    • 在兩臺伺服器安裝 nginx (前面有教程)
    • 在兩臺伺服器安裝 keepalived
      yum install keepalived -y
      安裝目錄為:/etc/keepalived
      檢視是否被安裝:rpm -q -a keepalived
      在這裡插入圖片描述
  • 完成高可用配置(主備配置)

    cd /etc/keepalived
    vim keepalived.conf

    主伺服器

    global_defs {
       notification_email {
            acassen@firewall.loc
            failover@firewall.loc
            sysadmin@firewall.loc
       }
        notification_email_from Alexandre.Cassen@firewall.loc
        smtp_server 192.168.200.1
        smtp_connect_timeout 30
        router_id LVS_DEVEL
    }
    
    vrrp_script chk_http_port {
        script "/usr/local/src/nginx_check.sh"
        interval 2  # 檢測指令碼執行的間隔
        weight 2
    }
    
    vrrp_instance VI_1 {
        state MASTER  # 備份伺服器上將 MASTER 改為 BACKUP
        interface eth0  # 網路卡
        virtual_router_id 51  # 主、備機的 virtual_router_id 必須相同
        priority 100  # 主、備機取不同的優先順序,主機值較大,備機值較小
        advert_int 1
        authentication {
            auth_type PASS
            auth_pass 1111
        }
        virtual_ipaddress {
            192.168.200.16  # VRRP H 虛擬地址
        }
    }

    備份伺服器

    global_defs {
       notification_email {
            acassen@firewall.loc
            failover@firewall.loc
            sysadmin@firewall.loc
       }
        notification_email_from Alexandre.Cassen@firewall.loc
        smtp_server 192.168.200.1
        smtp_connect_timeout 30
        router_id LVS_DEVEL
    }
    
    vrrp_script chk_http_port {
        script "/usr/local/src/nginx_check.sh"
        interval 2  # 檢測指令碼執行的間隔
        weight 2
    }
    
    vrrp_instance VI_1 {
        state BACKUP  # 備份伺服器上將 MASTER 改為 BACKUP
        interface eth0  # 網路卡
        virtual_router_id 51  # 主、備機的 virtual_router_id 必須相同
        priority 90  # 主、備機取不同的優先順序,主機值較大,備機值較小
        advert_int 1
        authentication {
            auth_type PASS
            auth_pass 1111
        }
        virtual_ipaddress {
            192.168.200.16  # VRRP H 虛擬地址
        }
    }

    在主伺服器和備份伺服器 /usr/local/src 下編寫檔案 nginx_check.sh

    #!/bin/bash
    A=`ps -C nginx -no-header |wc -1`
    if [ $A -eq 0 ];then
        /usr/local/nginx/sbin/nginx  # Nginx 啟動指令碼位置
        sleep 2
        if [ `ps -C nginx --no-header |wc -1` -eq 0 ];then
            killall keepalived
        fi
    fi

    啟動兩臺伺服器的 nginx 和 keepalived

    cd /usr/local/nginx/sbin
    ./nginx
    systemctl start keepalived
  • 測試:兩臺伺服器要在同一區域網,我這裡只是為了演示流程
  • keepalived 配置檔案詳解

    • global_defs:全域性配置(主要是 router_id 伺服器名字/etc/host 新增主機名稱)
    • vrrp_script:指令碼配置

      • script "xxx.sh"
      • interval 2:檢測指令碼執行的間隔(2s)
      • weight -20:權重(當指令碼中的條件成立,當前主機的權重降低20)
    • vrrp_instance:虛擬 IP 配置

      • state BACKUP:表示伺服器是主伺服器(MASTER)還是備份伺服器(BACKUP)
      • interface eth0:繫結的網路卡(通過 ifconfig 檢視)
      • virtual_router_id 51:主備機的id值,相當於唯一標識
      • priority 90:優先順序,值越大,優先順序越高(一般主伺服器設定為 100,從伺服器小於 100,比如 90)
      • advert_int 1:每隔多長時間傳送一個心跳,檢測伺服器是否或者,預設每隔 1 s 傳送一個心跳
      • authentication {auth_type PASS auth_pass 1111}:許可權校驗方式(密碼:1111)
      • vritual_ipaddress:繫結虛擬 IP(可以繫結多個)

4. Nginx 原理

  • nginx 啟動後有兩個程式:master 和 worker
    在這裡插入圖片描述
  • master 就相當於一個領導,不做具體工作,分配任務給 worker,worker 做具體的任務
  • worker 如何進行工作?

    • 當 client(客戶端)傳送一個請求到 nginx,首先到 master,master 得到請求後,將請求分擔給 worker,一個 master 下面有很多個 worker,worker 獲取任務不是平均分配,也不是輪詢,而是 爭搶 的機制
client 傳送請求 -> master ->worker(爭搶機制) -> 具體操作
  • 一個 master 和多個 worker 有什麼好處?

    • 可以使用 nginx -s reload 熱部署,利於 nginx 進行熱部署操作
    • 每個 worker 都是獨立的程式,不需要加鎖,一個程式退出後,其他程式可正常工作,降低風險
  • 設定多少個 worker 合適?

    • Nginx 同 redis 類似都採用了 IO 多路複用機制,每個 worker 都是一個獨立的程式,每個程式裡只有一個主執行緒,通過非同步非阻塞方式來處理請求。每個 worker 的執行緒可以把一個 CPU 的效能發揮到極致。因此,worker 數和伺服器的 CPU 數相等是最為適宜的。設少了會浪費 CPU,設多了會造成 CPU 頻繁切換上下文帶來的損耗
  • 連線數 worker_connection(每個 worker 程式所能建立連線的最大值)

    • 傳送一個請求,佔用了 worker 的幾個連線數?答案:2(client 訪問靜態資源,worker 收到請求後返回) 或者 4 個(worker 本身不支援 Java,worker 要把請求轉發給 tomcat,tomcat 再返回)
    • nginx 有一個 master,有 4 個 worker,每個 worker 支援的最大連線數為 1024, 支援的最大的併發數為多少?

      worker 最大支援的連線數 4*1024
      worker 支援的最大併發 4*1024/2=2048 或 4*1024/4=1024
    普通的靜態訪問最大併發數是:worker_connections * worker_processes / 2
    作為反向代理來說,最大的併發數量是:worker_connections * worker_processes / 4
    【注】worker_connections:每個 worker 支援的最大連線數(即上面所說的 1024)
    worker_processes:worker 的數量

相關文章