NGINX 學習筆記

前言

這是我的 NGINX 學習筆記,看什麼學什麼記什麼!



安裝

sudo apt-get install nginx


建立新的設定檔

vim /etc/nginx/sites-available/configName
server {
listen 80;
server_name yourServerName;
access_log /locationYouPrefer;
listen 443 ssl;
ssl_certificate /location/fullchain.pem;
ssl_certificate_key /location/privkey.pem;

location /upstream {
proxy_set_header Host www.tu8686.com;
set $upstream_url 210.209.13.49:80;
proxy_pass http://$upstream_url;
add_header Q-Status $upstream_cache_status;
break;
}

location / {
proxy_pass_header Server;
proxy_redirect off;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Scheme $scheme;
proxy_pass http://127.0.0.1:50005;
}
}
  • proxy_pass_header: 若回應 request 時, header 有設定了, 那告訴 NGINX 不要更改設定的 header, 若要加 header 需使用 via, 例如 範例圖片
  • server_name: request 的 header 中的 server 需符合
  • access_log: log 的位置
  • location: 符合 server 後, 改搜尋相對應的 location
  • proxy_redirect: 重新導向
  • proxy_set_header: 設定 header 值
  • proxy_pass: 將 request 導向指定的位置
  • proxy_set_header: set host
  • set $upstream_url: set $upstream_url
  • add_header: add header
  • break: 終止目前的 rewrite 規則。 如果有規則是被指定在目前的 location 內的,繼續將此 location 的 request 處理完畢。

啟用設定檔

複製到 enabled 資料夾

ln -s /etc/nginx/sites-available/yourConfig /etc/nginx/sites-enabled

啟用

systemctl restart nginx.service

location

參考官方文件

語法

Syntax:	location [ = | ~ | ~* | ^~ ] uri { ... }
location @name { ... }
Default: —
Context: server, location
  • 規則搜尋分為以下兩種方式

    • 正則搜尋 (regular expression)
      • ~*: 不區分大小寫
      • ~: 區分大小寫
    • 前綴字串 (prefix string)
  • 規則搜尋順序:
    使用前綴字串搜尋 → 搜尋到符合最長的 url, 並且記下結果 → 依照設定檔中的順序, 使用正則規則搜尋 → 如果正則規則有搜尋到符合的,會立即停止搜尋,因此正則順序至關重要 → 如果正則沒有搜尋到符合的,會採用使用前綴字串搜尋到的

  • 在一些不區分大小寫的系統中,像是 macOS 或是 Cygwin, 前綴字串規則會無視大小寫

  • 正則規則可以捕捉一些變數,在其他的規則中使用

  • 如果最長的前綴字串規則有 ^~, 那就不會再使用正則規則搜尋

  • 前綴規則有 =, 代表字串須完全符合,如果有找到,搜尋終止。 例如,如果 “/“ 請求很頻繁,那麼可以定義 “location = /“, 這樣可以加速請求處理

  • 在版本 0.7.1 到 0.8.41 中,如果請求符合前綴規則,就算沒有加上 =, 或者 ^~, 搜尋也會立即停止


範例

location = / {
[ configuration A ]
}

location / {
[ configuration B ]
}

location /documents/ {
[ configuration C ]
}

location ^~ /images/ {
[ configuration D ]
}

location ~* \.(gif|jpg|jpeg)$ {
[ configuration E ]
}
  • 請求 / 將會符合 A
  • 請求 /index.html 將會符合 B
  • 請求 /documents/document.html 將會符合 C
  • 請求 /images/1.gif 將會符合 D
  • 請求 /documents/1.jpg 將會符合 E
  • 請求 @name: 只用於內部重新導向,不用於正常使用, 例如:
    location /img/ {
    not_found 404 @not_found;
    }

    location @not_found {
    # 规则
    }

alias 與 root

alias

參考文件
定義特定 location 的替換。 舉例來說, 看看下面的設定

location /i/ {
alias /data/w3/images/;
}

如果請求是 /i/top.git 的話, 檔案 /data/w3/images/top.git 將會被送出

路徑可以包含變數, 除了 $document_root 以及 $realpath_root 之外

