本文將會從:安裝 -> 全局配置 -> 常用的各種配置 來書寫,其中常用配置寫的炒雞詳細,需要的童鞋可以直接滑倒相應的位置查看。
安裝 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
就可以查看
編譯并安裝
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?on
reboot 重啟系統生效,可以使用上面 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/profile
2、在最后一行添加配置,:wq 保存
export?PATH=$PATH:/usr/local/nginx/sbin
3、使配置立即生效
source?/etc/profile
這樣就可以愉快的直接在全局使用 nginx 命令了。
nginx 常用功能
反向代理
我們最常說的反向代理的是通過反向代理解決跨域問題。
其實反向代理還可以用來控制緩存(代理緩存 proxy cache),進行訪問控制等等,以及后面說的負載均衡其實都是通過反向代理來實現的。
server?{
????listen????8080;
????????#?用戶訪問?ip:8080/test?下的所有路徑代理到?github
????????location?/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 配置來分開
#?所有靜態請求都由nginx處理,存放目錄為?html
location?~?\.(gif|jpg|jpeg|png|bmp|swf|css|js)?{
????root????/usr/local/resource;
????expires?????10h;?#?設置過期時間為10小時
}
#?所有動態請求都轉發給?tomcat?處理
location?~?\.(jsp|do)?{
????proxy_pass??127.0.0.1:8888;
}
注意上面設置了 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://hostrequest_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?外鏈引用,將百度和谷歌也加入白名單有利于?SEO
????????if?(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.0
????ssl_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.clubrequest_uri;
????}
????#?全局非?https?協議時重定向
????if?(scheme?!=?'https')?{
????????return?301?https://server_namerequest_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 uriuri/ /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.loc
???smtp_server?127.0.0.1
???smtp_connect_timeout?30?//?上面都是郵件配置
???router_id?LVS_DEVEL?????//?當前服務器名字,用?hostname?命令來查看
}
vrrp_script?chk_maintainace?{?//?檢測機制的腳本名稱為chk_maintainace
????script?"[[?-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,備用機為BACKUP
????interface?eth0????//?網卡名字,可以從ifconfig中查找
????virtual_router_id?51?//?虛擬路由的id號,一般小于255,主備機id需要一樣
????priority?100??????//?優先級,master的優先級比backup的大
????advert_int?1??????//?默認心跳間隔
????authentication?{??//?認證機制
????????auth_type?PASS
????????auth_pass?1111???//?密碼
????}
????virtual_ipaddress?{??//?虛擬地址vip
???????172.16.2.8
????}
}
其中檢測腳本 nginx_check.sh
,這里提供一個:
#!/bin/bash
A=`ps?-C?nginx?--no-header?|?wc?-l`
if?[?$A?-eq?0?];then
????/usr/sbin/nginx?#?嘗試重新啟動nginx
????sleep?2?????????#?睡眠2秒
????if?[?`ps?-C?nginx?--no-header?|?wc?-l`?-eq?0?];then
??????? killall 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、GB
????????autoindex_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 頭信息
ab -n 1000?-c 5000 http://127.0.0.1/?#?每次發送1000并發的請求數,請求數總數為5000。
測試前需要安裝 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 服務器地址;
server?{
????listen???????80;
????server_name??~^([\w-]+)\.doc\.test\.club;
????root?/usr/local/html/doc/1;
}
泛域名轉發
和之前的功能類似,有時候我們希望把二級或者三級域名鏈接重寫到我們希望的路徑,讓后端就可以根據路由解析不同的規則:
- 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
server?{
????listen???????80;
????server_name?~^([\w-]+)\.serv\.test\.club;
????location?/?{
????????proxy_set_header????????X-Real-IP?remote_addr;
????????proxy_set_header????????X-Forwarded-For?proxy_add_x_forwarded_for;
????????proxy_set_header????????Host?http_host;
????????proxy_set_header????????X-NginX-Proxy?true;
????????proxy_pass??????????????http://127.0.0.1:8080/1request_uri;
????}
}
常見問題
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,例如$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
文章轉載:騰訊技術工程
(版權歸原作者所有,侵刪)
本文鏈接:http://m.abandonstatusquo.com/40021.html
網友評論comments