轉(zhuǎn)自前端大全 作者SHERlocked93
最近越來越頻繁地遇到需要配置反向代理的場景暂筝,在自己搭建博客的時候册舞,也不可避免要用到 Nginx恭应,所以這段時間集中學(xué)習(xí)了一下 Nginx并徘,同時做了一些筆記暗赶,希望也可以幫助到大家~ ??
這篇文章會在 CentOS 環(huán)境下安裝和使用 Nginx够委,如果對 CentOS 基本操作還不太清楚的荐类,可以先看看 <半小時搞會 CentOS 入門必備基礎(chǔ)知識> 一文先做了解。
相信作為開發(fā)者茁帽,大家都知道 Nginx 的重要玉罐,廢話不多說,一起來學(xué)習(xí)吧潘拨。
CentOS 版本:7.6
Nginx 版本:1.16.1
1. Nginx 介紹
傳統(tǒng)的 Web 服務(wù)器吊输,每個客戶端連接作為一個單獨(dú)的進(jìn)程或線程處理,需在切換任務(wù)時將 CPU 切換到新的任務(wù)并創(chuàng)建一個新的運(yùn)行時上下文铁追,消耗額外的內(nèi)存和 CPU 時間季蚂,當(dāng)并發(fā)請求增加時,服務(wù)器響應(yīng)變慢琅束,從而對性能產(chǎn)生負(fù)面影響扭屁。
<figcaption style="margin: 5px 0px 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; text-align: center; color: rgb(136, 136, 136); font-size: 14px;">Nginx</figcaption>
Nginx 是開源、高性能涩禀、高可靠的 Web 和反向代理服務(wù)器料滥,而且支持熱部署,幾乎可以做到 7 * 24 小時不間斷運(yùn)行埋泵,即使運(yùn)行幾個月也不需要重新啟動幔欧,還能在不間斷服務(wù)的情況下對軟件版本進(jìn)行熱更新罪治。性能是 Nginx 最重要的考量,其占用內(nèi)存少礁蔗、并發(fā)能力強(qiáng)觉义、能支持高達(dá) 5w 個并發(fā)連接數(shù),最重要的是浴井,Nginx 是免費(fèi)的并可以商業(yè)化晒骇,配置使用也比較簡單。
Nginx 的最重要的幾個使用場景:
- 靜態(tài)資源服務(wù)磺浙,通過本地文件系統(tǒng)提供服務(wù)洪囤;
- 反向代理服務(wù),延伸出包括緩存撕氧、負(fù)載均衡等瘤缩;
- API 服務(wù),OpenResty 伦泥;
對于前端來說 Node.js 不陌生了剥啤,Nginx 和 Node.js 的很多理念類似,HTTP 服務(wù)器不脯、事件驅(qū)動府怯、異步非阻塞等,且 Nginx 的大部分功能使用 Node.js 也可以實現(xiàn)防楷,但 Nginx 和 Node.js 并不沖突牺丙,都有自己擅長的領(lǐng)域。Nginx 擅長于底層服務(wù)器端資源的處理(靜態(tài)資源處理轉(zhuǎn)發(fā)复局、反向代理冲簿,負(fù)載均衡等),Node.js 更擅長上層具體業(yè)務(wù)邏輯的處理肖揣,兩者可以完美組合民假,共同助力前端開發(fā)。
下面我們著重學(xué)習(xí)一下 Nginx 的使用龙优。
2. 相關(guān)概念
2.1 簡單請求和非簡單請求
首先我們來了解一下簡單請求和非簡單請求,如果同時滿足下面兩個條件事秀,就屬于簡單請求:
- 請求方法是
HEAD
彤断、GET
、POST
三種之一易迹; - HTTP 頭信息不超過右邊著幾個字段:
Accept
宰衙、Accept-Language
、Content-Language
睹欲、Last-Event-ID``Content-Type
只限于三個值application/x-www-form-urlencoded
供炼、multipart/form-data
一屋、text/plain
;
凡是不同時滿足這兩個條件的袋哼,都屬于非簡單請求冀墨。
瀏覽器處理簡單請求和非簡單請求的方式不一樣:
簡單請求
對于簡單請求,瀏覽器會在頭信息中增加 Origin
字段后直接發(fā)出涛贯,Origin
字段用來說明诽嘉,本次請求來自的哪個源(協(xié)議+域名+端口)。
如果服務(wù)器發(fā)現(xiàn) Origin
指定的源不在許可范圍內(nèi)弟翘,服務(wù)器會返回一個正常的 HTTP 回應(yīng)虫腋,瀏覽器取到回應(yīng)之后發(fā)現(xiàn)回應(yīng)的頭信息中沒有包含 Access-Control-Allow-Origin
字段,就拋出一個錯誤給 XHR 的 error
事件稀余;
如果服務(wù)器發(fā)現(xiàn) Origin
指定的域名在許可范圍內(nèi)悦冀,服務(wù)器返回的響應(yīng)會多出幾個 Access-Control-
開頭的頭信息字段。
非簡單請求
非簡單請求是那種對服務(wù)器有特殊要求的請求睛琳,比如請求方法是 PUT
或 DELETE
盒蟆,或 Content-Type
值為 application/json
。瀏覽器會在正式通信之前掸掏,發(fā)送一次 HTTP 預(yù)檢 OPTIONS
請求茁影,先詢問服務(wù)器,當(dāng)前網(wǎng)頁所在的域名是否在服務(wù)器的許可名單之中丧凤,以及可以使用哪些 HTTP 請求方法和頭信息字段募闲。只有得到肯定答復(fù),瀏覽器才會發(fā)出正式的 XHR
請求愿待,否則報錯浩螺。
2.2 跨域
在瀏覽器上當(dāng)前訪問的網(wǎng)站向另一個網(wǎng)站發(fā)送請求獲取數(shù)據(jù)的過程就是跨域請求。
跨域是瀏覽器的同源策略決定的仍侥,是一個重要的瀏覽器安全策略要出,用于限制一個 origin 的文檔或者它加載的腳本與另一個源的資源進(jìn)行交互,它能夠幫助阻隔惡意文檔农渊,減少可能被攻擊的媒介患蹂,可以使用 CORS 配置解除這個限制。
關(guān)于跨域網(wǎng)上已經(jīng)有很多解釋砸紊,這里就不啰嗦传于,也可以直接看 MDN 的 <瀏覽器的同源策略> 文檔進(jìn)一步了解,這里就列舉幾個同源和不同元的例子醉顽,相信程序員都能看得懂沼溜。
# 同源的例子http://example.com/app1/index.html # 只是路徑不同http://example.com/app2/index.htmlhttp://Example.com:80 # 只是大小寫差異http://example.com# 不同源的例子http://example.com/app1 # 協(xié)議不同https://example.com/app2http://example.com # host 不同http://www.example.comhttp://myapp.example.comhttp://example.com # 端口不同http://example.com:8080
2.3 正向代理和反向代理
反向代理(Reverse Proxy)對應(yīng)的是正向代理(Forward Proxy),他們的區(qū)別:
正向代理: 一般的訪問流程是客戶端直接向目標(biāo)服務(wù)器發(fā)送請求并獲取內(nèi)容,使用正向代理后镇防,客戶端改為向代理服務(wù)器發(fā)送請求豆茫,并指定目標(biāo)服務(wù)器(原始服務(wù)器)涂乌,然后由代理服務(wù)器和原始服務(wù)器通信会傲,轉(zhuǎn)交請求并獲得的內(nèi)容序矩,再返回給客戶端酥夭。正向代理隱藏了真實的客戶端轻黑,為客戶端收發(fā)請求檐嚣,使真實客戶端對服務(wù)器不可見助泽;
舉個具體的例子 ??,你的瀏覽器無法直接訪問谷哥嚎京,這時候可以通過一個代理服務(wù)器來幫助你訪問谷哥嗡贺,那么這個服務(wù)器就叫正向代理。
反向代理: 與一般訪問流程相比鞍帝,使用反向代理后诫睬,直接收到請求的服務(wù)器是代理服務(wù)器,然后將請求轉(zhuǎn)發(fā)給內(nèi)部網(wǎng)絡(luò)上真正進(jìn)行處理的服務(wù)器帕涌,得到的結(jié)果返回給客戶端摄凡。反向代理隱藏了真實的服務(wù)器,為服務(wù)器收發(fā)請求蚓曼,使真實服務(wù)器對客戶端不可見亲澡。一般在處理跨域請求的時候比較常用。現(xiàn)在基本上所有的大型網(wǎng)站都設(shè)置了反向代理纫版。
舉個具體的例子 ??床绪,去飯店吃飯,可以點(diǎn)川菜其弊、粵菜癞己、江浙菜,飯店也分別有三個菜系的廚師 ?????梭伐,但是你作為顧客不用管哪個廚師給你做的菜痹雅,只用點(diǎn)菜即可,小二將你菜單中的菜分配給不同的廚師來具體處理糊识,那么這個小二就是反向代理服務(wù)器绩社。
簡單的說,一般給客戶端做代理的都是正向代理赂苗,給服務(wù)器做代理的就是反向代理铃将。
正向代理和反向代理主要的原理區(qū)別可以參見下圖:
2.4 負(fù)載均衡
一般情況下,客戶端發(fā)送多個請求到服務(wù)器哑梳,服務(wù)器處理請求,其中一部分可能要操作一些資源比如數(shù)據(jù)庫绘盟、靜態(tài)資源等鸠真,服務(wù)器處理完畢后悯仙,再將結(jié)果返回給客戶端。
這種模式對于早期的系統(tǒng)來說吠卷,功能要求不復(fù)雜锡垄,且并發(fā)請求相對較少的情況下還能勝任,成本也低祭隔。隨著信息數(shù)量不斷增長货岭,訪問量和數(shù)據(jù)量飛速增長,以及系統(tǒng)業(yè)務(wù)復(fù)雜度持續(xù)增加疾渴,這種做法已無法滿足要求千贯,并發(fā)量特別大時,服務(wù)器容易崩搞坝。
很明顯這是由于服務(wù)器性能的瓶頸造成的問題搔谴,除了堆機(jī)器之外,最重要的做法就是負(fù)載均衡桩撮。
請求爆發(fā)式增長的情況下敦第,單個機(jī)器性能再強(qiáng)勁也無法滿足要求了,這個時候集群的概念產(chǎn)生了店量,單個服務(wù)器解決不了的問題芜果,可以使用多個服務(wù)器,然后將請求分發(fā)到各個服務(wù)器上融师,將負(fù)載分發(fā)到不同的服務(wù)器右钾,這就是負(fù)載均衡,核心是「分?jǐn)倝毫Α刮芴病ginx 實現(xiàn)負(fù)載均衡霹粥,一般來說指的是將請求轉(zhuǎn)發(fā)給服務(wù)器集群。
舉個具體的例子 ??疼鸟,晚高峰乘坐地鐵的時候后控,入站口經(jīng)常會有地鐵工作人員大喇叭“請走 B 口,B 口人少車空....”空镜,這個工作人員的作用就是負(fù)載均衡浩淘。
<figcaption style="margin: 5px 0px 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; text-align: center; color: rgb(136, 136, 136); font-size: 14px;">負(fù)載均衡</figcaption>
2.5 動靜分離
為了加快網(wǎng)站的解析速度,可以把動態(tài)頁面和靜態(tài)頁面由不同的服務(wù)器來解析吴攒,加快解析速度张抄,降低原來單個服務(wù)器的壓力。
<figcaption style="margin: 5px 0px 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; text-align: center; color: rgb(136, 136, 136); font-size: 14px;">動靜分離</figcaption>
一般來說洼怔,都需要將動態(tài)資源和靜態(tài)資源分開署惯,由于 Nginx 的高并發(fā)和靜態(tài)資源緩存等特性,經(jīng)常將靜態(tài)資源部署在 Nginx 上镣隶。如果請求的是靜態(tài)資源极谊,直接到靜態(tài)資源目錄獲取資源诡右,如果是動態(tài)資源的請求,則利用反向代理的原理轻猖,把請求轉(zhuǎn)發(fā)給對應(yīng)后臺應(yīng)用去處理帆吻,從而實現(xiàn)動靜分離。
使用前后端分離后咙边,可以很大程度提升靜態(tài)資源的訪問速度猜煮,即使動態(tài)服務(wù)不可用,靜態(tài)資源的訪問也不會受到影響败许。
3. Nginx 快速安裝
3.1 安裝
我們可以先看看
yum list | grep nginx
來看看
<figcaption style="margin: 5px 0px 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; text-align: center; color: rgb(136, 136, 136); font-size: 14px;">image-20200307180412726</figcaption>
然后
yum install nginx
來安裝 Nginx王带,然后我們在命令行中 nginx -v
就可以看到具體的 Nginx 版本信息,也就安裝完畢了檐束。
<figcaption style="margin: 5px 0px 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; text-align: center; color: rgb(136, 136, 136); font-size: 14px;">image-20200307180545816</figcaption>
3.2 相關(guān)文件夾
然后我們可以使用 rpm -ql nginx
來查看 Nginx 被安裝到了什么地方辫秧,有哪些相關(guān)目錄,其中位于 /etc
目錄下的主要是配置文件被丧,還有一些文件見下圖:
<figcaption style="margin: 5px 0px 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; text-align: center; color: rgb(136, 136, 136); font-size: 14px;">Xnip2020-03-07_21-46-11</figcaption>
主要關(guān)注的文件夾有兩個:
-
/etc/nginx/conf.d/
文件夾盟戏,是我們進(jìn)行子配置的配置項存放處,/etc/nginx/nginx.conf
主配置文件會默認(rèn)把這個文件夾中所有子配置項都引入甥桂; -
/usr/share/nginx/html/
文件夾柿究,通常靜態(tài)文件都放在這個文件夾,也可以根據(jù)你自己的習(xí)慣放其他地方黄选;
3.3 跑起來康康
安裝之后開啟 Nginx,如果系統(tǒng)開啟了防火墻办陷,那么需要設(shè)置一下在防火墻中加入需要開放的端口貌夕,下面列舉幾個常用的防火墻操作(沒開啟的話不用管這個):
systemctl start firewalld # 開啟防火墻systemctl stop firewalld # 關(guān)閉防火墻systemctl status firewalld # 查看防火墻開啟狀態(tài),顯示running則是正在運(yùn)行firewall-cmd --reload # 重啟防火墻民镜,永久打開端口需要reload一下# 添加開啟端口啡专,--permanent表示永久打開,不加是臨時打開重啟之后失效firewall-cmd --permanent --zone=public --add-port=8888/tcp# 查看防火墻制圈,添加的端口也可以看到firewall-cmd --list-all
然后設(shè)置 Nginx 的開機(jī)啟動:
systemctl enable nginx
啟動 Nginx (其他命令后面有詳細(xì)講解):
systemctl start nginx
然后訪問你的 IP们童,這時候就可以看到 Nginx 的歡迎頁面了~ Welcome to nginx!
??
3.4 安裝 nvm & node & git
# 下載 nvm鲸鹦,或者看官網(wǎng)的步驟 https://github.com/nvm-sh/nvm#install--update-scriptcurl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.3/install.sh | bashsource ~/.bashrc # 安裝完畢后慧库,更新配置文件即可使用 nvm 命令nvm ls-remote # 查看遠(yuǎn)程 node 版本nvm install v12.16.3 # 選一個你要安裝的版本安裝,我這里選擇 12.16.3nvm list # 安裝完畢查看安裝的 node 版本node -v # 查看是否安裝好了yum install git # git 安裝
4. Nginx 操作常用命令
Nginx 的命令在控制臺中輸入 nginx -h
就可以看到完整的命令馋嗜,這里列舉幾個常用的命令:
nginx -s reload # 向主進(jìn)程發(fā)送信號齐板,重新加載配置文件,熱重啟nginx -s reopen # 重啟 Nginxnginx -s stop # 快速關(guān)閉nginx -s quit # 等待工作進(jìn)程處理完成后關(guān)閉nginx -T # 查看當(dāng)前 Nginx 最終的配置nginx -t -c <配置路徑> # 檢查配置是否有問題,如果已經(jīng)在配置目錄覆积,則不需要-c
systemctl
是 Linux 系統(tǒng)應(yīng)用管理工具 systemd
的主命令听皿,用于管理系統(tǒng),我們也可以用它來對 Nginx 進(jìn)行管理宽档,相關(guān)命令如下:
systemctl start nginx # 啟動 Nginxsystemctl stop nginx # 停止 Nginxsystemctl restart nginx # 重啟 Nginxsystemctl reload nginx # 重新加載 Nginx,用于修改配置后systemctl enable nginx # 設(shè)置開機(jī)啟動 Nginxsystemctl disable nginx # 關(guān)閉開機(jī)啟動 Nginxsystemctl status nginx # 查看 Nginx 運(yùn)行狀態(tài)
5. Nginx 配置語法
就跟前面文件作用講解的圖所示庵朝,Nginx 的主配置文件是 /etc/nginx/nginx.conf
吗冤,你可以使用 cat -n nginx.conf
來查看配置。
nginx.conf
結(jié)構(gòu)圖可以這樣概括:
main # 全局配置九府,對全局生效├── events # 配置影響 Nginx 服務(wù)器或與用戶的網(wǎng)絡(luò)連接├── http # 配置代理椎瘟,緩存,日志定義等絕大多數(shù)功能和第三方模塊的配置│ ├── upstream # 配置后端服務(wù)器具體地址侄旬,負(fù)載均衡配置不可或缺的部分│ ├── server # 配置虛擬主機(jī)的相關(guān)參數(shù)肺蔚,一個 http 塊中可以有多個 server 塊│ ├── server│ │ ├── location # server 塊可以包含多個 location 塊,location 指令用于匹配 uri│ │ ├── location│ │ └── ...│ └── ...└── ...
一個 Nginx 配置文件的結(jié)構(gòu)就像 nginx.conf
顯示的那樣儡羔,配置文件的語法規(guī)則:
- 配置文件由指令與指令塊構(gòu)成宣羊;
- 每條指令以
;
分號結(jié)尾,指令與參數(shù)間以空格符號分隔汰蜘; - 指令塊以
{}
大括號將多條指令組織在一起仇冯; -
include
語句允許組合多個配置文件以提升可維護(hù)性; - 使用
#
符號添加注釋族操,提高可讀性苛坚; - 使用
$
符號使用變量; - 部分指令的參數(shù)支持正則表達(dá)式色难;
5.1 典型配置
Nginx 的典型配置:
user nginx; # 運(yùn)行用戶泼舱,默認(rèn)即是nginx,可以不進(jìn)行設(shè)置worker_processes 1; # Nginx 進(jìn)程數(shù)枷莉,一般設(shè)置為和 CPU 核數(shù)一樣error_log /var/log/nginx/error.log warn; # Nginx 的錯誤日志存放目錄pid /var/run/nginx.pid; # Nginx 服務(wù)啟動時的 pid 存放位置events { use epoll; # 使用epoll的I/O模型(如果你不知道Nginx該使用哪種輪詢方法娇昙,會自動選擇一個最適合你操作系統(tǒng)的) worker_connections 1024; # 每個進(jìn)程允許最大并發(fā)數(shù)}http { # 配置使用最頻繁的部分,代理依沮、緩存涯贞、日志定義等絕大多數(shù)功能和第三方模塊的配置都在這里設(shè)置 # 設(shè)置日志模式 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 /var/log/nginx/access.log main; # Nginx訪問日志存放位置 sendfile on; # 開啟高效傳輸模式 tcp_nopush on; # 減少網(wǎng)絡(luò)報文段的數(shù)量 tcp_nodelay on; keepalive_timeout 65; # 保持連接的時間,也叫超時時間危喉,單位秒 types_hash_max_size 2048; include /etc/nginx/mime.types; # 文件擴(kuò)展名與類型映射表 default_type application/octet-stream; # 默認(rèn)文件類型 include /etc/nginx/conf.d/*.conf; # 加載子配置項 server { listen 80; # 配置監(jiān)聽的端口 server_name localhost; # 配置的域名 location / { root /usr/share/nginx/html; # 網(wǎng)站根目錄 index index.html index.htm; # 默認(rèn)首頁文件 deny 172.168.22.11; # 禁止訪問的ip地址宋渔,可以為all allow 172.168.33.44;# 允許訪問的ip地址辜限,可以為all } error_page 500 502 503 504 /50x.html; # 默認(rèn)50x對應(yīng)的訪問頁面 error_page 400 404 error.html; # 同上 }}
server 塊可以包含多個 location 塊皇拣,location 指令用于匹配 uri,語法:
location [ = | ~ | ~* | ^~] uri { ...}
指令后面:
-
=
精確匹配路徑,用于不含正則表達(dá)式的 uri 前氧急,如果匹配成功颗胡,不再進(jìn)行后續(xù)的查找; -
^~
用于不含正則表達(dá)式的 uri 前吩坝,表示如果該符號后面的字符是最佳匹配毒姨,采用該規(guī)則,不再進(jìn)行后續(xù)的查找钉寝; -
~
表示用該符號后面的正則去匹配路徑弧呐,區(qū)分大小寫; -
~*
表示用該符號后面的正則去匹配路徑嵌纲,不區(qū)分大小寫俘枫。跟~
優(yōu)先級都比較低,如有多個location的正則能匹配的話逮走,則使用正則表達(dá)式最長的那個鸠蚪;
如果 uri 包含正則表達(dá)式,則必須要有 ~
或 ~*
標(biāo)志师溅。
5.2 全局變量
Nginx 有一些常用的全局變量茅信,你可以在配置的任何位置使用它們,如下表:
全局變量名 | 功能 |
---|---|
$host |
請求信息中的 Host 险胰,如果請求中沒有 Host 行汹押,則等于設(shè)置的服務(wù)器名,不包含端口 |
$request_method |
客戶端請求類型起便,如 GET 棚贾、POST
|
$remote_addr |
客戶端的 IP 地址 |
$args |
請求中的參數(shù) |
$arg_PARAMETER |
GET 請求中變量名 PARAMETER 參數(shù)的值,例如:$http_user_agent (Uaer-Agent 值), $http_referer ... |
$content_length |
請求頭中的 Content-length 字段 |
$http_user_agent |
客戶端agent信息 |
$http_cookie |
客戶端cookie信息 |
$remote_addr |
客戶端的IP地址 |
$remote_port |
客戶端的端口 |
$http_user_agent |
客戶端agent信息 |
$server_protocol |
請求使用的協(xié)議榆综,如 HTTP/1.0 妙痹、HTTP/1.1
|
$server_addr |
服務(wù)器地址 |
$server_name |
服務(wù)器名稱 |
$server_port |
服務(wù)器的端口號 |
$scheme |
HTTP 方法(如http,https) |
還有更多的內(nèi)置預(yù)定義變量鼻疮,可以直接搜索關(guān)鍵字「nginx內(nèi)置預(yù)定義變量」可以看到一堆博客寫這個怯伊,這些變量都可以在配置文件中直接使用。
6. 設(shè)置二級域名虛擬主機(jī)
在某某云 ?? 上購買了域名之后判沟,就可以配置虛擬主機(jī)了耿芹,一般配置的路徑在 域名管理 -> 解析 -> 添加記錄
中添加二級域名,配置后某某云會把二級域名也解析到我們配置的服務(wù)器 IP 上挪哄,然后我們在 Nginx 上配置一下虛擬主機(jī)的訪問監(jiān)聽吧秕,就可以拿到從這個二級域名過來的請求了。
<figcaption style="margin: 5px 0px 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; text-align: center; color: rgb(136, 136, 136); font-size: 14px;">image-20200426150644768</figcaption>
現(xiàn)在我自己的服務(wù)器上配置了一個 fe 的二級域名迹炼,也就是說在外網(wǎng)訪問 fe.sherlocked93.club
的時候砸彬,也可以訪問到我們的服務(wù)器了颠毙。
由于默認(rèn)配置文件 /etc/nginx/nginx.conf
的 http 模塊中有一句 include /etc/nginx/conf.d/*.conf
也就是說 conf.d
文件夾下的所有 *.conf
文件都會作為子配置項被引入配置文件中。為了維護(hù)方便砂碉,我在 /etc/nginx/conf.d
文件夾中新建一個 fe.sherlocked93.club.conf
:
# /etc/nginx/conf.d/fe.sherlocked93.club.confserver { listen 80; server_name fe.sherlocked93.club; location / { root /usr/share/nginx/html/fe; index index.html; }}
然后在 /usr/share/nginx/html
文件夾下新建 fe 文件夾蛀蜜,新建文件 index.html
,內(nèi)容隨便寫點(diǎn)增蹭,改完 nginx -s reload
重新加載滴某,瀏覽器中輸入 fe.sherlocked93.club
,發(fā)現(xiàn)從二級域名就可以訪問到我們剛剛新建的 fe 文件夾:
7. 配置反向代理
反向代理是工作中最常用的服務(wù)器功能沪铭,經(jīng)常被用來解決跨域問題园欣,下面簡單介紹一下如何實現(xiàn)反向代理岖瑰。
首先進(jìn)入 Nginx 的主配置文件:
vim /etc/nginx/nginx.conf
為了看起來方便,把行號顯示出來 :set nu
(個人習(xí)慣)腕唧,然后我們?nèi)?http
模塊的 server
塊中的 location /
厅克,增加一行將默認(rèn)網(wǎng)址重定向到最大學(xué)習(xí)網(wǎng)站 Bilibili 的 proxy_pass
配置 ?? :
改完保存退出赔退,nginx -s reload
重新加載,進(jìn)入默認(rèn)網(wǎng)址证舟,那么現(xiàn)在就直接跳轉(zhuǎn)到 B 站了硕旗,實現(xiàn)了一個簡單的代理。
實際使用中女责,可以將請求轉(zhuǎn)發(fā)到本機(jī)另一個服務(wù)器上漆枚,也可以根據(jù)訪問的路徑跳轉(zhuǎn)到不同端口的服務(wù)中。
比如我們監(jiān)聽 9001
端口抵知,然后把訪問不同路徑的請求進(jìn)行反向代理:
- 把訪問
http://127.0.0.1:9001/edu
的請求轉(zhuǎn)發(fā)到http://127.0.0.1:8080
- 把訪問
http://127.0.0.1:9001/vod
的請求轉(zhuǎn)發(fā)到http://127.0.0.1:8081
這種要怎么配置呢墙基,首先同樣打開主配置文件,然后在 http 模塊下增加一個 server 塊:
server { listen 9001; server_name *.sherlocked93.club; location ~ /edu/ { proxy_pass http://127.0.0.1:8080; } location ~ /vod/ { proxy_pass http://127.0.0.1:8081; }}
反向代理還有一些其他的指令刷喜,可以了解一下:
-
proxy_set_header
:在將客戶端請求發(fā)送給后端服務(wù)器之前残制,更改來自客戶端的請求頭信息; -
proxy_connect_timeout
:配置 Nginx 與后端代理服務(wù)器嘗試建立連接的超時時間掖疮; -
proxy_read_timeout
:配置 Nginx 向后端服務(wù)器組發(fā)出 read 請求后初茶,等待相應(yīng)的超時時間; -
proxy_send_timeout
:配置 Nginx 向后端服務(wù)器組發(fā)出 write 請求后浊闪,等待相應(yīng)的超時時間恼布; -
proxy_redirect
:用于修改后端服務(wù)器返回的響應(yīng)頭中的 Location 和 Refresh。
8. 跨域 CORS 配置
關(guān)于簡單請求搁宾、非簡單請求折汞、跨域的概念,前面已經(jīng)介紹過了猛铅,還不了解的可以看看前面的講解∽种В現(xiàn)在前后端分離的項目一統(tǒng)天下,經(jīng)常本地起了前端服務(wù),需要訪問不同的后端地址堕伪,不可避免遇到跨域問題揖庄。
要解決跨域問題,我們來制造一個跨域問題欠雌。首先和前面設(shè)置二級域名的方式一樣蹄梢,先設(shè)置好 fe.sherlocked93.club
和 be.sherlocked93.club
二級域名,都指向本云服務(wù)器地址富俄,雖然對應(yīng) IP 是一樣的禁炒,但是在 fe.sherlocked93.club
域名發(fā)出的請求訪問 be.sherlocked93.club
域名的請求還是跨域了,因為訪問的 host 不一致(如果不知道啥原因參見前面跨域的內(nèi)容)霍比。
8.1 使用反向代理解決跨域
在前端服務(wù)地址為 fe.sherlocked93.club
的頁面請求 be.sherlocked93.club
的后端服務(wù)導(dǎo)致的跨域幕袱,可以這樣配置:
server { listen 9001; server_name fe.sherlocked93.club; location / { proxy_pass be.sherlocked93.club; }}
這樣就將對前一個域名 fe.sherlocked93.club
的請求全都代理到了 be.sherlocked93.club
,前端的請求都被我們用服務(wù)器代理到了后端地址下悠瞬,繞過了跨域们豌。
這里對靜態(tài)文件的請求和后端服務(wù)的請求都以 fe.sherlocked93.club
開始,不易區(qū)分浅妆,所以為了實現(xiàn)對后端服務(wù)請求的統(tǒng)一轉(zhuǎn)發(fā)望迎,通常我們會約定對后端服務(wù)的請求加上 /apis/
前綴或者其他的 path 來和對靜態(tài)資源的請求加以區(qū)分,此時我們可以這樣配置:
# 請求跨域凌外,約定代理后端服務(wù)請求path以/apis/開頭location ^~/apis/ { # 這里重寫了請求辩尊,將正則匹配中的第一個分組的path拼接到真正的請求后面,并用break停止后續(xù)匹配 rewrite ^/apis/(.*)$ /$1break; proxy_pass be.sherlocked93.club; # 兩個域名之間cookie的傳遞與回寫 proxy_cookie_domain be.sherlocked93.club fe.sherlocked93.club;}
這樣康辑,靜態(tài)資源我們使用 fe.sherlocked93.club/xx.html
摄欲,動態(tài)資源我們使用 fe.sherlocked93.club/apis/getAwo
,瀏覽器頁面看起來仍然訪問的前端服務(wù)器晾捏,繞過了瀏覽器的同源策略蒿涎,畢竟我們看起來并沒有跨域。
也可以統(tǒng)一一點(diǎn)惦辛,直接把前后端服務(wù)器地址直接都轉(zhuǎn)發(fā)到另一個 server.sherlocked93.club
劳秋,只通過在后面添加的 path 來區(qū)分請求的是靜態(tài)資源還是后端服務(wù),看需求了胖齐。
8.2 配置 header 解決跨域
當(dāng)瀏覽器在訪問跨源的服務(wù)器時玻淑,也可以在跨域的服務(wù)器上直接設(shè)置 Nginx,從而前端就可以無感地開發(fā)呀伙,不用把實際上訪問后端的地址改成前端服務(wù)的地址补履,這樣可適性更高。
比如前端站點(diǎn)是 fe.sherlocked93.club
剿另,這個地址下的前端頁面請求 be.sherlocked93.club
下的資源箫锤,比如前者的 fe.sherlocked93.club/index.html
內(nèi)容是這樣的:
<html><body> <h1>welcome fe.sherlocked93.club!!<h1> <script type='text/javascript'> var xmlhttp = new XMLHttpRequest() xmlhttp.open("GET", "http://be.sherlocked93.club/index.html", true); xmlhttp.send(); </script></body></html>
打開瀏覽器訪問 fe.sherlocked93.club/index.html
的結(jié)果如下:
很明顯這里是跨域請求贬蛙,在瀏覽器中直接訪問 http://be.sherlocked93.club/index.html
是可以訪問到的,但是在 fe.sherlocked93.club
的 html 頁面訪問就會出現(xiàn)跨域谚攒。
在 /etc/nginx/conf.d/
文件夾中新建一個配置文件阳准,對應(yīng)二級域名 be.sherlocked93.club
:
# /etc/nginx/conf.d/be.sherlocked93.club.confserver { listen 80; server_name be.sherlocked93.club; add_header 'Access-Control-Allow-Origin'$http_origin; # 全局變量獲得當(dāng)前請求origin,帶cookie的請求不支持* add_header 'Access-Control-Allow-Credentials''true'; # 為 true 可帶上 cookie add_header 'Access-Control-Allow-Methods''GET, POST, OPTIONS'; # 允許請求方法 add_header 'Access-Control-Allow-Headers'$http_access_control_request_headers; # 允許請求的 header馏臭,可以為 * add_header 'Access-Control-Expose-Headers''Content-Length,Content-Range'; if ($request_method = 'OPTIONS') { add_header 'Access-Control-Max-Age' 1728000; # OPTIONS 請求的有效期野蝇,在有效期內(nèi)不用發(fā)出另一條預(yù)檢請求 add_header 'Content-Type''text/plain; charset=utf-8'; add_header 'Content-Length' 0; return 204; # 200 也可以 } location / { root /usr/share/nginx/html/be; index index.html; }}
然后 nginx -s reload
重新加載配置。這時再訪問 fe.sherlocked93.club/index.html
結(jié)果如下括儒,請求中出現(xiàn)了我們剛剛配置的 Header:
解決了跨域問題绕沈。
9. 開啟 gzip 壓縮
gzip 是一種常用的網(wǎng)頁壓縮技術(shù),傳輸?shù)木W(wǎng)頁經(jīng)過 gzip 壓縮之后大小通嘲镅埃可以變?yōu)樵瓉淼囊话肷踔粮乍狐。ü倬W(wǎng)原話),更小的網(wǎng)頁體積也就意味著帶寬的節(jié)約和傳輸速度的提升固逗,特別是對于訪問量巨大大型網(wǎng)站來說澜躺,每一個靜態(tài)資源體積的減小,都會帶來可觀的流量與帶寬的節(jié)省抒蚜。
百度可以找到很多檢測站點(diǎn)來查看目標(biāo)網(wǎng)頁有沒有開啟 gzip 壓縮,在下隨便找了一個 <網(wǎng)頁GZIP壓縮檢測> 輸入掘金 juejin.im
來偷窺下掘金有沒有開啟 gzip耘戚。
這里可以看到掘金是開啟了 gzip 的嗡髓,壓縮效果還挺不錯,達(dá)到了 52% 之多收津,本來 34kb
的網(wǎng)頁體積饿这,壓縮完只需要 16kb
,可以想象網(wǎng)頁傳輸速度提升了不少撞秋。
9.1 Nginx 配置 gzip
使用 gzip 不僅需要 Nginx 配置长捧,瀏覽器端也需要配合,需要在請求消息頭中包含 Accept-Encoding: gzip
(IE5 之后所有的瀏覽器都支持了吻贿,是現(xiàn)代瀏覽器的默認(rèn)設(shè)置)串结。一般在請求 html 和 css 等靜態(tài)資源的時候,支持的瀏覽器在 request 請求靜態(tài)資源的時候舅列,會加上 Accept-Encoding: gzip
這個 header肌割,表示自己支持 gzip 的壓縮方式,Nginx 在拿到這個請求的時候帐要,如果有相應(yīng)配置把敞,就會返回經(jīng)過 gzip 壓縮過的文件給瀏覽器,并在 response 相應(yīng)的時候加上 content-encoding: gzip
來告訴瀏覽器自己采用的壓縮方式(因為瀏覽器在傳給服務(wù)器的時候一般還告訴服務(wù)器自己支持好幾種壓縮方式)榨惠,瀏覽器拿到壓縮的文件后奋早,根據(jù)自己的解壓方式進(jìn)行解析盛霎。
先來看看 Nginx 怎么進(jìn)行 gzip 配置,和之前的配置一樣耽装,為了方便管理愤炸,還是在 /etc/nginx/conf.d/
文件夾中新建配置文件 gzip.conf
:
# /etc/nginx/conf.d/gzip.confgzip on; # 默認(rèn)off,是否開啟gzipgzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;# 上面兩個開啟基本就能跑起了剂邮,下面的愿意折騰就了解一下gzip_static on;gzip_proxied any;gzip_vary on;gzip_comp_level 6;gzip_buffers 16 8k;# gzip_min_length 1k;gzip_http_version 1.1;
稍微解釋一下:
- gzip_types:要采用 gzip 壓縮的 MIME 文件類型摇幻,其中 text/html 被系統(tǒng)強(qiáng)制啟用;
-
gzip_static:默認(rèn) off挥萌,該模塊啟用后绰姻,Nginx 首先檢查是否存在請求靜態(tài)文件的 gz 結(jié)尾的文件,如果有則直接返回該
.gz
文件內(nèi)容引瀑; - gzip_proxied:默認(rèn) off狂芋,nginx做為反向代理時啟用,用于設(shè)置啟用或禁用從代理服務(wù)器上收到相應(yīng)內(nèi)容 gzip 壓縮憨栽;
-
gzip_vary:用于在響應(yīng)消息頭中添加
Vary:Accept-Encoding
帜矾,使代理服務(wù)器根據(jù)請求頭中的Accept-Encoding
識別是否啟用 gzip 壓縮; - gzip_comp_level:gzip 壓縮比屑柔,壓縮級別是 1-9屡萤,1 壓縮級別最低,9 最高掸宛,級別越高壓縮率越大死陆,壓縮時間越長,建議 4-6唧瘾;
- gzip_buffers:獲取多少內(nèi)存用于緩存壓縮結(jié)果措译,16 8k 表示以 8k*16 為單位獲得;
-
gzip_min_length:允許壓縮的頁面最小字節(jié)數(shù)饰序,頁面字節(jié)數(shù)從header頭中的
Content-Length
中進(jìn)行獲取领虹。默認(rèn)值是 0,不管頁面多大都壓縮求豫。建議設(shè)置成大于 1k 的字節(jié)數(shù)塌衰,小于 1k 可能會越壓越大; - gzip_http_version:默認(rèn) 1.1注祖,啟用 gzip 所需的 HTTP 最低版本猾蒂;
這個配置可以插入到 http 模塊整個服務(wù)器的配置里,也可以插入到需要使用的虛擬主機(jī)的 server
或者下面的 location
模塊中是晨,當(dāng)然像上面我們這樣寫的話就是被 include 到 http 模塊中了肚菠。
其他更全的配置信息可以查看 <官網(wǎng)文檔ngx_http_gzip_module>,配置前是這樣的:
配置之后 response 的 header 里面多了一個 Content-Encoding: gzip
罩缴,返回信息被壓縮了:
注意了蚊逢,一般 gzip 的配置建議加上 gzip_min_length 1k
层扶,不加的話:
由于文件太小,gzip 壓縮之后得到了 -48% 的體積優(yōu)化烙荷,壓縮之后體積還比壓縮之前體積大了镜会,所以最好設(shè)置低于 1kb
的文件就不要 gzip 壓縮了 ??
9.2 Webpack 的 gzip 配置
當(dāng)前端項目使用 Webpack 進(jìn)行打包的時候,也可以開啟 gzip 壓縮:
// vue-cli3 的 vue.config.js 文件const CompressionWebpackPlugin = require('compression-webpack-plugin')module.exports = { // gzip 配置 configureWebpack: config => { if (process.env.NODE_ENV === 'production') { // 生產(chǎn)環(huán)境 return { plugins: [new CompressionWebpackPlugin({ test: /\.js$|\.html$|\.css/, // 匹配文件名 threshold: 10240, // 文件壓縮閾值终抽,對超過10k的進(jìn)行壓縮 deleteOriginalAssets: false// 是否刪除源文件 })] } } }, ...}
由此打包出來的文件如下圖:
這里可以看到某些打包之后的文件下面有一個對應(yīng)的 .gz
經(jīng)過 gzip
壓縮之后的文件戳表,這是因為這個文件超過了 10kb
,有的文件沒有超過 10kb
就沒有進(jìn)行 gzip
打包昼伴,如果你期望壓縮文件的體積閾值小一點(diǎn)匾旭,可以在 compression-webpack-plugin
這個插件的配置里進(jìn)行對應(yīng)配置。
那么為啥這里 Nginx 已經(jīng)有了 gzip 壓縮圃郊,Webpack 這里又整了個 gzip 呢价涝,因為如果全都是使用 Nginx 來壓縮文件,會耗費(fèi)服務(wù)器的計算資源持舆,如果服務(wù)器的 gzip_comp_level
配置的比較高色瘩,就更增加服務(wù)器的開銷,相應(yīng)增加客戶端的請求時間逸寓,得不償失居兆。
如果壓縮的動作在前端打包的時候就做了,把打包之后的高壓縮等級文件作為靜態(tài)資源放在服務(wù)器上竹伸,Nginx 會優(yōu)先查找這些壓縮之后的文件返回給客戶端史辙,相當(dāng)于把壓縮文件的動作從 Nginx 提前給 Webpack 打包的時候完成,節(jié)約了服務(wù)器資源佩伤,所以一般推介在生產(chǎn)環(huán)境應(yīng)用 Webpack 配置 gzip 壓縮。
10. 配置負(fù)載均衡
負(fù)載均衡在之前已經(jīng)介紹了相關(guān)概念了晦毙,主要思想就是把負(fù)載均勻合理地分發(fā)到多個服務(wù)器上生巡,實現(xiàn)壓力分流的目的。
主要配置如下:
http { upstream myserver { # ip_hash; # ip_hash 方式 # fair; # fair 方式 server 127.0.0.1:8081; # 負(fù)載均衡目的服務(wù)地址 server 127.0.0.1:8080; server 127.0.0.1:8082 weight=10; # weight 方式见妒,不寫默認(rèn)為 1 } server { location / { proxy_pass http://myserver; proxy_connect_timeout 10; } }}
Nginx 提供了好幾種分配方式孤荣,默認(rèn)為輪詢,就是輪流來须揣。有以下幾種分配方式:
- 輪詢盐股,默認(rèn)方式,每個請求按時間順序逐一分配到不同的后端服務(wù)器耻卡,如果后端服務(wù)掛了疯汁,能自動剔除;
- weight卵酪,權(quán)重分配幌蚊,指定輪詢幾率谤碳,權(quán)重越高,在被訪問的概率越大溢豆,用于后端服務(wù)器性能不均的情況蜒简;
- ip_hash,每個請求按訪問 IP 的 hash 結(jié)果分配漩仙,這樣每個訪客固定訪問一個后端服務(wù)器搓茬,可以解決動態(tài)網(wǎng)頁 session 共享問題。負(fù)載均衡每次請求都會重新定位到服務(wù)器集群中的某一個队他,那么已經(jīng)登錄某一個服務(wù)器的用戶再重新定位到另一個服務(wù)器卷仑,其登錄信息將會丟失,這樣顯然是不妥的漱挎;
- fair(第三方)系枪,按后端服務(wù)器的響應(yīng)時間分配,響應(yīng)時間短的優(yōu)先分配磕谅,依賴第三方插件 nginx-upstream-fair私爷,需要先安裝;
11. 配置動靜分離
動靜分離在之前也介紹過了膊夹,就是把動態(tài)和靜態(tài)的請求分開衬浑。方式主要有兩種,一種 是純粹把靜態(tài)文件獨(dú)立成單獨(dú)的域名放刨,放在獨(dú)立的服務(wù)器上工秩,也是目前主流推崇的方案。另外一種方法就是動態(tài)跟靜態(tài)文件混合在一起發(fā)布进统, 通過 Nginx 配置來分開助币。
通過 location 指定不同的后綴名實現(xiàn)不同的請求轉(zhuǎn)發(fā)。通過 expires 參數(shù)設(shè)置螟碎,可以使瀏覽器緩存過期時間眉菱,減少與服務(wù)器之前的請求和流量。具體 expires 定義:是給一個資源設(shè)定一個過期時間掉分,也就是說無需去服務(wù)端驗證俭缓,直接通過瀏覽器自身確認(rèn)是否過期即可,所以不會產(chǎn)生額外的流量酥郭。此種方法非常適合不經(jīng)常變動的資源华坦。(如果經(jīng)常更新的文件,不建議使用 expires 來緩存)不从,我這里設(shè)置 3d惜姐,表示在這 3 天之內(nèi)訪問這個URL,發(fā)送一個請求椿息,比對服務(wù)器該文件最后更新時間沒有變化载弄。則不會從服務(wù)器抓取耘拇,返回狀態(tài)碼 304,如果有修改宇攻,則直接從服務(wù)器重新下載惫叛,返回狀態(tài)碼 200。
server { location /www/ { root /data/; index index.html index.htm; } location /image/ { root /data/; autoindex on; }}
12. 配置高可用集群(雙機(jī)熱備)
當(dāng)主 Nginx 服務(wù)器宕機(jī)之后逞刷,切換到備份 Nginx 服務(wù)器
<figcaption style="margin: 5px 0px 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; text-align: center; color: rgb(136, 136, 136); font-size: 14px;">2020-03-13-雙機(jī)熱備</figcaption>
首先安裝 keepalived嘉涌,
yum install keepalived -y
然后編輯 /etc/keepalived/keepalived.conf
配置文件,并在配置文件中增加 vrrp_script
定義一個外圍檢測機(jī)制夸浅,并在 vrrp_instance
中通過定義 track_script
來追蹤腳本執(zhí)行過程螺垢,實現(xiàn)節(jié)點(diǎn)轉(zhuǎn)移:
global_defs{ notification_email { acassen@firewall.loc } notification_email_from Alexandre@firewall.loc smtp_server 127.0.0.1 smtp_connect_timeout 30// 上面都是郵件配置苛蒲,沒卵用 router_id LVS_DEVEL // 當(dāng)前服務(wù)器名字社证,用hostname命令來查看}vrrp_script chk_maintainace { // 檢測機(jī)制的腳本名稱為chk_maintainace script "[[ -e/etc/keepalived/down ]] && exit 1 || exit 0"http:// 可以是腳本路徑或腳本命令 // script "/etc/keepalived/nginx_check.sh" // 比如這樣的腳本路徑 interval 2 // 每隔2秒檢測一次 weight -20 // 當(dāng)腳本執(zhí)行成立油啤,那么把當(dāng)前服務(wù)器優(yōu)先級改為-20}vrrp_instanceVI_1 { // 每一個vrrp_instance就是定義一個虛擬路由器 state MASTER // 主機(jī)為MASTER,備用機(jī)為BACKUP interface eth0 // 網(wǎng)卡名字坯钦,可以從ifconfig中查找 virtual_router_id 51 // 虛擬路由的id號预皇,一般小于255,主備機(jī)id需要一樣 priority 100 // 優(yōu)先級婉刀,master的優(yōu)先級比backup的大 advert_int 1 // 默認(rèn)心跳間隔 authentication { // 認(rèn)證機(jī)制 auth_type PASS auth_pass 1111 // 密碼 } virtual_ipaddress { // 虛擬地址vip 172.16.2.8 }}
其中檢測腳本 nginx_check.sh
吟温,這里提供一個:
#!/bin/bashA=`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服務(wù)殺死突颊。將vip漂移到其它備份節(jié)點(diǎn) fifi
復(fù)制一份到備份服務(wù)器鲁豪,備份 Nginx 的配置要將 state
后改為 BACKUP
,priority
改為比主機(jī)小律秃。
設(shè)置完畢后各自 service keepalived start
啟動爬橡,經(jīng)過訪問成功之后,可以把 Master 機(jī)的 keepalived 停掉棒动,此時 Master 機(jī)就不再是主機(jī)了 service keepalived stop
堤尾,看訪問虛擬 IP 時是否能夠自動切換到備機(jī) ip addr
。
再次啟動 Master 的 keepalived迁客,此時 vip 又變到了主機(jī)上。
13. 適配 PC 或移動設(shè)備
根據(jù)用戶設(shè)備不同返回不同樣式的站點(diǎn)辞槐,以前經(jīng)常使用的是純前端的自適應(yīng)布局掷漱,但無論是復(fù)雜性和易用性上面還是不如分開編寫的好,比如我們常見的淘寶榄檬、京東......這些大型網(wǎng)站就都沒有采用自適應(yīng)卜范,而是用分開制作的方式,根據(jù)用戶請求的 user-agent
來判斷是返回 PC 還是 H5 站點(diǎn)鹿榜。
首先在 /usr/share/nginx/html
文件夾下 mkdir
分別新建兩個文件夾 PC
和 mobile
海雪,vim
編輯兩個 index.html
隨便寫點(diǎn)內(nèi)容锦爵。
cd /usr/share/nginx/htmlmkdir pc mobilecd pcvim index.html # 隨便寫點(diǎn)比如 hello pc!cd ../mobilevim index.html # 隨便寫點(diǎn)比如 hello mobile!
然后和設(shè)置二級域名虛擬主機(jī)時候一樣,去 /etc/nginx/conf.d
文件夾下新建一個配置文件 fe.sherlocked93.club.conf
:
# /etc/nginx/conf.d/fe.sherlocked93.club.confserver { listen 80; server_name fe.sherlocked93.club; location / { root /usr/share/nginx/html/pc; if ($http_user_agent ~* '(Android|webOS|iPhone|iPod|BlackBerry)') { root /usr/share/nginx/html/mobile; } index index.html; }}
配置基本沒什么不一樣的奥裸,主要多了一個 if
語句险掀,然后使用 $http_user_agent
全局變量來判斷用戶請求的 user-agent
,指向不同的 root 路徑湾宙,返回對應(yīng)站點(diǎn)樟氢。
在瀏覽器訪問這個站點(diǎn),然后 F12 中模擬使用手機(jī)訪問:
可以看到在模擬使用移動端訪問的時候侠鳄,Nginx 返回的站點(diǎn)變成了移動端對應(yīng)的 html 了埠啃。
14. 配置 HTTPS
具體配置過程網(wǎng)上挺多的了,也可以使用你購買的某某云伟恶,一般都會有免費(fèi)申請的服務(wù)器證書碴开,安裝直接看所在云的操作指南即可。
我購買的騰訊云提供的亞洲誠信機(jī)構(gòu)頒發(fā)的免費(fèi)證書只能一個域名使用博秫,二級域名什么的需要另外申請潦牛,但是申請審批比較快,一般幾分鐘就能成功台盯,然后下載證書的壓縮文件罢绽,里面有個 nginx 文件夾,把 xxx.crt
和 xxx.key
文件拷貝到服務(wù)器目錄静盅,再配置下:
server { listen 443 ssl http2 default_server; # SSL 訪問端口號為 443 server_name sherlocked93.club; # 填寫綁定證書的域名 ssl_certificate /etc/nginx/https/1_sherlocked93.club_bundle.crt; # 證書文件地址 ssl_certificate_key /etc/nginx/https/2_sherlocked93.club.key; # 私鑰文件地址 ssl_session_timeout 10m; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; #請按照以下協(xié)議配置 ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE; ssl_prefer_server_ciphers on; location / { root /usr/share/nginx/html; index index.html index.htm; }}
寫完 nginx -t -q
校驗一下良价,沒問題就 nginx -s reload
,現(xiàn)在去訪問 https://sherlocked93.club/
就能訪問 HTTPS 版的網(wǎng)站了蒿叠。
一般還可以加上幾個增強(qiáng)安全性的命令:
add_header X-Frame-Options DENY; # 減少點(diǎn)擊劫持add_header X-Content-Type-Options nosniff; # 禁止服務(wù)器自動解析資源類型add_header X-Xss-Protection 1; # 防XSS攻擊
15. 一些常用技巧
15.1 靜態(tài)服務(wù)
server { listen 80; server_name static.sherlocked93.club; charset utf-8; # 防止中文文件名亂碼 location /download { alias /usr/share/nginx/html/static; # 靜態(tài)資源目錄 autoindex on; # 開啟靜態(tài)資源列目錄 autoindex_exact_size off; # on(默認(rèn))顯示文件的確切大小明垢,單位是byte;off顯示文件大概大小市咽,單位KB痊银、MB、GB autoindex_localtime off; # off(默認(rèn))時顯示的文件時間為GMT時間施绎;on顯示的文件時間為服務(wù)器時間 }}
15.2 圖片防盜鏈
server { listen 80; server_name *.sherlocked93.club; # 圖片防盜鏈 location ~* \.(gif|jpg|jpeg|png|bmp|swf)$ { valid_referers none blocked 192.168.0.2; # 只允許本機(jī) IP 外鏈引用 if ($invalid_referer){ return 403; } }}
15.3 請求過濾
# 非指定請求全返回 403if ( $request_method !~ ^(GET|POST|HEAD)$ ) { return 403;}location / { # IP訪問限制(只允許IP是 192.168.0.2 機(jī)器訪問) allow 192.168.0.2; deny all; root html; index index.html index.htm;}
15.4 配置圖片溯革、字體等靜態(tài)文件緩存
由于圖片、字體谷醉、音頻致稀、視頻等靜態(tài)文件在打包的時候通常會增加了 hash,所以緩存可以設(shè)置的長一點(diǎn)俱尼,先設(shè)置強(qiáng)制緩存抖单,再設(shè)置協(xié)商緩存;如果存在沒有 hash 值的靜態(tài)文件,建議不設(shè)置強(qiáng)制緩存矛绘,僅通過協(xié)商緩存判斷是否需要使用緩存耍休。
# 圖片緩存時間設(shè)置location ~ .*\.(css|js|jpg|png|gif|swf|woff|woff2|eot|svg|ttf|otf|mp3|m4a|aac|txt)$ { expires 10d;}# 如果不希望緩存expires -1;
15.5 單頁面項目 history 路由配置
server { listen 80; server_name fe.sherlocked93.club; location / { root /usr/share/nginx/html/dist; # vue 打包后的文件夾 index index.html index.htm; try_files $uri$uri/ /index.html @rewrites; expires -1; # 首頁一般沒有強(qiáng)制緩存 add_header Cache-Control no-cache; } # 接口轉(zhuǎn)發(fā),如果需要的話 #location ~ ^/api { # proxy_pass http://be.sherlocked93.club; #} location @rewrites { rewrite ^(.+)$ /index.html break; }}
15.6 HTTP 請求轉(zhuǎn)發(fā)到 HTTPS
配置完 HTTPS 后货矮,瀏覽器還是可以訪問 HTTP 的地址 http://sherlocked93.club/
的羊精,可以做一個 301 跳轉(zhuǎn),把對應(yīng)域名的 HTTP 請求重定向到 HTTPS 上
server { listen 80; server_name www.sherlocked93.club; # 單域名重定向 if ($host = 'www.sherlocked93.club'){ return 301 https://www.sherlocked93.club$request_uri; } # 全局非 https 協(xié)議時重定向 if ($scheme != 'https') { return 301 https://$server_name$request_uri; } # 或者全部重定向 return 301 https://$server_name$request_uri; # 以上配置選擇自己需要的即可次屠,不用全部加}
15.7 泛域名路徑分離
這是一個非常實用的技能园匹,經(jīng)常有時候我們可能需要配置一些二級或者三級域名,希望通過 Nginx 自動指向?qū)?yīng)目錄劫灶,比如:
-
test1.doc.sherlocked93.club
自動指向/usr/share/nginx/html/doc/test1
服務(wù)器地址裸违; -
test2.doc.sherlocked93.club
自動指向/usr/share/nginx/html/doc/test2
服務(wù)器地址;
server { listen 80; server_name ~^([\w-]+)\.doc\.sherlocked93\.club$; root /usr/share/nginx/html/doc/$1;}
15.8 泛域名轉(zhuǎn)發(fā)
和之前的功能類似本昏,有時候我們希望把二級或者三級域名鏈接重寫到我們希望的路徑供汛,讓后端就可以根據(jù)路由解析不同的規(guī)則:
-
test1.serv.sherlocked93.club/api?name=a
自動轉(zhuǎn)發(fā)到127.0.0.1:8080/test1/api?name=a
; -
test2.serv.sherlocked93.club/api?name=a
自動轉(zhuǎn)發(fā)到127.0.0.1:8080/test2/api?name=a
涌穆;
server { listen 80; server_name ~^([\w-]+)\.serv\.sherlocked93\.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/$1$request_uri; }}
16. 最佳實踐
- 為了使 Nginx 配置更易于維護(hù)怔昨,建議為每個服務(wù)創(chuàng)建一個單獨(dú)的配置文件,存儲在
/etc/nginx/conf.d
目錄宿稀,根據(jù)需求可以創(chuàng)建任意多個獨(dú)立的配置文件趁舀。 - 獨(dú)立的配置文件,建議遵循以下命名約定
<服務(wù)>.conf
祝沸,比如域名是sherlocked93.club
矮烹,那么你的配置文件的應(yīng)該是這樣的/etc/nginx/conf.d/sherlocked93.club.conf
,如果部署多個服務(wù)罩锐,也可以在文件名中加上 Nginx 轉(zhuǎn)發(fā)的端口號奉狈,比如sherlocked93.club.8080.conf
,如果是二級域名涩惑,建議也都加上fe.sherlocked93.club.conf
仁期。 - 常用的、復(fù)用頻率比較高的配置可以放到
/etc/nginx/snippets
文件夾竭恬,在 Nginx 的配置文件中需要用到的位置 include 進(jìn)去跛蛋,以功能來命名,并在每個 snippet 配置文件的開頭注釋標(biāo)明主要功能和引入位置痊硕,方便管理赊级。比如之前的gzip
、cors
等常用配置寿桨,我都設(shè)置了 snippet。 - Nginx 日志相關(guān)目錄,內(nèi)以
域名.type.log
命名(比如be.sherlocked93.club.access.log
和be.sherlocked93.club.error.log
)位于/var/log/nginx/
目錄中亭螟,為每個獨(dú)立的服務(wù)配置不同的訪問權(quán)限和錯誤日志文件挡鞍,這樣查找錯誤時,會更加方便快捷预烙。
網(wǎng)上的帖子大多深淺不一墨微,甚至有些前后矛盾,在下的文章都是學(xué)習(xí)過程中的總結(jié)扁掸,如果發(fā)現(xiàn)錯誤翘县,歡迎留言指出~