NGINX 從入門到精通,學會這些就夠了

北行發表於2020-06-22

20200622104645

工作這麼多年一直用的都是NGINX,也一直想寫總結,不過之前都是在上班,下班後就比較懶了,所以一直擱置著,趁著現在離職了有時間,就想把之前欠下的都補上,也算是對自己近年來工作技能的總結,希望這篇文章能幫助到你。

Nginx(發音同“engine X”)是非同步框架的網頁伺服器,也可以用作反向代理、負載平衡器和HTTP快取。該軟體由伊戈爾·賽索耶夫建立並於2004年首次公開發布。2011年成立同名公司以提供支援。2019年3月11日,Nginx公司被F5 Networks以6.7億美元收購。

#!/usr/bin/env bash

DIR=/Users/shiwenyuan/webserver
mkdir -p $DIR
cd $DIR
mkdir run

tar -zxvf /Users/shiwenyuan/totalXbox/project/phpstorm/xlegal/devops/opbin/nginx_modules.tgz -C $DIR

mkdir tmp
cd tmp

wget http://nginx.org/download/nginx-1.8.1.tar.gz -O nginx-1.8.1.tar.gz

tar -zxvf nginx-1.8.1.tar.gz

cd nginx-1.8.1

./configure \
--with-http_realip_module \
--with-http_stub_status_module \
--with-http_addition_module \
--add-module=$DIR/nginx_modules/echo-nginx-module-master \
--add-module=$DIR/nginx_modules/headers-more-nginx-module-master \
--add-module=$DIR/nginx_modules/memc-nginx-module-master \
--add-module=$DIR/nginx_modules/nginx-http-concat-master \
--add-module=$DIR/nginx_modules/ngx_devel_kit-master \
--add-module=$DIR/nginx_modules/ngx_http_consistent_hash-master \
--add-module=$DIR/nginx_modules/ngx_http_enhanced_memcached_module-master \
--add-module=$DIR/nginx_modules/ngx_http_upstream_ketama_chash-0.6 \
--add-module=$DIR/nginx_modules/srcache-nginx-module-master \
--with-pcre=$DIR/nginx_modules/pcre-8.38 \
--prefix=$DIR
if [[ $? -ne 0 ]];then
    echo 'error occured\n'
    exit 1
fi
make && make install
cd $DIR
/bin/rm -rf tmp
/bin/rm -rf node_modules

/sbin/nginx -t
  • nginx # 啟動nginx
  • nginx -s reload # 向主程式傳送訊號,重新載入配置檔案,熱重啟
  • nginx -s reopen # 重啟 Nginx
  • nginx -s stop # 快速關閉
  • nginx -s quit # 等待工作程式處理完成後關閉
  • nginx -t # 檢視當前 Nginx 配置是否有錯誤
  • nginx -t -c <配置路徑> # 檢查配置是否有問題,如果已經在配置目錄,則不需要-c

20200622144019

  • main:全域性設定
  • events:配置影響Nginx伺服器或與使用者的網路連線
  • http:http模組設定
  • upstream:負載均衡設定
  • server:http伺服器配置,一個http模組中可以有多個server模組
  • location:url匹配配置,一個server模組中可以包含多個location模組

一個nginx配置檔案的結構就像nginx.conf顯示的那樣,配置檔案的語法規則:

  1. 配置檔案由模組組成
  2. 使用#新增註釋
  3. 使用$使用變數
  4. 使用include引用多個配置檔案

訪問路徑


www.example.com/index.php
        |
        |
      Nginx
        |
        |
php-fpm監聽127.0.0.1:9000地址
        |
        |
www.example.com/index.php請求轉發到127.0.0.1:9000
        |
        |
nginx的fastcgi模組將http請求對映為fastcgi請求
        |
        | 
  php-fpm監聽fastcgi請求
        |
        | 
php-fpm接收到請求,並透過worker程式處理請求
        |
        | 
php-fpm處理完請求,返回給nginx
        |
        | 

nginx與php通訊方式

tcp-socket

tcp socket通訊方式,需要在nginx配置檔案中填寫php-fpm執行的ip地址和埠號,該方式支援跨伺服器,即nginx和php-fpm不再同一機器上時。

