Nginx 最全操作总结
作者:chrootliu,騰訊 QQ 音樂前端開發工程師
本文將會從:安裝 -> 全局配置 -> 常用的各種配置 來書寫,其中常用配置寫的炒雞詳細,需要的童鞋可以直接滑倒相應的位置查看。
安裝 nginx
下載 nginx 的壓縮包文件到根目錄,官網下載地址:nginx.org/download/nginx-x.xx.xx.tar.gz
yum?update?#更新系統軟件 cd?/ wget?nginx.org/download/nginx-1.17.2.tar.gz解壓 tar.gz 壓縮包文件,進去 nginx-1.17.2
tar?-xzvf?nginx-1.17.2.tar.gz cd?nginx-1.17.2進入文件夾后進行配置檢查
./configure通過安裝前的配置檢查,發現有報錯。檢查中發現一些依賴庫沒有找到,這時候需要先安裝 nginx 的一些依賴庫
yum?-y?install?pcre*?#安裝使nginx支持rewrite yum?-y?install?gcc-c++ yum?-y?install?zlib* yum?-y?install?openssl?openssl-devel再次進行檢查操作 ./configure 沒發現報錯顯示,接下來進行編譯并安裝的操作
?//?檢查模塊支持./configure??--prefix=/usr/local/nginx??--with-http_ssl_module?--with-http_v2_module?--with-http_realip_module?--with-http_addition_module?--with-http_sub_module?--with-http_dav_module?--with-http_flv_module?--with-http_mp4_module?--with-http_gunzip_module?--with-http_gzip_static_module?--with-http_auth_request_module?--with-http_random_index_module?--with-http_secure_link_module?--with-http_degradation_module?--with-http_slice_module?--with-http_stub_status_module?--with-mail?--with-mail_ssl_module?--with-stream?--with-stream_ssl_module?--with-stream_realip_module?--with-stream_ssl_preread_module?--with-threads?--user=www?--group=www這里得特別注意下,你以后需要用到的功能模塊是否存在,不然以后添加新的包會比較麻煩。
查看默認安裝的模塊支持
命令 ls nginx-1.17.2 查看 nginx 的文件列表,可以發現里面有一個 auto 的目錄。
在這個 auto 目錄中有一個 options 文件,這個文件里面保存的就是 nginx 編譯過程中的所有選項配置。
通過命令:cat nginx-1.17.2/auto/options | grep YES就可以查看
nginx 編譯安裝時,怎么查看安裝模塊
編譯并安裝
make?&&?make?install這里需要注意,模塊的支持跟后續的 nginx 配置有關,比如 SSL,gzip 壓縮等等,編譯安裝前最好檢查需要配置的模塊存不存在。
查看 nginx 安裝后在的目錄,可以看到已經安裝到 /usr/local/nginx 目錄了
whereis?nginx $nginx:?/usr/local/nginx啟動 nginx 服務
cd?/usr/local/nginx/sbin/ ./nginx服務啟動的時候報錯了:nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use) ,通過命令查看本機網絡地址和端口等一些信息,找到被占用的 80 端口 netstat -ntpl 的 tcp 連接,并殺死進程(kill 進程 pid)
netstat?-ntpl kill?進程PID繼續啟動 nginx 服務,啟動成功
./nginx在瀏覽器直接訪問 ip 地址,頁面出現 Welcome to Nginx! 則安裝成功。
nginx 配置
基本結構
main????????#?全局配置,對全局生效 ├──?events??#?配置影響?nginx?服務器或與用戶的網絡連接 ├──?http????#?配置代理,緩存,日志定義等絕大多數功能和第三方模塊的配置 │???├──?upstream?#?配置后端服務器具體地址,負載均衡配置不可或缺的部分 │???├──?server???#?配置虛擬主機的相關參數,一個?http?塊中可以有多個?server?塊 │???├──?server │???│???├──?location??#?server?塊可以包含多個?location?塊,location?指令用于匹配?uri │???│???├──?location │???│???└──?... │???└──?... └──?...主要配置含義
main:nginx 的全局配置,對全局生效。
events:配置影響 nginx 服務器或與用戶的網絡連接。
http:可以嵌套多個 server,配置代理,緩存,日志定義等絕大多數功能和第三方模塊的配置。
server:配置虛擬主機的相關參數,一個 http 中可以有多個 server。
location:配置請求的路由,以及各種頁面的處理情況。
upstream:配置后端服務器具體地址,負載均衡配置不可或缺的部分。
nginx.conf 配置文件的語法規則
配置文件由指令與指令塊構成
每條指令以 “;” 分號結尾,指令與參數間以空格符號分隔
指令塊以 {} 大括號將多條指令組織在一起
include 語句允許組合多個配置文件以提升可維護性
通過 # 符號添加注釋,提高可讀性
通過 $ 符號使用變量
部分指令的參數支持正則表達式,例如常用的 location 指令
內置變量
nginx 常用的內置全局變量,你可以在配置中隨意使用:
常用命令
這里列舉幾個常用的命令:
nginx?-s?reload??#?向主進程發送信號,重新加載配置文件,熱重啟 nginx?-s?reopen??#?重啟?Nginx nginx?-s?stop????#?快速關閉 nginx?-s?quit????#?等待工作進程處理完成后關閉 nginx?-T?????????#?查看當前?Nginx?最終的配置 nginx?-t?-c?<配置路徑>??#?檢查配置是否有問題,如果已經在配置目錄,則不需要?-c以上命令通過 nginx -h 就可以查看到,還有其它不常用這里未列出。
Linux 系統應用管理工具 systemd 關于 nginx 的常用命令:
systemctl?start?nginx????#?啟動?Nginx systemctl?stop?nginx?????#?停止?Nginx systemctl?restart?nginx??#?重啟?Nginx systemctl?reload?nginx???#?重新加載?Nginx,用于修改配置后 systemctl?enable?nginx???#?設置開機啟動?Nginx systemctl?disable?nginx??#?關閉開機啟動?Nginx systemctl?status?nginx???#?查看?Nginx?運行狀態配置 nginx 開機自啟
利用 systemctl 命令:
如果用 yum install 命令安裝的 nginx,yum 命令會自動創建 nginx.service 文件,直接用命令:
systemctl?enable?nginx???#?設置開機啟動?Nginx systemctl?disable?nginx??#?關閉開機啟動?Nginx就可以設置開機自啟,否則需要在系統服務目錄里創建 nginx.service 文件。
創建并打開 nginx.service 文件:
vi?/lib/systemd/system/nginx.service內容如下:
[Unit] Description=nginx After=network.target[Service] Type=forking ExecStart=/usr/local/nginx/sbin/nginx ExecReload=/usr/local/nginx/sbin/nginx?-s?reload ExecStop=/usr/local/nginx/sbin/nginx?-s?quit PrivateTmp=true[Install] WantedBy=multi-user.target:wq 保存退出,運行 systemctl daemon-reload 使文件生效。
這樣便可以通過以下命令操作 nginx 了:
systemctl?start?nginx.service?#?啟動nginx服務 systemctl?enable?nginx.service?#?設置開機啟動 systemctl?disable?nginx.service?#?停止開機自啟動 systemctl?status?nginx.service?#?查看服務當前狀態 systemctl?restart?nginx.service?#?重新啟動服務 systemctl?is-enabled?nginx.service?#查詢服務是否開機啟動通過開機啟動命令腳本實現開機自啟
創建開機啟動命令腳本文件:
vi?/etc/init.d/nginx在這個 nginx 文件中插入一下啟動腳本代碼,啟動腳本代碼來源網絡復制,實測有效:
#!?/bin/bash #?chkconfig:?-?85?15 PATH=/usr/local/nginx DESC="nginx?daemon" NAME=nginx DAEMON=$PATH/sbin/$NAME CONFIGFILE=$PATH/conf/$NAME.conf PIDFILE=$PATH/logs/$NAME.pid scriptNAME=/etc/init.d/$NAME set?-e [?-x?"$DAEMON"?]?||?exit?0 do_start()?{ $DAEMON?-c?$CONFIGFILE?||?echo?-n?"nginx?already?running" } do_stop()?{ $DAEMON?-s?stop?||?echo?-n?"nginx?not?running" } do_reload()?{ $DAEMON?-s?reload?||?echo?-n?"nginx?can't?reload" } case?"$1"?in start) echo?-n?"Starting?$DESC:?$NAME" do_start echo?"." ;; stop) echo?-n?"Stopping?$DESC:?$NAME" do_stop echo?"." ;; reload|graceful) echo?-n?"Reloading?$DESC?configuration..." do_reload echo?"." ;; restart) echo?-n?"Restarting?$DESC:?$NAME" do_stop do_start echo?"." ;; *) echo?"Usage:?$scriptNAME?{start|stop|reload|restart}"?>&2 exit?3 ;; esac exit?0設置所有人都有對這個啟動腳本 nginx 文件的執行權限:
chmod?a+x?/etc/init.d/nginx把 nginx 加入系統服務中:
chkconfig?--add?nginx把服務設置為開機啟動:
chkconfig?nginx?onreboot 重啟系統生效,可以使用上面 systemctl 方法相同的命令:
systemctl?start?nginx.service?#?啟動nginx服務 systemctl?enable?nginx.service?#?設置開機啟動 systemctl?disable?nginx.service?#?停止開機自啟動 systemctl?status?nginx.service?#?查看服務當前狀態 systemctl?restart?nginx.service?#?重新啟動服務 systemctl?is-enabled?nginx.service?#查詢服務是否開機啟動如果服務啟動的時候出現 Restarting nginx daemon: nginxnginx: [error] open() "/usr/local/nginx/logs/nginx.pid" failed (2: No such file or directory) nginx not running 的錯誤,通過 nginx -c 參數指定配置文件即可解決
/usr/local/nginx/sbin/nginx?-c?/usr/local/nginx/conf/nginx.conf如果服務啟動中出現 nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use) 的錯誤,可以先通過 service nginx stop 停止服務,再啟動就好。
配置 nginx 全局可用
當你每次改了 nginx.conf 配置文件的內容都需要重新到 nginx 啟動目錄去執行命令,或者通過 -p 參數指向特定目錄,會不會感覺很麻煩?
例如:直接執行 nginx -s reload 會報錯 -bash: nginx: command not found,需要到 /usr/local/nginx/sbin 目錄下面去執行,并且是執行 ./nginx -s reload。
這里有兩種方式可以解決,一種是通過腳本對 nginx 命令包裝,這里介紹另外一種比較簡單:通過把 nginx 配置到環境變量里,用 nginx 執行指令即可。步驟如下:
1、編輯 /etc/profile
vi?/etc/profile2、在最后一行添加配置,:wq 保存
export?PATH=$PATH:/usr/local/nginx/sbin3、使配置立即生效
source?/etc/profile這樣就可以愉快的直接在全局使用 nginx 命令了。
nginx 常用功能
反向代理
我們最常說的反向代理的是通過反向代理解決跨域問題。
其實反向代理還可以用來控制緩存(代理緩存 proxy cache),進行訪問控制等等,以及后面說的負載均衡其實都是通過反向代理來實現的。
server?{listen????8080;#?用戶訪問?ip:8080/test?下的所有路徑代理到?githublocation?/test?{proxy_pass???https://github.com;}#?所有?/api?下的接口訪問都代理到本地的?8888?端口#?例如你本地運行的?java?服務的端口是?8888,接口都是以?/api?開頭location?/api?{proxy_pass???http://127.0.0.1:8888;}}訪問控制
server?{location?~?^/index.html?{#?匹配?index.html?頁面?除了?127.0.0.1?以外都可以訪問deny?192.168.1.1;deny?192.168.1.2;allow?all;} }上面的命令表示禁止 192.168.1.1 和 192.168.1.2 兩個 ip 訪問,其它全部允許。從上到下的順序,匹配到了便跳出,可以按你的需求設置。
負載均衡
通過負載均衡充利用服務器資源,nginx 目前支持自帶 4 種負載均衡策略,還有 2 種常用的第三方策略。
輪詢策略(默認)
每個請求按時間順序逐一分配到不同的后端服務器,如果有后端服務器掛掉,能自動剔除。但是如果其中某一臺服務器壓力太大,出現延遲,會影響所有分配在這臺服務器下的用戶。
http?{upstream?test.com?{server?192.168.1.12:8887;server?192.168.1.13:8888;}server?{location?/api?{proxy_pass??http://test.com;}} }根據服務器權重
例如要配置:10 次請求中大概 1 次訪問到 8888 端口,9 次訪問到 8887 端口:
http?{upstream?test.com?{server?192.168.1.12:8887?weight=9;server?192.168.1.13:8888?weight=1;}server?{location?/api?{proxy_pass??http://test.com;}} }客戶端 ip 綁定(ip_hash)
來自同一個 ip 的請求永遠只分配一臺服務器,有效解決了動態網頁存在的 session 共享問題。例如:比如把登錄信息保存到了 session 中,那么跳轉到另外一臺服務器的時候就需要重新登錄了。
所以很多時候我們需要一個客戶只訪問一個服務器,那么就需要用 ip_hash 了。
http?{upstream?test.com?{ip_hash;server?192.168.1.12:8887;server?192.168.1.13:8888;}server?{location?/api?{proxy_pass??http://test.com;}} }最小連接數策略
將請求優先分配給壓力較小的服務器,它可以平衡每個隊列的長度,并避免向壓力大的服務器添加更多的請求。
http?{upstream?test.com?{least_conn;server?192.168.1.12:8887;server?192.168.1.13:8888;}server?{location?/api?{proxy_pass??http://test.com;}} }最快響應時間策略(依賴于第三方 NGINX Plus)
依賴于 NGINX Plus,優先分配給響應時間最短的服務器。
http?{upstream?test.com?{fair;server?192.168.1.12:8887;server?192.168.1.13:8888;}server?{location?/api?{proxy_pass??http://test.com;}} }按訪問 url 的 hash 結果(第三方)
按訪問 url 的 hash 結果來分配請求,使每個 url 定向到同一個后端服務器,后端服務器為緩存時比較有效。在 upstream 中加入 hash 語句,server 語句中不能寫入 weight 等其他的參數,hash_method 是使用的 hash 算法
http?{upstream?test.com?{hash?$request_uri;hash_method?crc32;server?192.168.1.12:8887;server?192.168.1.13:8888;}server?{location?/api?{proxy_pass??http://test.com;}} }采用 HAproxy 的 loadbalance uri 或者 nginx 的 upstream_hash 模塊,都可以做到針對 url 進行哈希算法式的負載均衡轉發。
gzip 壓縮
開啟 gzip 壓縮可以大幅減少 http 傳輸過程中文件的大小,可以極大的提高網站的訪問速度,基本是必不可少的優化操作:
gzip??on;?#?開啟gzip?壓縮 #?gzip_types #?gzip_static?on; #?gzip_proxied?expired?no-cache?no-store?private?auth; #?gzip_buffers?16?8k; gzip_min_length?1k; gzip_comp_level?4; gzip_http_version?1.0; gzip_vary?off; gzip_disable?"MSIE?[1-6]\.";解釋一下:
gzip_types:要采用 gzip 壓縮的 MIME 文件類型,其中 text/html 被系統強制啟用;
gzip_static:默認 off,該模塊啟用后,Nginx 首先檢查是否存在請求靜態文件的 gz 結尾的文件,如果有則直接返回該 .gz 文件內容;
gzip_proxied:默認 off,nginx 做為反向代理時啟用,用于設置啟用或禁用從代理服務器上收到相應內容 gzip 壓縮;
gzip_buffers:獲取多少內存用于緩存壓縮結果,16 8k 表示以 8k*16 為單位獲得;
gzip_min_length:允許壓縮的頁面最小字節數,頁面字節數從 header 頭中的 Content-Length 中進行獲取。默認值是 0,不管頁面多大都壓縮。建議設置成大于 1k 的字節數,小于 1k 可能會越壓越大;
gzip_comp_level:gzip 壓縮比,壓縮級別是 1-9,1 壓縮級別最低,9 最高,級別越高壓縮率越大,壓縮時間越長,建議 4-6;
gzip_http_version:默認 1.1,啟用 gzip 所需的 HTTP 最低版本;
gzip_vary:用于在響應消息頭中添加 Vary:Accept-Encoding,使代理服務器根據請求頭中的 Accept-Encoding 識別是否啟用 gzip 壓縮;
gzip_disable 指定哪些不需要 gzip 壓縮的瀏覽器
其中第 2 點,普遍是結合前端打包的時候打包成 gzip 文件后部署到服務器上,這樣服務器就可以直接使用 gzip 的文件了,并且可以把壓縮比例提高,這樣 nginx 就不用壓縮,也就不會影響速度。一般不追求極致的情況下,前端不用做任何配置就可以使用啦~
附前端 webpack 開啟 gzip 壓縮配置,在 vue-cli3 的 vue.config.js 配置文件中:
const?CompressionWebpackPlugin?=?require('compression-webpack-plugin')module.exports?=?{//?gzip?配置configureWebpack:?config?=>?{if?(process.env.NODE_ENV?===?'production')?{//?生產環境return?{plugins:?[new?CompressionWebpackPlugin({test:?/\.js$|\.html$|\.css/,????//?匹配文件名threshold:?1024,???????????????//?文件壓縮閾值,對超過?1k?的進行壓縮deleteOriginalAssets:?false?????//?是否刪除源文件})]}}},... }HTTP 服務器
nginx 本身也是一個靜態資源的服務器,當只有靜態資源的時候,就可以使用 nginx 來做服務器:
server?{listen???????80;server_name??localhost;location?/?{root???/usr/local/app;index??index.html;} }這樣如果訪問 http://ip 就會默認訪問到 /usr/local/app 目錄下面的 index.html,如果一個網站只是靜態頁面的話,那么就可以通過這種方式來實現部署,比如一個靜態官網。
動靜分離
就是把動態和靜態的請求分開。方式主要有兩種:
一種是純粹把靜態文件獨立成單獨的域名,放在獨立的服務器上,也是目前主流推崇的方案
一種方法就是動態跟靜態文件混合在一起發布, 通過 nginx 配置來分開
注意上面設置了 expires,當 nginx 設置了 expires 后,例如設置為:expires 10d; 那么,所在的 location 或 if 的內容,用戶在 10 天內請求的時候,都只會訪問瀏覽器中的緩存,而不會去請求 nginx 。
請求限制
對于大流量惡意的訪問,會造成帶寬的浪費,給服務器增加壓力。可以通過 nginx 對于同一 IP 的連接數以及并發數進行限制。合理的控制還可以用來防止 DDos 和 CC 攻擊。
關于請求限制主要使用 nginx 默認集成的 2 個模塊:
limit_conn_module 連接頻率限制模塊
limit_req_module 請求頻率限制模塊
涉及到的配置主要是:
limit_req_zone 限制請求數
limit_conn_zone 限制并發連接數
通過 limit_req_zone 限制請求數
http{limit_conn_zone?$binary_remote_addrzone=limit:10m;?//?設置共享內存空間大server{location?/{limit_conn addr 5;?#?同一用戶地址同一時間只允許有5個連接。}} }如果共享內存空間被耗盡,服務器將會對后續所有的請求返回 503 (Service Temporarily Unavailable) 錯誤。
當多個 limit_conn_zone 指令被配置時,所有的連接數限制都會生效。比如,下面配置不僅會限制單一 IP 來源的連接數,同時也會限制單一虛擬服務器的總連接數:
limit_conn_zone?$binary_remote_addr?zone=perip:10m; limit_conn_zone?$server_name?zone=perserver:10m; server?{limit_conn?perip?10;?#?限制每個?ip?連接到服務器的數量limit_conn?perserver?2000;?#?限制連接到服務器的總數 }通過 limit_conn_zone 限制并發連接數
limit_req_zone?$binary_remote_addr?zone=creq:10?mrate=10r/s; server{location?/{limit_req?zone=creq?burst=5;} }限制平均每秒不超過一個請求,同時允許超過頻率限制的請求數不多于 5 個。如果不希望超過的請求被延遲,可以用 nodelay 參數,如:
limit_req zone=creq burst=5 nodelay;
這里只是簡單講講,讓大家有這個概念,配置的時候可以深入去找找資料。
正向代理
正向代理,意思是一個位于客戶端和原始服務器(origin server)之間的服務器,為了從原始服務器取得內容,客戶端向代理發送一個請求并指定目標(原始服務器),然后代理向原始服務器轉交請求并將獲得的內容返回給客戶端。客戶端才能使用正向代理,比如我們使用的 VPN 服務就是正向代理,直觀區別:
配置正向代理:
resolver?8.8.8.8?#?谷歌的域名解析地址 server?{resolver_timeout?5s;?//?設超時時間location?/?{#?當客戶端請求我的時候,我會把請求轉發給它#?$host?要訪問的主機名?$request_uri?請求路徑proxy_pass?http://$host$request_uri;} }正向代理的對象是客戶端,服務器端看不到真正的客戶端。
圖片防盜鏈
server?{listen???????80;server_name??*.test;#?圖片防盜鏈location?~*?\.(gif|jpg|jpeg|png|bmp|swf)$?{valid_referers?none?blocked?server_names?~\.google\.?~\.baidu\.?*.qq.com;??#?只允許本機?IP?外鏈引用,將百度和谷歌也加入白名單有利于?SEOif?($invalid_referer){return?403;}} }以上設置就能防止其它網站利用外鏈訪問我們的圖片,有利于節省流量
適配 PC 或移動設備
根據用戶設備不同返回不同樣式的站點,以前經常使用的是純前端的自適應布局,但是復雜的網站并不適合響應式,無論是復雜性和易用性上面還是不如分開編寫的好,比如我們常見的淘寶、京東。
根據用戶請求的 user-agent 來判斷是返回 PC 還是 H5 站點:
server?{listen?80;server_name?test.com;location?/?{root??/usr/local/app/pc;?#?pc?的?html?路徑if?($http_user_agent?~*?'(Android|webOS|iPhone|iPod|BlackBerry)')?{root?/usr/local/app/mobile;?#?mobile?的?html?路徑}index?index.html;} }設置二級域名
新建一個 server 即可:
server?{listen?80;server_name?admin.test.com;?//?二級域名location?/?{root??/usr/local/app/admin;?#?二級域名的?html?路徑index?index.html;} }配置 HTTPS
這里我使用的是 certbot 免費證書,但申請一次有效期只有 3 個月(好像可以用 crontab 嘗試配置自動續期,我暫時沒試過):
先安裝 certbot
wget?https://dl.eff.org/certbot-auto chmod?a+x?certbot-auto申請證書(注意:需要把要申請證書的域名先解析到這臺服務器上,才能申請):
sudo?./certbot-auto?certonly?--standalone?--email?admin@abc.com?-d?test.com?-d?www.test.com執行上面指令,按提示操作。
Certbot 會啟動一個臨時服務器來完成驗證(會占用 80 端口或 443 端口,因此需要暫時關閉 Web 服務器),然后 Certbot 會把證書以文件的形式保存,包括完整的證書鏈文件和私鑰文件。
文件保存在 /etc/letsencrypt/live/ 下面的域名目錄下。
修改 nginx 配置:
server{listen?443?ssl?http2;?//?這里還啟用了?http/2.0ssl_certificate?/etc/letsencrypt/live/test.com/fullchain.pem;?#?證書文件地址ssl_certificate_key?/etc/letsencrypt/live/test.com/privkey.pem;?#?私鑰文件地址server_name?test.com?www.test.com;?//?證書綁定的域名 }配置 HTTP 轉 HTTPS
server?{listen??????80;server_name?test.com?www.test.com;#?單域名重定向if?($host?=?'www.sherlocked93.club'){return?301?https://www.sherlocked93.club$request_uri;}#?全局非?https?協議時重定向if?($scheme?!=?'https')?{return?301?https://$server_name$request_uri;}#?或者全部重定向return?301?https://$server_name$request_uri; }以上配置選擇自己需要的一條即可,不用全部加。
單頁面項目 history 路由配置
server?{listen???????80;server_name??fe.sherlocked93.club;location?/?{root???????/usr/local/app/dist;??#?vue?打包后的文件夾index??????index.html?index.htm;try_files??$uri?$uri/?/index.html?@rewrites;?#?默認目錄下的?index.html,如果都不存在則重定向expires?-1;??????????????????????????#?首頁一般沒有強制緩存add_header?Cache-Control?no-cache;}location?@rewrites?{?//?重定向設置rewrite?^(.+)$?/index.html?break;} }vue-router 官網只有一句話 try_files $uri $uri/ /index.html;,而上面做了一些重定向處理。
配置高可用集群(雙機熱備)
當主 nginx 服務器宕機之后,切換到備份的 nginx 服務器
首先安裝 keepalived:
yum?install?keepalived?-y然后編輯 /etc/keepalived/keepalived.conf 配置文件,并在配置文件中增加 vrrp_script 定義一個外圍檢測機制,并在 vrrp_instance 中通過定義 track_script 來追蹤腳本執行過程,實現節點轉移:
global_defs{notification_email?{cchroot@gmail.com}notification_email_from?test@firewall.locsmtp_server?127.0.0.1smtp_connect_timeout?30?//?上面都是郵件配置router_id?LVS_DEVEL?????//?當前服務器名字,用?hostname?命令來查看 } vrrp_script?chk_maintainace?{?//?檢測機制的腳本名稱為chk_maintainacescript?"[[?-e/etc/keepalived/down?]]?&&?exit?1?||?exit?0"?//?可以是腳本路徑或腳本命令//?script?"/etc/keepalived/nginx_check.sh"????//?比如這樣的腳本路徑interval?2??//?每隔2秒檢測一次weight?-20??//?當腳本執行成立,那么把當前服務器優先級改為-20 } vrrp_instanceVI_1?{???//?每一個vrrp_instance就是定義一個虛擬路由器state?MASTER??????//?主機為MASTER,備用機為BACKUPinterface?eth0????//?網卡名字,可以從ifconfig中查找virtual_router_id?51?//?虛擬路由的id號,一般小于255,主備機id需要一樣priority?100??????//?優先級,master的優先級比backup的大advert_int?1??????//?默認心跳間隔authentication?{??//?認證機制auth_type?PASSauth_pass?1111???//?密碼}virtual_ipaddress?{??//?虛擬地址vip172.16.2.8} }其中檢測腳本 nginx_check.sh,這里提供一個:
#!/bin/bash A=`ps?-C?nginx?--no-header?|?wc?-l` if?[?$A?-eq?0?];then/usr/sbin/nginx?#?嘗試重新啟動nginxsleep?2?????????#?睡眠2秒if?[?`ps?-C?nginx?--no-header?|?wc?-l`?-eq?0?];thenkillall keepalived #?啟動失敗,將keepalived服務殺死。將vip漂移到其它備份節點fi fi復制一份到備份服務器,備份 nginx 的配置要將 state 后改為 BACKUP,priority 改為比主機小。設置完畢后各自 service keepalived start 啟動,經過訪問成功之后,可以把 Master 機的 keepalived 停掉,此時 Master 機就不再是主機了 service keepalived stop,看訪問虛擬 IP 時是否能夠自動切換到備機 ip addr。
再次啟動 Master 的 keepalived,此時 vip 又變到了主機上。
配置高可用集群的內容來源于:Nginx 從入門到實踐,萬字詳解!
其它功能和技巧
代理緩存
nginx 的 http_proxy 模塊,提供類似于 Squid 的緩存功能,使用 proxy_cache_path 來配置。
nginx 可以對訪問過的內容在 nginx 服務器本地建立副本,這樣在一段時間內再次訪問該數據,就不需要通過 nginx 服務器再次向后端服務器發出請求,減小數據傳輸延遲,提高訪問速度:
proxy_cache_path?usr/local/cache?levels=1:2?keys_zone=my_cache:10m;server?{listen???????80;server_name??test.com;location?/?{proxy_cache?my_cache;proxy_pass?http://127.0.0.1:8888;proxy_set_header?Host?$host;} }上面的配置表示:nginx 提供一塊 10 M 的內存用于緩存,名字為 my_cache, levels 等級為 1:2,緩存存放的路徑為 usr/local/cache。
訪問日志
訪問日志默認是注釋的狀態,需要可以打開和進行更詳細的配置,一下是 nginx 的默認配置:
http?{log_format??main??'$remote_addr?-?$remote_user?[$time_local]?"$request"?''$status?$body_bytes_sent?"$http_referer"?''"$http_user_agent"?"$http_x_forwarded_for"';access_log??logs/access.log??main; }錯誤日志
錯誤日志放在 main 全局區塊中,童鞋們打開 nginx.conf 就可以看見在配置文件中和下面一樣的代碼了:
#error_log??logs/error.log; #error_log??logs/error.log??notice; #error_log??logs/error.log??info;nginx 錯誤日志默認配置為:
error_log logs/error.log error;
靜態資源服務器
server?{listen???????80;server_name??static.bin;charset?utf-8;????#?防止中文文件名亂碼location?/download?{alias???????????/usr/share/nginx/static;??#?靜態資源目錄autoindex???????????????on;????#?開啟靜態資源列目錄,瀏覽目錄權限autoindex_exact_size????off;???# on(默認)顯示文件的確切大小,單位是byte;off顯示文件大概大小,單位KB、MB、GBautoindex_localtime?????off;???# off(默認)時顯示的文件時間為GMT時間;on顯示的文件時間為服務器時間} }禁止指定 user_agent
nginx 可以禁止指定的瀏覽器和爬蟲框架訪問:
#?http_user_agent?為瀏覽器標識 #?禁止?user_agent?為baidu、360和sohu,~*表示不區分大小寫匹配 if?($http_user_agent?~*?'baidu|360|sohu')?{return?404; }#?禁止?Scrapy?等工具的抓取 if?($http_user_agent?~*?(Scrapy|Curl|HttpClient))?{return?403;請求過濾
根據請求類型過濾
#?非指定請求全返回?403 if?(?$request_method?!~?^(GET|POST|HEAD)$?)?{return?403; }根據狀態碼過濾
error_page?502?503?/50x.html; location?=?/50x.html?{root?/usr/share/nginx/html; }這樣實際上是一個內部跳轉,當訪問出現 502、503 的時候就能返回 50x.html 中的內容,這里需要注意是否可以找到 50x.html 頁面,所以加了個 location 保證找到你自定義的 50x 頁面。
根據 URL 名稱過濾
if?($host?=?zy.com'?)?{#其中?$1是取自regex部分()里的內容,匹配成功后跳轉到的URL。rewrite ^/(.*)$? http://www.zy.com/$1 permanent; }location?/test?{//?/test?全部重定向到首頁rewrite??^(.*)$?/index.html??redirect; }ab 命令
ab 命令全稱為:Apache bench,是 Apache 自帶的壓力測試工具,也可以測試 Nginx、IIS 等其他 Web 服務器:
-n 總共的請求數
-c 并發的請求數
-t 測試所進行的最大秒數,默認值 為 50000
-p 包含了需要的 POST 的數據文件
-T POST 數據所使用的 Content-type 頭信息
測試前需要安裝 httpd-tools:yum install httpd-tools
泛域名路徑分離
這是一個非常實用的技能,經常有時候我們可能需要配置一些二級或者三級域名,希望通過 nginx 自動指向對應目錄,比如:
test1.doc.test.club 自動指向 /usr/local/html/doc/test1 服務器地址;
test2.doc.test.club 自動指向 /usr/local/html/doc/test2 服務器地址;
泛域名轉發
和之前的功能類似,有時候我們希望把二級或者三級域名鏈接重寫到我們希望的路徑,讓后端就可以根據路由解析不同的規則:
test1.serv.test.club/api?name=a 自動轉發到 127.0.0.1:8080/test1/api?name=a
test2.serv.test.club/api?name=a 自動轉發到 127.0.0.1:8080/test2/api?name=a
常見問題
nginx 中怎么設置變量
或許你不知道,nginx 的配置文件使用的是一門微型的編程語言。既然是編程語言,一般也就少不了“變量”這種東西,但是在 nginx 配置中,變量只能存放一種類型的值,因為也只存在一種類型的值,那就是字符串。
例如我們在 nginx.conf 中有這樣一行配置:
set?$name?"chroot";上面使用了 set 配置指令對變量 $name進行了賦值操作,把 "chroot" 賦值給了 $name。nginx 變量名前面有一個 $ 符號,這是記法上的要求。所有的 Nginx 變量在 Nginx 配置文件中引用時都須帶上 $ 前綴。這種表示方法和 Perl、PHP 這些語言是相似的。
這種表示方法的用處在哪里呢,那就是可以直接把變量嵌入到字符串常量中以構造出新的字符串,例如你需要進行一個字符串拼接:
server?{listen???????80;server_name??test.com;location?/?{set?$temp?hello;return?"$temp?world";} }以上當匹配成功的時候就會返回字符串 "hello world" 了。需要注意的是,當引用的變量名之后緊跟著變量名的構成字符時(比如后跟字母、數字以及下劃線),我們就需要使用特別的記法來消除歧義,例如:
server?{listen???????80;server_name??test.com;location?/?{set?$temp?"hello?";return?"${temp}world";} }這里,我們在配置指令的參數值中引用變量 $temp 的時候,后面緊跟著 world 這個單詞,所以如果直接寫作 "$tempworld" 則 nginx 的計算引擎會將之識別為引用了變量 $tempworld. 為了解決這個問題,nginx 的字符串支持使用花括號在 $ 之后把變量名圍起來,比如這里的 ${temp},所以 上面這個例子返回的還是 "hello world":
$?curl?'http://test.com/'hello?world還需要注意的是,若是想輸出 $ 符號本身,可以這樣做:
geo?$dollar?{default?"$"; } server?{listen???????80;server_name??test.com;location?/?{set?$temp?"hello?";return?"${temp}world:?$dollar";} }上面用到了標準模塊 ngx_geo 提供的配置指令 geo 來為變量 $dollar 賦予字符串 "$" ,這樣,這里的返回值就是 "hello world: $" 了。
附 nginx 內置預定義變量
按字母順序,變量名與對應定義:
$arg_PARAMETER #GET 請求中變量名 PARAMETER 參數的值
$args #這個變量等于 GET 請求中的參數,例如,foo=123&bar=blahblah;這個變量可以被修改
$binary_remote_addr #二進制碼形式的客戶端地址
$body_bytes_sent #傳送頁面的字節數
$content_length #請求頭中的 Content-length 字段
$content_type #請求頭中的 Content-Type 字段
$cookie_COOKIE #cookie COOKIE 的值
$document_root #當前請求在 root 指令中指定的值
$document_uri #與 $uri 相同
$host #請求中的主機頭(Host)字段,如果請求中的主機頭不可用或者空,則為處理請求的 server 名稱(處理請求的 server 的 server_name 指令的值)。值為小寫,不包含端口
$hostname #機器名使用 gethostname 系統調用的值
$http_HEADER #HTTP 請求頭中的內容,HEADER 為 HTTP 請求中的內容轉為小寫,-變為_(破折號變為下劃線),例如:$http_user_agent(Uaer-Agent 的值)
$sent_http_HEADER #HTTP 響應頭中的內容,HEADER 為 HTTP 響應中的內容轉為小寫,-變為_(破折號變為下劃線),例如:$sent_http_cache_control、$sent_http_content_type…
$is_args #如果 $args 設置,值為"?",否則為""
$limit_rate #這個變量可以限制連接速率
$nginx_version #當前運行的 nginx 版本號
$query_string #與 $args 相同
$remote_addr #客戶端的 IP 地址
$remote_port #客戶端的端口
$remote_port #已經經過 Auth Basic Module 驗證的用戶名
$request_filename #當前連接請求的文件路徑,由 root 或 alias 指令與 URI 請求生成
$request_body #這個變量(0.7.58+)包含請求的主要信息。在使用 proxy_pass 或 fastcgi_pass 指令的 location 中比較有意義
$request_body_file #客戶端請求主體信息的臨時文件名
$request_completion #如果請求成功,設為"OK";如果請求未完成或者不是一系列請求中最后一部分則設為空
$request_method #這個變量是客戶端請求的動作,通常為 GET 或 POST。包括 0.8.20 及之前的版本中,這個變量總為 main request 中的動作,如果當前請求是一個子請求,并不使用這個當前請求的動作
$request_uri #這個變量等于包含一些客戶端請求參數的原始 URI,它無法修改,請查看 $uri 更改或重寫 URI
$scheme #所用的協議,例如 http 或者是 https,例如 rewrite ^(.+)$$scheme://example.com$1 redirect
$server_addr #服務器地址,在完成一次系統調用后可以確定這個值,如果要繞開系統調用,則必須在 listen 中指定地址并且使用 bind 參數
$server_name #服務器名稱
$server_port #請求到達服務器的端口號
$server_protocol #請求使用的協議,通常是 HTTP/1.0、HTTP/1.1 或 HTTP/2
$uri #請求中的當前 URI(不帶請求參數,參數位于 args ) , 不 同 于 瀏 覽 器 傳 遞 的 args),不同于瀏覽器傳遞的 args),不同于瀏覽器傳遞的 request_uri 的值,它可以通過內部重定向,或者使用 index 指令進行修改。不包括協議和主機名,例如 /foo/bar.html
附 nginx 模塊
nginx 模塊分類
核心模塊:nginx 最基本最核心的服務,如進程管理、權限控制、日志記錄;
標準 HTTP 模塊:nginx 服務器的標準 HTTP 功能;
可選 HTTP 模塊:處理特殊的 HTTP 請求
郵件服務模塊:郵件服務
第三方模塊:作為擴展,完成特殊功能
模塊清單
核心模塊:
ngx_core
ngx_errlog
ngx_conf
ngx_events
ngx_event_core
ngx_epll
ngx_regex
標準 HTTP 模塊:
ngx_http
ngx_http_core #配置端口,URI 分析,服務器相應錯誤處理,別名控制 (alias) 等
ngx_http_log #自定義 access 日志
ngx_http_upstream #定義一組服務器,可以接受來自 proxy, Fastcgi,Memcache 的重定向;主要用作負載均衡
ngx_http_static
ngx_http_autoindex #自動生成目錄列表
ngx_http_index #處理以/結尾的請求,如果沒有找到 index 頁,則看是否開啟了 random_index;如開啟,則用之,否則用 autoindex
ngx_http_auth_basic #基于 http 的身份認證 (auth_basic)
ngx_http_access #基于 IP 地址的訪問控制 (deny,allow)
ngx_http_limit_conn #限制來自客戶端的連接的響應和處理速率
ngx_http_limit_req #限制來自客戶端的請求的響應和處理速率
ngx_http_geo
ngx_http_map #創建任意的鍵值對變量
ngx_http_split_clients
ngx_http_referer #過濾 HTTP 頭中 Referer 為空的對象
ngx_http_rewrite #通過正則表達式重定向請求
ngx_http_proxy
ngx_http_fastcgi #支持 fastcgi
ngx_http_uwsgi
ngx_http_scgi
ngx_http_memcached
ngx_http_empty_gif #從內存創建一個 1×1 的透明 gif 圖片,可以快速調用
ngx_http_browser #解析 http 請求頭部的 User-Agent 值
ngx_http_charset #指定網頁編碼
ngx_http_upstream_ip_hash
ngx_http_upstream_least_conn
ngx_http_upstream_keepalive
ngx_http_write_filter
ngx_http_header_filter
ngx_http_chunked_filter
ngx_http_range_header
ngx_http_gzip_filter
ngx_http_postpone_filter
ngx_http_ssi_filter
ngx_http_charset_filter
ngx_http_userid_filter
ngx_http_headers_filter #設置 http 響應頭
ngx_http_copy_filter
ngx_http_range_body_filter
ngx_http_not_modified_filter
可選 HTTP 模塊:
ngx_http_addition #在響應請求的頁面開始或者結尾添加文本信息
ngx_http_degradation #在低內存的情況下允許服務器返回 444 或者 204 錯誤
ngx_http_perl
ngx_http_flv #支持將 Flash 多媒體信息按照流文件傳輸,可以根據客戶端指定的開始位置返回 Flash
ngx_http_geoip #支持解析基于 GeoIP 數據庫的客戶端請求
ngx_google_perftools
ngx_http_gzip #gzip 壓縮請求的響應
ngx_http_gzip_static #搜索并使用預壓縮的以.gz 為后綴的文件代替一般文件響應客戶端請求
ngx_http_image_filter #支持改變 png,jpeg,gif 圖片的尺寸和旋轉方向
ngx_http_mp4 #支持.mp4,.m4v,.m4a 等多媒體信息按照流文件傳輸,常與 ngx_http_flv 一起使用
ngx_http_random_index #當收到 / 結尾的請求時,在指定目錄下隨機選擇一個文件作為 index
ngx_http_secure_link #支持對請求鏈接的有效性檢查
ngx_http_ssl #支持 https
ngx_http_stub_status
ngx_http_sub_module #使用指定的字符串替換響應中的信息
ngx_http_dav #支持 HTTP 和 WebDAV 協議中的 PUT/DELETE/MKCOL/COPY/MOVE 方法
ngx_http_xslt #將 XML 響應信息使用 XSLT 進行轉換
郵件服務模塊:
ngx_mail_core
ngx_mail_pop3
ngx_mail_imap
ngx_mail_smtp
ngx_mail_auth_http
ngx_mail_proxy
ngx_mail_ssl
第三方模塊:
echo-nginx-module #支持在 nginx 配置文件中使用 echo/sleep/time/exec 等類 Shell 命令
memc-nginx-module
rds-json-nginx-module #使 nginx 支持 json 數據的處理
lua-nginx-module
視頻號最新視頻
想了解騰訊人的故事,歡迎關注:騰訊技術
總結
以上是生活随笔為你收集整理的Nginx 最全操作总结的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 这篇Redis文章,图灵看了都说好
- 下一篇: 不吹不擂,一文揭秘鸿蒙操作系统