NGINX 入門到企業級應用實踐-基礎篇

今日長劍在握發表於2021-11-24

這是一系列免費的知識,有圖文版視訊版,你現在看到的是圖文版。

NGINX 系列課分為三篇,基礎篇、進階篇和企業實踐篇,你現在正在閱讀的是基礎篇

視訊版釋出在我自己的社群,喜歡看視訊的朋友可前往社群,微信掃碼登入或微信授權登入後即可播放

寫在前面

基礎篇學習目的:瞭解 NGINX,並能夠自己動手操作,能獨立完成負載均衡配置,並繫結域名,實現通過域名訪問後端服務。

NGINX系列課課學習目的:瞭解 NGINX、能夠自己獨立完成負載均衡配置、能夠自己搭建高可用的企業級生產環境、對 NGINX 進行監控。

聽過視訊課的朋友已經能夠獨立完成負載均衡配置了,還提交了作業

image.png

我們這半年,將會輸出非常多公開課,有圖文版、有視訊版。重要的是,這些都是免費的!!! 來了就能聽。課程清單如下

image.png

其中綠色標註的是已經發布的內容,紅色的是正在準備素材的內容。

NGINX 基礎篇圖文版

好的,正題來了,開始吧。

如果平時接觸後端或者伺服器比較少的朋友可能會問,NGINX 是什麼

關於它是什麼,我們可以引用 NGINX 官網百度百科中的介紹,NGINX 是一款高效能的 HTTP 伺服器,同時也是一款反向代理伺服器(NGINX 官網原文稱為 reverse proxy server)。除了支援 HTTP 協議外,還支援郵件協議、TCP/UDP 等。

它能夠做什麼

在我看來,它其實是一款閘道器。作用 1 請求轉發,作用 2 限流,作用 3 鑑權,作用 4 負載均衡。上面提到的反向代理 reverse proxy server,可以歸類到請求轉發。

正向代理,反向代理???

太多道理我們就不講了,可以閱讀其他平臺上關於這個問題的解讀 https://zhuanlan.zhihu.com/p/...

這裡我們簡單總結一下,正向代理代理的物件是客戶端,反向代理代理的物件是服務端

做爬蟲的朋友們,平時你們用的 IP 代理就是正向代理,爬蟲程式通過代理,將請求轉發給後端。而我們提到的 NGINX 反向代理則是將客戶端的請求轉發到後端。從上面講到的文章裡借幾張圖

image.png

image.png

用 NGINX 的公司多嗎?

大部分公司都有用到 NGINX,大至 Google Meta(Facebook) Amazon Alibaba Tencent HUAWEI,小至全世界 70%+ (我猜的,實際比這更多)的網際網路企業,社群使用的也是 NGINX

安裝 NGINX

安裝基於 Ubuntu20.04,雲伺服器。基礎篇先通過快速安裝,讓我們可以操作起來,學一些基礎,後續進階篇會有編譯安裝。

開啟 Terminal,執行 sudo apt install nginx -y,等待命令執行即完成安裝。安裝完成後它會自行啟動,大家訪問自己伺服器的地址即可,例如我的伺服器 IP 是 101.42.137.185,那我訪問的是 http://101.42.137.185

image.png

如果頁面顯示的是 Welcome to nginx 字樣,說明服務正常。如果沒有,請檢查安裝時 Terminal 輸出的錯誤資訊,或者檢查自己的防火牆、安全組策略等(如果不懂,或者怎麼操作也不對,可以通過社群之前釋出的 Linux 雲伺服器公開課學習)

NGINX 基本工作原理和模組關係簡述

NGINX 有一個主程式和多個工作程式。主程式用於維護自身運轉,例如讀取配置、解析配置、維護工作程式、重新載入配置等等;工作程式才是具體響應請求的程式。

工作程式數可在配置檔案中調整。

NGINX 由模組組成,這些模組受配置檔案中的配置操控,也就是說配置檔案決定了 NGINX 的工作方式。

這裡還是引用其他文章,就不自己一一寫明瞭。NGINX 原理和架構可以參考 https://zhuanlan.zhihu.com/p/...,實際上在初期我們需要關注的只有一個地方,也就是模組那部分,隨便看看做個大體瞭解即可,不必深入。