location ~ \.php$ {
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_pass 127.0.0.1:9000;
    fastcgi_index index.php;
}

unix-socket

unix socket通訊方式,需要在nginx配置檔案中填寫php-fpm執行的pid檔案地址。unix socket又叫IPC(inter process communication程式間通訊)socket,用於實現統一主機上程式間通訊。

location ~ \.php$ {
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_pass unix:/var/run/php5-fpm.sock;
    fastcgi_index index.php;
}

兩者間的區別

Unix socket 不需要經過網路協議棧,不需要打包拆包、計算校驗和、維護序號和應答等,只是將應用層資料從一個程式複製到另一個程式。所以其效率比 tcp socket 的方式要高,可減少不必要的 tcp 開銷。不過,unix socket 高併發時不穩定,連線數爆發時,會產生大量的長時快取,在沒有面向連線協議的支撐下,大資料包可能會直接出錯不返回異常。而 tcp 這樣的面向連線的協議,可以更好的保證通訊的正確性和完整性。

所以,如果面臨的是高併發業務,則考慮優先使用更可靠的tcp socket,我們可以透過負載均衡、核心最佳化等手段來提供效率。

什麼是動靜分離

在Web開發中,通常來說,動態資源其實就是指那些後臺資源,而靜態資源就是指HTML,JavaScript,CSS,img等檔案。
在使用前後端分離之後,可以很大程度的提升靜態資源的訪問速度,同時在開發過程中也可以讓前後端開發並行可以有效的提高開發時間,也可以有效的減少聯調時間 。

動靜分離方案

  • 直接使用不同的域名,把靜態資源放在獨立的雲伺服器上,這個種方案也是目前比較推崇的。
  • 動態請求和靜態檔案放在一起,透過nginx配置分開
server {
  location /www/ {
      root /www/;
    index index.html index.htm;
  }

  location /image/ {
      root /image/;
  }
}

反向代理常用於不想把埠暴露出去,直接訪問域名處理請求。

server {
    listen    80;
    server_name www.phpblog.com.cn;
    location /swoole/ {
        proxy_pass http://127.0.0.1:9501;
    }
    location /node/ {
        proxy_pass http://127.0.0.1:9502;
    }

}
upstream phpServer{
    server 127.0.0.1:9501;
    server 127.0.0.1:9502;
    server 127.0.0.1:9503;
}
server {
    listen    80;
    server_name www.phpblog.com.cn;
    location / {
        proxy_pass http://phpServer;
        proxy_redirect     off;
        proxy_set_header   Host             $host;
        proxy_set_header   X-Real-IP        $remote_addr;
        proxy_next_upstream error timeout invalid_header;
        proxy_max_temp_file_size 0;
        proxy_connect_timeout      90;
        proxy_send_timeout         90;
        proxy_read_timeout         90;
        proxy_buffer_size          4k;
        proxy_buffers              4 32k;
        proxy_busy_buffers_size    64k;
        proxy_temp_file_write_size 64k;
    }
}

常見的負載均衡策略

round-robin/輪詢: 到應用伺服器的請求以round-robin/輪詢的方式被分發

upstream phpServer{
    server 127.0.0.1:9501 weight=3;
    server 127.0.0.1:9502;
    server 127.0.0.1:9503;
}

在這個配置中,每5個新請求將會如下的在應用例項中分派: 3個請求分派去9501,一個去9502,另外一個去9503.

least-connected/最少連線:下一個請求將被分派到活動連線數量最少的伺服器

upstream phpServer{
    least_conn;
    server 127.0.0.1:9501;
    server 127.0.0.1:9502;
    server 127.0.0.1:9503;
}

當某些請求需要更長時間來完成時,最少連線可以更公平的控制應用例項上的負載。

ip-hash/IP雜湊: 使用hash演算法來決定下一個請求要選擇哪個伺服器(基於客戶端IP地址)

upstream phpServer{
    ip_hash;
    server 127.0.0.1:9501;
    server 127.0.0.1:9502;
    server 127.0.0.1:9503;
}