如果 alias 被使用在正則定義的 location 之內, 那 alias 必須要參考正則捕捉到的條件, 範例如下:

location ~ ^/users/(.+\.(?:gif|jpe?g|png))$ {
alias /data/w3/images/$1;
}

當 location 的值跟 alias 的最後一個資料夾的值相同, 像下面這樣:

location /images/ {
alias /data/w3/images/;
}

那會建議使用 root

location /images/ {
root /data/w3;
}

root

參考文件
設定 root 的資料夾位置為請求路徑, 例如以下範例:

location /i/ {
root /data/w3;
}

/data/w3/i/top.git 檔案將會被送出, 以回應 /i/top.git 請求

路徑可以包含變數, 除了 $document_root 以及 $realpath_root 之外


總結

  • alias 會取代 location 成為新的請求資源路徑
  • root + location 的值 = 請求資源路徑

部署 vue 專案

Build

npm run build, 看 script 怎麼寫, 這邊只管部署


config

server {
# Listen port 號
listen 8080;
# Server name
server_name localhost;

# Log 位置
access_log logs/host.access.log;

# root 位置, 可以參考上面的 root 詳解
root /Users/rainy/Desktop/MyWork/Work/website/dist;

# 預設檔案
index index.html index.htm;

location / {
# try to find $uri, and then $uri/, and if they both are not found, go for @router
try_files $uri $uri/ @router;

# If the path is found, go for index file below
index index.html index.htm;
}

location @router {
# rewite whatever to /index.html

# 不管 request 是什麼, 都 rewrite 到 /index.html, 並且執行 last, last 代表說, 結束這一次的 rewrite 規則, 並且使用 rewrite 後的結果重新對 server 發一次請求
rewrite ^.*$ /index.html last;
}
}

upstream

語法

Syntax:	upstream name { ... }
Default: —
Context: http

範例

upstream backend {
server backend1.example.com weight=5;
server 127.0.0.1:8080 max_fails=3 fail_timeout=30s;
server unix:/tmp/backend3;

server backup1.example.com backup;
}

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

詳解

定義多個 server, server 可以 listen 不同的 port 號, TCP 以及 UNIX-domain socket 可以混用
預設的話, 會採用權重輪詢分配請求到不同的 server, 以上面的範例來看, 每 7 個 request 中, 5 個會被分配到 backend1.example.com (weight=5), 2 個分別到 127.0.0.1:8080 以及 unix:/tmp/backend3
如果在溝通途中有錯誤, 請求會被分派到下一個 server, 直到出現成功回應的 server 。 如果裡面都沒有可以成功回應的, 那客戶端會收到最後一個 server 的回應 (backup)


PHP-FPM

fast

  • 請求網址為 http://lemp.test/test.php/foo/bar.php?v=1
  • 各項資訊如下:
    array (
    'USER' => 'www-data',
    'HOME' => '/var/www',
    'FCGI_ROLE' => 'RESPONDER',
    'QUERY_STRING' => 'v=1',
    'REQUEST_METHOD' => 'GET',
    'CONTENT_TYPE' => '',
    'CONTENT_LENGTH' => '',
    'SCRIPT_FILENAME' => '/var/www/test.php',
    'SCRIPT_NAME' => '/test.php',
    'PATH_INFO' => '/foo/bar.php',
    'REQUEST_URI' => '/test.php/foo/bar.php?v=1',
    'DOCUMENT_URI' => '/test.php/foo/bar.php',
    'DOCUMENT_ROOT' => '/var/www',
    'SERVER_PROTOCOL' => 'HTTP/1.1',
    'GATEWAY_INTERFACE' => 'CGI/1.1',
    'SERVER_SOFTWARE' => 'nginx/1.4.0',
    'REMOTE_ADDR' => '192.168.56.1',
    'REMOTE_PORT' => '44644',
    'SERVER_ADDR' => '192.168.56.3',
    'SERVER_PORT' => '80',
    'SERVER_NAME' => '',
    'HTTPS' => '',
    'REDIRECT_STATUS' => '200',
    'HTTP_HOST' => 'lemp.test',
    'HTTP_USER_AGENT' => 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:20.0) Gecko/20100101 Firefox/20.0',
    'HTTP_ACCEPT' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
    'HTTP_ACCEPT_LANGUAGE' => 'en-US,en;q=0.5',
    'HTTP_ACCEPT_ENCODING' => 'gzip, deflate',
    'HTTP_CONNECTION' => 'keep-alive',
    'PHP_SELF' => '/test.php/foo/bar.php',
    'REQUEST_TIME' => 1367829847,
    )