NGINX 的訊號

訊號,這裡指的是控制訊號。訊號是控制 NGINX 工作狀態的模組,訊號語法格式為

nginx -s signal

常用的訊號有

stop 快速關停
quit 正常關停
reload 重新載入配置
reopen 重新開啟日誌檔案

NGINX 的正確關停,是 nginx -s quit 它可以讓 NGINX 處理完已經開始的工作後再退出。

NGINX 配置說明

基於之前的社群公開課,我們可以在正式講 NGINX 配置前先看看它的應用程式管理配置。通過 status 命令找到 NGINX 的 Server 配置檔案

> systemctl status nginx

檢視 NGINX 的 Server 配置

[Unit]
Description=A high performance web server and a reverse proxy server
Documentation=man:nginx(8)
After=network.target

[Service]
Type=forking
PIDFile=/run/nginx.pid
ExecStartPre=/usr/sbin/nginx -t -q -g 'daemon on; master_process on;'
ExecStart=/usr/sbin/nginx -g 'daemon on; master_process on;'
ExecReload=/usr/sbin/nginx -g 'daemon on; master_process on;' -s reload
ExecStop=-/sbin/start-stop-daemon --quiet --stop --retry QUIT/5 --pidfile /run/nginx.pid
TimeoutStopSec=5
KillMode=mixed

[Install]
WantedBy=multi-user.target

看到 ExecStart 選項,可以確定 NGINX 安裝在 /usr/sbin/nginx,這個配置檔案與我們之前的公開課 Linux 雲伺服器公開課講到的知識遙相呼應,這裡提一下。

查詢預設的主配置檔案

配置檔案部分正式開始

NGINX 有主配置檔案輔助配置檔案,主配置檔案預設名稱為 nginx.conf,預設存放在 /etc/nginx/nginx.conf。輔助配置檔案的路徑受主配置檔案控制,具體路徑通過主配置檔案設定,輔助配置的檔名稱和路徑都可更改,檔名通常以 conf 結尾。

安裝完成後如果你不知道主配置檔案在哪,可以通過預設路徑查詢,或者通過 find 命令搜尋。

> sudo find / -name nginx.conf
/etc/nginx/nginx.conf

主配置檔案基本結構和作用。使用 cat /etc/nginx/nginx.conf 可列出檔案內容。如果你不懂,那麼可以通過社群之前釋出的的公開課 Linux 雲伺服器公開課學習具體的 Linux 檔案檢視指令。