將一個客戶端繫結給某個特定的應用伺服器;

由於瀏覽器同源策略的存在使得一個源中載入來自其它源中資源的行為受到了限制。即會出現跨域請求禁止。
所謂同源是指:域名、協議、埠相同。

20200622140049

server {
        listen       80;
        server_name  www.phpblog.com.cn;
        root   /Users/shiwenyuan/blog/public;
        index  index.html index.htm index.php;
        location / {
            try_files $uri $uri/ /index.php?$query_string;
        }
        add_header 'Access-Control-Allow-Origin' "$http_origin";
        add_header 'Access-Control-Allow-Credentials' 'true';
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, DELETE, PUT, PATCH';
        add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,X-XSRF-TOKEN';

        location ~ \.php$ {
            fastcgi_pass   127.0.0.1:9000;
            fastcgi_index  index.php;
            fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;
            include        fastcgi_params;
        }
        error_page  404              /404.html;
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
}
  • Access-Control-Allow-Origin:允許的域名,只能填 *(萬用字元)或者單域名。
  • Access-Control-Allow-Methods: 允許的方法,多個方法以逗號分隔。
  • Access-Control-Allow-Headers: 允許的頭部,多個方法以逗號分隔。
  • Access-Control-Allow-Credentials: 是否允許傳送Cookie。
    nginx配置https證照認證

    應用場景

  • seo最佳化
  • 安全
  • 流量轉發
location ^~ /saas {
    root /home/work/php/saas/public;
    index index.php;
    rewrite ^/saas(/[^\?]*)?((\?.*)?)$ /index.php$1$2 last;
    break;
}

日誌切割指令碼

#!/bin/bash
#設定你的日誌存放的目錄
log_files_path="/mnt/usr/logs/"
#日誌以年/月的目錄形式存放
log_files_dir=${log_files_path}"backup/"
#設定需要進行日誌分割的日誌檔名稱,多個以空格隔開
log_files_name=(access.log error.log)
#設定nginx的安裝路徑
nginx_sbin="/mnt/usr/sbin/nginx -c /mnt/usr/conf/nginx.conf"
#Set how long you want to save
save_days=10

############################################
#Please do not modify the following script #
############################################
mkdir -p $log_files_dir

log_files_num=${#log_files_name[@]}
#cut nginx log files
for((i=0;i<$log_files_num;i++));do
    mv ${log_files_path}${log_files_name[i]} ${log_files_dir}${log_files_name[i]}_$(date -d "yesterday" +"%Y%m%d")
done
$nginx_sbin -s reload

圖片防盜鏈

server {
  listen       80;        
  server_name  *.phpblog.com.cn;

  # 圖片防盜鏈
  location ~* \.(gif|jpg|jpeg|png|bmp|swf)$ {
    valid_referers none blocked server_names ~\.google\. ~\.baidu\. *.qq.com;
    if ($invalid_referer){
      return 403;
    }
  }
}

nginx訪問控制

location ~ \.php$ {
    allow 127.0.0.1;  #只允許127.0.0.1的訪問,其他均拒絕
    deny all;
    fastcgi_pass   127.0.0.1:9000;
    fastcgi_index  index.php;
    fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;
    include        fastcgi_params;
}

丟棄不受支援的副檔名的請求

location ~ \.(js|css|sql)$ {
    deny all;
}

後話

創作不易,希望對你有所幫助。
如果本篇部落格有任何錯誤,請批評指教,不勝感激!!!

文章將持續更新中,也可以透過微信搜尋[石先生的私房菜]或者下方二維碼關注第一時間閱讀和催更,除了部落格以外還會定期傳送leetcodephp版題解

20200619155130


2020-06-22:感謝@輕描淡寫提交了一處錯別字,已修正。
2020-06-24:感謝@Jiannei提交了一處錯別字,已修正。
2020-07-03:感謝@bigbug提交的文字最佳化,已修正。
2020-07-03:感謝@MasterPoser提交的文字最佳化,已修正。

本作品採用《CC 協議》,轉載必須註明作者和本文連結
原創不易,轉載請註明出處

相關文章