Questions and Answers

以下的 Nginx configuration example 的意思是?
  • Example:
    proxy_http_version 1.1;
  • Answer:
    將 http version 設定為 1.1, 預設為 1.0
    1.0 是不會開啟 keep-alive feature 在 proxy server 跟 backend 的
Nginx 中, 何時可能會用到 proxy_set_header?

當我想要使用預設的 variable 來設定 header 時, 例如取得 $remote_addr

以下的 Nginx 設定的意思是?
  • Example:

    server {
    listen 80;
    underscores_in_headers on;
    location / {
    if ($http_custom_header = ray) {
    proxy_pass http://127.0.0.1:3000;
    }
    }
    }
  • Answer:
    使用 custom variable, 會自動 assign request header name custom_headertitle column collection 的 value 到 $http_custom_header 這個變數中, 所以如果我在 request header 使用 custom_header: ray 的話, 就會 pass 到 http://127.0.0.1:3000;
    參考 Nginx document

  • 以下的設定中, location ~ \.php$ 中, 最終帶過去的 fastcgi_param 是什麼? $query_string, 原本的 $request_method 跟 $document_root, $fastcgi_script_name 會處於未設定

    # server context
    root /var/www/html;

    fastcgi_param REQUEST_METHOD $request_method;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_index index.php;

    location /scripts {
    fastcgi_pass unix:/var/run/php5-fpm.sock;
    }

    location ~ \.php$ {
    fastcgi_param QUERY_STRING $query_string;
    fastcgi_pass 127.0.0.1:9000;
    }
  • 在以下的設定中, 如果使用 PHP-FPM 的話, 最終傳出的 fastcgi_param TEST 跟 DOCUMENT_ROOT 是? three, override

    # server context

    location ~ \.php$ {
    fastcgi_param REQUEST_METHOD $request_method;
    fastcgi_param SCRIPT_FILENAME $request_uri;

    fastcgi_param DOCUMENT_ROOT initial;
    fastcgi_param DOCUMENT_ROOT override;

    fastcgi_param TEST one;
    fastcgi_param TEST two;
    fastcgi_param TEST three;

    fastcgi_pass 127.0.0.1:9000;
    }
  • 不同的 FastCGI 處理器的作用方式依樣嗎? 不同哦

  • 因為不同的 FastCGI 處理器行為不同, 所以宣告 fastcgi_param 時, 建議宣告幾次? 1次

  • 當我們使用 PHP-FPM, 要 pass fastcgi_params 時, 怎樣可以在不同的 location 中在保留共同變數的同時, 又可以客制新的變數? 使用 include 共同檔案, 如下:

    root /var/www/html;

    location /scripts {
    include fastcgi_common;

    fastcgi_index index.php;
    fastcgi_pass unix:/var/run/php5-fpm.sock;
    }

    location ~ \.php$ {
    include fastcgi_common;
    fastcgi_param QUERY_STRING $query_string;
    fastcgi_param CONTENT_TYPE $content_type;
    fastcgi_param CONTENT_LENGTH $content_length;

    fastcgi_index index.php;
    fastcgi_pass 127.0.0.1:9000;
    }

  • CGI 全寫? Common Gateway Interface

  • Fast CGI 全寫? Fast Common Gateway Interface

  • CGI 用途? 一份協議, 規定要傳哪些數據, 以什麼樣的格式給後端

  • Fast CGI 用途? 依據 CGI 協議, 將請求以及數據傳給後端這個動作, 每一次都會產生一個程序, Fast CGI 會啟動一個主程序, 並將工作分配給子進程處理, 避免重複的勞動, 提高效率

  • PHP-FPM 全寫? PHP-Fast CGI Process Manager

  • PHP-FPM 用途? PHP 針對 FastCGI 的實現

  • 如何使用 systemctl 啟動 Nginx

    sudo systemctl start nginx
  • 如何使用 systemctl, 預設開機啟動 NGINX?

    sudo systemctl enable nginx
  • 如何使用 systemctl, 停止 nginx?

    sudo systemctl stop nginx
  • 如何使用 systemctl, 重啟 nginx?

    sudo systemctl restart nginx
  • 如何使用 systemctl, 重新載入 nginx 配置文件?

    sudo systemctl reload nginx
  • 如何測試 nginx 配置?

    sudo nginx -t
  • 如何使用 systemctl, 顯示 nginx 狀態?

    sudo systemctl status nginx
  • 如何檢查 nginx 版本?

    sudo nginx -v
  • 在 NGINX 中如果我想要從本地帶客製的 header 到 server, 該 header 的 key 有 underscore, 該怎麼解決?

    在 NGINX server block 中加入以下設定
    underscores_in_headers on;
  • NGINX 中, location 的規則搜尋, 又區分為哪兩種?

    1. 正則搜尋
    2. 前贅字串
  • NGINX 中, location 的正則搜尋中, ~* 代表的意思是? 不區分大小寫

  • NGINX 中, location 的正則搜尋中, ~ 代表的意思是? 區分大小寫

  • NGINX 中, location 的規則搜尋的順序?

    1. 使用前綴字串搜尋
    2. 搜尋到符合最長的 uri, 記錄下來
    3. 依照設定檔中的順序, 使用正則搜尋
    4. 若正則有找到, 停止搜尋, 以正則的為主
    5. 若正則沒找到, 以前最字串為主
  • NGINX 中, location 的規則搜尋的順序, 會先使用哪種規則搜尋? 前贅字串

  • NGINX 中, location 的規則搜尋的順序, 前綴字串搜尋結束後, 會使用什麼規則搜尋? 正則

  • NGINX 中, location 的規則搜尋的順序, 若再找到符合的前綴字串後, 還是使用正則搜尋一次嗎??

  • NGINX 中, location 的規則搜尋的順序, 若正則規則找到符合的, 還會繼續搜尋嗎? 不會

  • NGINX 中, location 的規則搜尋的順序, 若前綴跟正則都有符合的, 以哪種為優先? 正則

  • NGINX 中, location 的規則搜尋中, macOS 會區分大小寫嗎? 不會

  • NGINX 中, location 的規則搜尋中, 如何捕捉變數? 使用正則

  • NGINX 中, location 的規則搜尋中, ^~ 代表什麼意思? 當使用 ^~ 的前綴有找到符合的, 不會再使用正則搜尋

  • NGINX 中, location 的規則搜尋中, ^~ 是用於前綴還是正則? 前綴

  • NGINX 中, location 的規則搜尋中, = 是用於前綴還是正則? 前綴

  • NGINX 中, location 的規則搜尋中, = 代表什麼意思? 前綴須完全符合, 若有找到, 搜尋停止

  • NGINX 中, location 的規則搜尋中, 如果 / 的搜尋非常頻繁, 可以使用什麼樣的規則來加快速度? = /

  • NGINX 中, location 的規則搜尋中, 下圖中, 請求 / 會符合哪一個? A

    location = / {
    [ configuration A ]
    }

    location / {
    [ configuration B ]
    }

    location /documents/ {
    [ configuration C ]
    }

    location ^~ /images/ {
    [ configuration D ]
    }

    location ~* \.(gif|jpg|jpeg)$ {
    [ configuration E ]
    }
  • NGINX 中, location 的規則搜尋中, 下圖中, 請求 /index.html 會符合哪一個? B

    location = / {
    [ configuration A ]
    }

    location / {
    [ configuration B ]
    }

    location /documents/ {
    [ configuration C ]
    }

    location ^~ /images/ {
    [ configuration D ]
    }

    location ~* \.(gif|jpg|jpeg)$ {
    [ configuration E ]
    }
  • NGINX 中, location 的規則搜尋中, 下圖中, 請求 documents/document.htm 會符合哪一個? C

    location = / {
    [ configuration A ]
    }

    location / {
    [ configuration B ]
    }

    location /documents/ {
    [ configuration C ]
    }

    location ^~ /images/ {
    [ configuration D ]
    }

    location ~* \.(gif|jpg|jpeg)$ {
    [ configuration E ]
    }
  • NGINX 中, location 的規則搜尋中, 下圖中, 請求 images/1.gif 會符合哪一個? D

    location = / {
    [ configuration A ]
    }

    location / {
    [ configuration B ]
    }

    location /documents/ {
    [ configuration C ]
    }

    location ^~ /images/ {
    [ configuration D ]
    }

    location ~* \.(gif|jpg|jpeg)$ {
    [ configuration E ]
    }
  • NGINX 中, location 的規則搜尋中, 下圖中, 請求 @name 可否用於正常使用? 不可