user www-data;  # 使用者
worker_processes auto; 工作程式數
pid /run/nginx.pid; # 程式檔案
include /etc/nginx/modules-enabled/*.conf; # 外掛模組配置

events {
        worker_connections 768;  # 允許同時連線的連線數
        # multi_accept on;
}

http {
        sendfile on;
        tcp_nopush on;
        tcp_nodelay on;
        keepalive_timeout 65;
        types_hash_max_size 2048;
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE
        ssl_prefer_server_ciphers on;

        access_log /var/log/nginx/access.log;
        error_log /var/log/nginx/error.log;
        include /etc/nginx/conf.d/*.conf;  # 輔助配置檔案路徑
        include /etc/nginx/sites-enabled/*;
}


# 示例
#mail {
  ...
#}

這裡列出的配置檔案我做了適當的調整,刪除了被註釋的內容,保留了有效內容。重要項的含義都用中文以註釋的形式標記在上面了。

看到配置,你肯定有點懵,這都是些啥啊。接下來我們來學習 NGINX 配置檔案的基礎語法。

NGINX 配置檔案基礎語法

NGINX 配置檔案中的配置項成為指令,指令分為簡單指令塊指令。簡單的指令由指令名稱引數組成,以空格進行分隔並以英文分號結尾,例如

worker_processes auto;

其中 worker_processes 是指令,這個指令的作用是設定工作程式數。auto 代表程式數的數量,可以是數字也可以是 auto(根據 CPU 數量按固定數學公式計算,一般是 CPU+1)。

塊指令語法格式與簡單指令相似,單以花括號包裹更多的簡單指令,例如

http {
  server {
    ...
  }
}

上下文/語境

上下文有些地方也稱語境,如果塊指令內包含其他指令,則這個塊指令稱為上下文。常見的上下文例如

events
http
server
location

有一個隱藏的上下文指令,main。它不需要顯示宣告,所有指令的最外層就是 main 的範圍。main 作為其他上下文的參考,例如 events 和 http 必須在 main 範圍中;server 必須在 http 中;location 必須在 server 中;以上限定是固定的,不可以隨意放置,否則無法執行 NGINX 程式,但能夠在日誌裡看到錯誤提示資訊。

講了這麼多,你一定乏了,拿我們來動手吧!

使用 NGINX 為後端程式配置代理

一個簡單的 WEB 服務,例如下面這個 flask 應用

from flask import Flask
from flask_restful import Resource, Api
​
app = Flask(__name__)
api = Api(app)
​
​
class HelloWorld(Resource):
    def get(self):
        app.logger.info("receive a request, and response '穿甲兵技術社群'")
        return {'message': '穿甲兵技術社群', "address": "https://chuanjiabing.com"}
​
​
api.add_resource(HelloWorld, '/')
​
if __name__ == '__main__':
    app.run(debug=True, host="127.0.0.1", port=6789)

將內容寫入到伺服器上的某個檔案,例如 /home/ubuntu/ke.py

啟動前記得安裝相關的 Python 庫 pip3 install flask-restful

在 Ubuntu 20.04 上預設帶有新版 Python,環境什麼的不用擔心。執行這個 Web 後端服務 python3 /home/ubuntu/ke.py

完成後端的啟動後,我們來配置 NGINX

通過前面檢視主配置檔案可知,輔助配置檔案的目錄為 /etc/nginx/conf.d,那麼現在我們在輔助配置檔案目錄新增配置檔案

> sudo vim /etc/nginx/conf.d/ke.conf

server {
    listen 8000;
    server_name localhost;

    location / {
        proxy_pass http://localhost:6789;
    }
}

檢查配置檔案是否正確

> sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

重新載入配置

> sudo nginx -s reload

瀏覽器訪問 http://ip:port 例如我的伺服器 http://101.42.137.185:8000/

就可以看到後端的輸出了

NGINX 日誌檔案

預設分為正常日誌和內部錯誤日誌,日誌路徑可在主配置檔案中設定

/var/log/nginx/access.log
/var/log/nginx/error.log

檢視正常日誌

> cat /var/log/nginx/access.log
117.183.211.177 - - [19/Nov/2021:20:18:46 +0800] "GET / HTTP/1.1" 200 107 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.71 Safari/537.36"
117.183.211.177 - - [19/Nov/2021:20:18:48 +0800] "GET /favicon.ico HTTP/1.1" 404 209 "http://101.42.137.185:8000/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.71 Safari/537.36"

官方文件-日誌格式 http://nginx.org/en/docs/http...

預設的日誌格式

log_format compression '$remote_addr - $remote_user [$time_local] '
                       '"$request" $status $bytes_sent '
                       '"$http_referer" "$http_user_agent" "$gzip_ratio"';

可在主配置檔案中自行配置,具體配置項參考官方文件。

使用 NGINX 為前端程式配置代理

一個簡單的 HTML 文件

> vim /home/ubuntu/index.html
<html><meta charset="utf-8"/><body><title>穿甲兵技術社群</title><div><p>穿甲兵技術社群<p><a>https://chuanjiabing.com</a></div><body></html>

無論是大型前端專案還是中小型前端專案,一般來講都需要編譯為 HTML 文件,然後使用類似 NGINX 這樣的應用提供可訪問的服務。

注意:一些 Vue/React 的服務有可能會做服務端渲染部署,但大部分還是編譯為 HTML。這裡的簡單示例和那些前端工程專案在配置上並沒有什麼區別。作為示例,不用糾結,學習 NGINX 才是要緊的。

> sudo vim /etc/nginx/conf.d/page.conf

server {
    listen 1235;
    server_name localhost;
    charset utf-8;
    
    location / {
        root /home/ubuntu/;
        index index.html index.htm;
    }
}

基於 NGINX 實現負載均衡

想象一下場景,例如現在你伺服器上的後端服務主要是用於格式化時間,有很多爬蟲程式需要呼叫它,而且還需要確保服務穩定可用。

場景延伸:假設你逆向了一個 JS 演算法,現在所有爬蟲都需要在發出請求前呼叫這個演算法生成 sign 值,帶著值去請求。如果你把 JS 程式碼放在 Python/Golang 這類程式碼裡做本地呼叫執行,那麼你改動演算法時需要改動/重新部署所有爬蟲程式,但做成 WEB 服務,只需要改動/重啟這個 WEB 服務就可以了。

現在 1 個後端服務的情況下有 2 個明顯缺點:

1、服務效能不夠,請求太多會導致程式卡頓,響應速度慢,影響整體效率;

2、服務整體不穩定,一旦程式退出或者伺服器當機,那服務將不可訪問;

使用負載均衡的好處

1、啟動多個後端服務,配置負載均衡,讓請求按需(例如輪流)轉發到它門那裡進行處理,那麼就能夠承擔更多的工作需求;

2、一個 NGINX 負載多個後端服務,當一個服務或者幾個服務出現程式退出的情況,還有其他服務在工作;

NGINX 只需要引入 proxy_pass 指令和對應的 upstream 上下文即可實現負載均衡。一個簡單的負載均衡配置例如

⚠️ 實驗前,請先啟動多個後端程式。可以將剛才的 Flask 程式碼複製到另一個檔案(例如 /home/ubuntu/main.py,但記得需要改動裡面的埠號,建議改為跟教程一樣的 6799),如果你想在網頁上看到負載的效果,可以在響應內容處用 6789/6799 來區分具體是那個後端程式。

# /etc/nginx/conf.d/ke.conf 內容改為
upstream backend{
    server localhost:6789;
    server localhost:6799;
}

server {
    listen 8000;
    server_name localhost;

    location / {
        proxy_pass http://backend;
    }
}

儲存後重新載入配置即可

> sudo nginx -s reload

多次訪問 http://101.42.137.185:8000/,可以看到頁面上顯示的內容是 6789 和 6799 這兩個後端服務交替返回資訊,這說明負載均衡配置成功

image.png

image.png

域名解析與配置實踐

開啟雲服務商控制檯(後續以騰訊云為例,因為教程錄製時使用的是騰訊雲輕量級伺服器),其他雲服務商介面有差異,請大家見機行事。

在搜尋框處搜尋域名解析(騰訊的的是 DNSPOD)

image.png

進入找到要解析的域名(這裡的前提是你自己已經買了域名,做好備案。如果沒有,那看我操作也可以),點選解析

image.png

點選新增記錄

在主機記錄處輸入子域名名稱(例如 ke)、在記錄值處輸入伺服器 IP 地址後選擇儲存即可,其他選項預設。

image.png

完成雲伺服器控制檯的設定後,還不可以通過域名訪問到我們伺服器上的應用

前往伺服器改動 NGINX 輔助配置檔案,更改埠、繫結域名

> sudo vim/etc/nginx/conf.d/ke.conf
# 改動 server 上下文中的 listen 和 server_name
listen 80;
server_name ke.chuanjiabing.com;

記得過載配置

> sudo nginx -s reload

然後就可以通過域名 http://ke.chuanjiabing.com/ 訪問服務了

image.png

課後作業:在社群課程帖子下曬出後端程式的 NGINX 負載均衡配置截圖,3 張。一張是配置截圖;另外兩張是瀏覽器訪問時負載配置生效的截圖。

後續進階篇和企業實踐篇的課程大綱如下,後續課程的學習目的:能夠在工作中很好的應用 NGINX,完成企業級生產環境部署和監控告警

NGINX 進階篇

NGINX 負載均衡策略理論

編譯安裝 NGINX

基於 NGINX 實現許可權驗證

基於 NGINX 實現訪問限流

基於 NGINX 的簡單反爬蟲

基於 NGINX 實現不停機更新

NGINX 企業級實踐篇

NGINX 的 HTTPS 配置實踐

NGINX 外掛安裝

NGINX 資料監控實戰

NGINX 生產環境高可用部署實踐

相關文章