location /img/ {
not_found 404 @not_found;
}

location @not_found {
# 规则
}
  • NGINX 中, alias 與 root 的規則中, 下圖中, 如果請求 /i/top.gif 那哪一個檔案會被送出? /data/w3/images/top.gif

    location /i/ {
    alias /data/w3/images/;
    }
  • NGINX 中, alias 與 root 的規則中, 下圖中, 如果像下圖般有使用到變數, 該從哪裡取變數? location

location ~ xxx {
alias /data/w3/images/$1;
}
  • NGINX 中, alias 與 root 的規則中, 如下圖般, 當 location 以及 alias 的最後一個資料夾的值相同時, 建議如何?
    location /images/ {
    root /data/w3;
    }
location /images/ {
alias /data/w3/images/;
}
  • NGINX 中, alias 與 root 的規則中, 如下圖般, 如果請求是 /i/top.gif, 哪個檔案會被送出? /data/w3/i/top.gif
location /i/ {
root /data/w3;
}
  • NGINX 全域變數中, $document_root 是什麼? 當前請求的文檔根目錄或別名

  • NGINX 全域變數中, 下面的 request url 中, $document_uri 是哪一段? /test1/test2

    http://34.83.35.165/test1/test2?test1=123&test2=456
  • NGINX 全域變數中, 下面的 request url 中, $host 是哪一段? 34.83.35.165

    http://34.83.35.165/test1/test2?test1=123&test2=456
  • NGINX 全域變數中, $hostname 是什麼? 主機名稱, 可在 Linux 中設定

  • NGINX 全域變數中, $is_args 是什麼? 如果請求中有參數,值為“?”,否則為空字符串。

  • NGINX 全域變數中, $limit_rate 是什麼? 用於設置響應的速度限制,詳見limit_rate。

  • NGINX 全域變數中, $msec 是什麼? 當前的Unix時間戳(1.3.9, 1.2.6)

  • NGINX 全域變數中, $pipe 是什麼? 如果請求來自管道通信,值為“p”,否則為“.”

  • NGINX 全域變數中, 下面的 request url 中, $query_string 是哪一段? test1=123&test2=456

    http://34.83.35.165/test1/test2?test1=123&test2=456
  • NGINX 全域變數中, $realpath_root 是什麼? 當前請求的文檔根目錄或別名的真實路徑,會將所有符號連接轉換為真實路徑, 位置同 document_root

  • NGINX 全域變數中, $remote_addr 是什麼? 客戶端地址

  • NGINX 全域變數中, $remote_port 是什麼? 客戶端端口

  • NGINX 全域變數中, $request 是什麼? 代表客戶端的請求地址, 像這樣: POST /test1/test2?test1=123&test2=456 HTTP/1.1

  • NGINX 全域變數中, $request_body 是什麼? 客戶端的請求主體, 此變量可在location中使用,將請求主體通過proxy_pass, fastcgi_pass, uwsgi_pass,和scgi_pass傳遞給下一級的代理服務器。

  • NGINX 全域變數中, $request_filename 是什麼? 當前連接請求的文件路徑,由root或alias指令與URI請求生成。 /usr/share/nginx/html/test1/test2

  • NGINX 全域變數中, $request_length 是什麼? 請求的長度(包括請求的地址, http請求頭和請求主體) (1.3.12, 1.2.7)

  • NGINX 全域變數中, $request_method 是什麼? HTTP請求方法,通常為“GET”或“POST”

  • NGINX 全域變數中, $request_time 是什麼? 處理客戶端請求使用的時間(1.3.9, 1.2.6); 從讀取客戶端的第一個字節開始計時。

  • NGINX 全域變數中, 下面的 request url 中, $request_uri 是哪一段? /test1/test2?test1=123&test2=456
    這個變量等於包含一些客戶端請求參數的原始URI,它無法修改,請查看$uri更改或重寫URI,不包含主機名,例如:”/cnphp/test.php?arg=freemouse”。

    http://34.83.35.165/test1/test2?test1=123&test2=456
  • NGINX 全域變數中, $scheme 是什麼? 請求使用的Web協議, “http” 或“https”

  • NGINX 全域變數中, $sent_http_name是什麼? 可以設置任意http響應頭字段; 變量名中的後半部分“name”可以替換成任意響應頭字段,如需要設置響應頭Content-length,那麼將“-”替換為下劃線,大寫字母替換為小寫,形如:$sent_http_content_length 4096即可。

  • NGINX 全域變數中, $server_addr 是什麼? 服務器端地址,非外部 IP, 機器在該網域的地址

  • NGINX 全域變數中, $server_port 是什麼? 服務器端口

  • NGINX 全域變數中, $server_protocol 是什麼? 服務器的HTTP版本, 通常為“HTTP/1.0” 或“HTTP/1.1”

  • NGINX 全域變數中, $status 是什麼? HTTP status code

  • NGINX 全域變數中, $time_iso8601 是什麼? 服務器時間的ISO 8610格式, 如 2019-11-27T14:11:04+00:00

  • NGINX 全域變數中, $time_local 是什麼? 服務器時間(LOG Format 格式) 27/Nov/2019:14:11:38 +0000

  • NGINX 全域變數中, $uri 是什麼? 請求中的當前URI(不帶請求參數,參數位於$args),可以不同於瀏覽器傳遞的$request_uri的值,它可以通過內部重定向,或者使用index指令進行修改,$uri不包含主機名,如”/foo/bar.html”。

  • NGINX 全域變數中, 下面的 request url 中, $uri 是哪一段? /test1/test2

    http://34.83.35.165/test1/test2?test1=123&test2=456
  • 參考以下的 NGINX 設定, 並思考接下來一連串的問題

    upstream backend {
    server backend1.example.com weight=5;
    server 127.0.0.1:8080 max_fails=3 fail_timeout=30s;
    server unix:/tmp/backend3;

    server backup1.example.com backup;
    }

    server {
    location / {
    proxy_pass http://backend;
    }
    }
  • 以上的 nginx 設定中, 到 / 的請求會被送到哪裡?
    upstream backend

  • 以上的 nginx 設定中, 每七個請求中, 會有幾個到 backend1.example.com? 為什麼?
    5 個
    因為 weight=5

  • 以上的 nginx 設定中, 每七個請求中, 會有幾個到 127.0.0.1:8080? 為什麼?
    1 個
    因為沒有特別分配權重, 預設平均分配

  • 以上的 nginx 設定中, 每七個請求中, 會有幾個到 unix:/tmp/backend3 為什麼?
    1 個
    因為沒有特別分配權重, 預設平均分配

  • 以上的 nginx 設定中, 如果送給 server 127.0.0.1:8080 出錯了, 會怎麼樣?
    送往下一個, 即 unix:/tmp/backend3

  • 以上的 nginx 設定中, 如果 upstream 中的 server 都無法服務, 會怎麼樣?
    送給 backup server, 即 backup1.example.com, 客戶會收到這一個 server 的回應




NGINX Cookbook

  • NGINX 中, root 語法的意思是什麼?
    將會在 root 所定義的位置中尋找請求中帶過來的 URL 部分
Markdown 學習筆記 使用 Google Stackdriver 來除錯, 追蹤, 紀錄 以及部署紀錄點

留言

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×