- Nginx詳解
- 1. Nginx關鍵特性
- 2. Nginx配置
- 2.1 event
- 2.2 http
- 2.2.1 log_format
- 2.2.2 sendfile
- 2.2.3 tcp_nopush
- 2.2.4 tcp_nodelay
- 2.2.5 keepalive_timeout
- 2.2.6 include
- 2.2.7 default_type
- 2.2.8 server
- 3. 配置Nginx虛擬主機
- 3.1 基於埠
- 3.2 基於IP
- 3.3 基於域名
- 4. Location
- 4.1 拒絕訪問
- 4.2 拒絕訪問test開頭的所有檔案
- 4.3 忽略大小寫
- 4.4 反向代理
- 5. 配置https
- 6. Nginx熱升級
- 6.1 環境清理
- 6.2 編譯安裝舊版本Nginx
- 6.3 啟動舊版nginx
- 6.4 下載新版nginx
Nginx詳解
Nginx與Apache一樣,都是web伺服器,但是Nginx比Apache多一些功能,比如Nginx可以做代理,可以做負載均衡……
1. Nginx關鍵特性
- 支援高併發
- 單機Nginx可支援十萬級別的併發連線,經過最佳化後可支援百萬級別併發
- 記憶體資源消耗低
- 在同級web中,Nginx佔用的記憶體最少,一萬非活躍的http長連線僅消耗2.5M記憶體
- 高擴充套件性
- 和Apache一樣,Nginx採用模組化設計,並支援非常多豐富的第三方模組
- 高可靠性
- Nginx採用master-worker模式,如果worker出現故障,master可以快速開啟一個新的worker來提供服務
2. Nginx配置
[root@ceph conf.d]# grep -Ev "^#|^$|#" /etc/nginx/nginx.conf |cat -n
1 user nginx;
2 worker_processes auto;
3 error_log /var/log/nginx/error.log;
4 pid /run/nginx.pid;
5 include /usr/share/nginx/modules/*.conf;
6 events {
7 worker_connections 1024;
8 }
9 http {
10 log_format main '$remote_addr - $remote_user [$time_local] "$request" '
11 '$status $body_bytes_sent "$http_referer" '
12 '"$http_user_agent" "$http_x_forwarded_for"';
13 access_log /var/log/nginx/access.log main;
14 sendfile on;
15 tcp_nopush on;
16 tcp_nodelay on;
17 keepalive_timeout 65;
18 types_hash_max_size 4096;
19 include /etc/nginx/mime.types;
20 default_type application/octet-stream;
21 include /etc/nginx/conf.d/*.conf;
22 server {
23 listen 80;
24 listen [::]:80;
25 server_name _;
26 root /usr/share/nginx/html;
27 include /etc/nginx/default.d/*.conf;
28 error_page 404 /404.html;
29 location = /40x.html {
30 }
31 error_page 500 502 503 504 /50x.html;
32 location = /50x.html {
33 }
34 }
35 }
由於之前很詳細的寫過Apache的配置了,這裡就說一下這倆服務之間的差異,nginx的配置檔案每行配置結束必須以分號;結尾
- Nginx也可以配置啟動的使用者,預設為nginx,可以修改
- Nginx工作程序,預設為auto(與CPU核心數保持一致),也可以手動修改
- 定義nginx的錯誤日誌
這兩個都是Apache服務裡面也有的,這裡就簡答說一下
2.1 event
第六行event這個是指定nginx的工作模式,預設的,Apache也有這個模式,這個段落裡面的內容
events {
worker_connections 1024; 指定單個程序的連線數
}
2.2 http
這個段落裡面就是一些http的配置
2.2.1 log_format
首先就是定義日誌的格式log_format,然後就是access.log這個就不細寫
2.2.2 sendfile
sendfile on;這個代表高效傳輸,也就是可以將檔案直接從磁碟傳輸到網路中,而不先讀到記憶體
2.2.3 tcp_nopush
tcp_nopush on 立刻回應tcp的請求
2.2.4 tcp_nodelay
tcp_nodelay on 對於小資料包直接回應
2.2.5 keepalive_timeout
keepalive_timeout 65,這個透過名字就可以知道,是長連線的超時時間
2.2.6 include
我跳過了types_hash_max_size,這個是hash雜湊表,我也不知道是幹嘛的
include /etc/nginx/mime.types; 這裡是載入nginx能夠識別的型別,你可以開啟這個檔案去看這裡面都定義了什麼,開啟就一目瞭然了
2.2.7 default_type
default_type application/octet-stream; 二進位制的檔案可以直接下載
2.2.8 server
server {
listen 80;
listen [::]:80;
server_name _;
root /usr/share/nginx/html;
include /etc/nginx/default.d/*.conf;
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
}
這裡的server對應的就是Apache的虛擬主機
listen 監聽的埠,他這裡預設監聽了2個,一個是IPv4,另一個是IPv6
server_name:對外提供的服務名,也就是域名
root:網站根目錄
include: 定義虛擬主機的特性,可以將一些其他的特性解除安裝conf.d/下之後他會自動載入配置
error_page 404 :這個是錯誤頁,當404出現的時候,nginx會返回網站根目錄下的404.html
locatioin: 這個是nginx的重頭戲,叫做路由規則,你可以將路由策略寫在這,他就會根據你的策略來處理流量,這個我們稍後細講
error_page 500當服務發生500以上的錯誤的時候,nginx返回網站根目錄下的50x.html
3. 配置Nginx虛擬主機
Nginx也支援3種虛擬主機,與Apache一樣
- 基於埠的虛擬主機
- 基於IP的虛擬主機
- 基於域名的虛擬主機
3.1 基於埠
虛擬主機我們可以在conf.d下進行配置
[root@ceph conf.d]# vim virthost.conf
server {
listen 81;
root /web1;
}
server {
listen 82;
root /web2;
}
[root@ceph conf.d]# echo 81 > /web1/index.html
[root@ceph conf.d]# echo 82 > /web2/index.html
[root@ceph conf.d]# systemctl restart nginx
[root@ceph conf.d]# curl localhost:82
82
[root@ceph conf.d]# curl localhost:81
81
基於埠的虛擬主機這樣就配好了
3.2 基於IP
首先配置一個臨時IP
[root@ceph conf.d]# sudo ip addr add 192.168.1.100/24 dev ens33
[root@ceph conf.d]# ip a |grep 192.168.1.100
inet 192.168.1.100/24 scope global ens33
虛擬的IP就配置好了,接下來配置nginx
[root@ceph conf.d]# vim virthost.conf
server {
listen 81;
root /web1;
}
server {
listen 82;
root /web2;
}
server {
listen 192.168.200.210:80;
root /web3;
}
server {
listen 192.168.1.100:80;
root /web4;
}
然後我們建立對應的網站根目錄以及index.html
[root@ceph conf.d]# echo 192.168.200.210 > /web3/index.html
[root@ceph conf.d]# echo 192.168.1.100 > /web4/index.html
[root@ceph conf.d]# systemctl restart nginx
[root@ceph conf.d]# curl 192.168.200.210
192.168.200.210
[root@ceph conf.d]# curl 192.168.1.100
192.168.1.100
可以看到,透過不同的ip訪問回顯是不同的內容
3.3 基於域名
[root@ceph conf.d]# vim virthost.conf
server {
listen 80;
server_name test.com;
root /web5;
}
server {
listen 80;
server_name example.com;
root /web6;
}
建立根目錄以及重啟服務,還需要做hosts解析
[root@ceph conf.d]# echo web5 > /web5/index.html
[root@ceph conf.d]# echo web6 > /web6/index.html
[root@ceph conf.d]# systemctl restart nginx
[root@ceph conf.d]# vim /etc/hosts
192.168.200.210 test.com
192.168.200.210 example.com
[root@ceph conf.d]# curl test.com
web5
[root@ceph conf.d]# curl example.com
web6
這樣也是可以訪問到對應的檔案的
4. Location
這個是nginx最重要的配置了,在Apache裡面訪問控制是用Directory
和Files
來做的,那麼在nginx裡面的做法就是location了
4.1 拒絕訪問
我不想你訪問網站根目錄下的/test.html,那麼我的路由規則就應該這樣寫,還是在虛擬主機裡定義
[root@ceph conf.d]# vim virthost.conf
server {
listen 80;
server_name test.com;
root /web5;
location /test.html {
return 403;
}
}
我們來建立這個test.html檔案,並嘗試訪問
[root@ceph conf.d]# echo "test file" > /web5/test.html
[root@ceph conf.d]# systemctl restart nginx
[root@ceph conf.d]# curl 192.168.200.210/test.html
<html>
<head><title>403 Forbidden</title></head>
<body>
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx</center>
</body>
</html>
看到了嗎?他就返回的是403,這樣做之後,訪問test.html的請求就被拒絕掉了,但是如果我們需要拒絕掉所有以test開頭的檔案呢?也是跟Apache一樣使用 * 號嗎?不,Nginx是另外的做法
4.2 拒絕訪問test開頭的所有檔案
[root@ceph conf.d]# vim virthost.conf
server {
listen 80;
server_name test.com;
root /web5;
location ^~ /test {
return 403;
}
}
[root@ceph conf.d]# echo test > /web5/test.1
[root@ceph conf.d]# echo test > /web5/test.2
[root@ceph conf.d]# systemctl restart nginx
我們在/web5下建立了test.1和test.2包括之前建立的test.html一共有3個test開頭的檔案,那我們現在來嘗試訪問一下
[root@ceph conf.d]# curl 192.168.200.210/test.html -I
HTTP/1.1 403 Forbidden
Server: nginx
Date: Tue, 02 Jul 2024 09:09:49 GMT
Content-Type: text/html
Content-Length: 146
Connection: keep-alive
[root@ceph conf.d]# curl 192.168.200.210/test.1 -I
HTTP/1.1 403 Forbidden
Server: nginx
Date: Tue, 02 Jul 2024 09:09:56 GMT
Content-Type: text/html
Content-Length: 146
Connection: keep-alive
[root@ceph conf.d]# curl 192.168.200.210/test.xxx -I
HTTP/1.1 403 Forbidden
Server: nginx
Date: Tue, 02 Jul 2024 09:10:12 GMT
Content-Type: text/html
Content-Length: 146
Connection: keep-alive
看到了吧,儘管我們訪問一個不存在的檔案,按道理應該是返回404,但是這個檔案是以test開頭,那麼他會被拒絕訪問,不管這個檔案存不存在
但是這樣配置,只能拒絕掉以test開頭的,我如果訪問的是Test,那麼他就不會被拒絕了
[root@ceph conf.d]# curl 192.168.200.210/Test -I
HTTP/1.1 404 Not Found
Server: nginx
Date: Tue, 02 Jul 2024 09:12:57 GMT
Content-Type: text/html
Content-Length: 146
Connection: keep-alive
對吧,因為我們沒有這個資源,所以他返回了404,而不是403,說明沒有被拒絕,如果想忽略大小寫,可以這樣做
4.3 忽略大小寫
[root@ceph conf.d]# vim virthost.conf
server {
listen 80;
server_name test.com;
root /web5;
location ~* /test {
return 403;
}
}
只需要將^~
這個地方改為~*
,我們來訪問一下看看
[root@ceph conf.d]# curl -I 192.168.200.210/test
HTTP/1.1 403 Forbidden
Server: nginx
Date: Tue, 02 Jul 2024 09:15:17 GMT
Content-Type: text/html
Content-Length: 146
Connection: keep-alive
[root@ceph conf.d]# curl -I 192.168.200.210/Test
HTTP/1.1 403 Forbidden
Server: nginx
Date: Tue, 02 Jul 2024 09:15:21 GMT
Content-Type: text/html
Content-Length: 146
Connection: keep-alive
[root@ceph conf.d]# curl -I 192.168.200.210/TEst
HTTP/1.1 403 Forbidden
Server: nginx
Date: Tue, 02 Jul 2024 09:15:23 GMT
Content-Type: text/html
Content-Length: 146
Connection: keep-alive
現在的配置,不管你的大寫的TEST還是小寫的test,亦或者是大小寫都有的,一律都會被拒絕訪問
4.4 反向代理
我們還可以透過location來做反向代理,比如你現在訪問我網站下的/
那我就直接給你代理到baidu.com
去,你要搜尋啥你自己去搜吧,你以為這個百度是我給你提供的,其實不然,我是把你的請求給到百度了
[root@ceph conf.d]# vim virthost.conf
server {
listen 80;
server_name test.com;
root /web5;
location / {
proxy_pass https://www.baidu.com;
}
}
看到了嗎?這是貨真價實的百度哦,可以搜尋內容的
怎麼樣,你現在就搭建了一個反向代理,客戶端只知道他訪問的是192.168.200.210這個IP,他並不知道你把他的請求給了百度,所以客戶端會以為你就是百度
5. 配置https
nginx配置https的方式其實跟Apache是差不多的,直接告訴他你的金鑰檔案放在哪,有2種方式可以配置https,第一種是直接改主配置檔案,主配置檔案裡是有https段落的,只不過預設被註釋了。
第二種方式就是自己寫一個虛擬主機,我這裡直接修改主配置檔案
[root@ceph nginx]# vim nginx.conf
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name _;
root /usr/share/nginx/html;
ssl_certificate "/etc/nginx/server.crt";
ssl_certificate_key "/etc/nginx/server.key";
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
將這一段的註釋全部給放開,ssl只保留需要的這2行內容,然後將證書地址改為你的證書的實際目錄就可以了,然後重啟nginx服務
6. Nginx熱升級
Nginx熱升級是指可以做到不停機升級Nginx的版本,yum安裝的Nginx是不支援熱升級的,如果想要熱升級Nginx,那麼你的Nginx必須是原始碼編譯安裝的
編譯安裝流程:
- 下載原始碼包
- 解壓原始碼包
- 執行預編譯 ./configure
- 編譯 make
- 編譯安裝 make install
這是編譯安裝的流程
在執行到第5步的時候,他就會將編譯好的二進位制檔案放在objs目錄下,就是依賴於這個目錄下的二進位制檔案我們才可以做到版本共存
nginx的熱升級原理主要依賴於以下幾個關鍵步驟:
- 啟動新版本的nginx程序:在進行熱升級時,首先啟動一個新版本的nginx程序,這個程序會使用新的配置檔案和程式檔案。
- 舊版本nginx程序繼續服務:啟動新版本nginx程序後,舊版本的nginx程序仍然繼續執行,繼續處理客戶端的請求。
- 新舊版本的協調切換:新版本nginx程序啟動後,會逐漸接管處理新的客戶端請求。同時,舊版本nginx程序在處理完當前已有的請求後逐漸退出。
- 共享監聽埠:新舊版本的nginx程序可以透過共享監聽的網路埠來實現平滑過渡。在大多數情況下,nginx會採用SO_REUSEPORT選項來允許多個程序監聽同一個埠。
- 無縫切換:由於新舊版本nginx程序可以並行執行並共享埠,因此在沒有中斷服務的情況下完成從舊版本到新版本的切換,實現了熱升級。
6.1 環境清理
如果你已經使用yum安裝了,先解除安裝nginx
[root@ceph ~]# yum remove -y nginx
6.2 編譯安裝舊版本Nginx
Nginx下載地址
在這裡面找一個相對舊一點的版本,我這裡下載一個1.26.1,然後將1.26.1升級到1.27.0
[root@ceph ~]# cd /opt/
[root@ceph opt]# wget https://nginx.org/download/nginx-1.26.1.tar.gz
[root@ceph opt]# tar -zxf nginx-1.26.1.tar.gz
[root@ceph opt]# cd nginx-1.26.1/
[root@ceph nginx-1.26.1]# ls
auto CHANGES.ru configure html man src
CHANGES conf contrib LICENSE README
[root@ceph nginx-1.26.1]# ./configure --prefix=/usr/local/nginx
在這裡執行的時候他可能會報錯,根據他的報錯你安裝相對應的軟體包就好了
Configuration summary
+ using system PCRE2 library
+ OpenSSL library is not used
+ using system zlib library
nginx path prefix: "/usr/local/nginx"
nginx binary file: "/usr/local/nginx/sbin/nginx"
nginx modules path: "/usr/local/nginx/modules"
nginx configuration prefix: "/usr/local/nginx/conf"
nginx configuration file: "/usr/local/nginx/conf/nginx.conf"
nginx pid file: "/usr/local/nginx/logs/nginx.pid"
nginx error log file: "/usr/local/nginx/logs/error.log"
nginx http access log file: "/usr/local/nginx/logs/access.log"
nginx http client request body temporary files: "client_body_temp"
nginx http proxy temporary files: "proxy_temp"
nginx http fastcgi temporary files: "fastcgi_temp"
nginx http uwsgi temporary files: "uwsgi_temp"
nginx http scgi temporary files: "scgi_temp"
他執行完之後會這樣輸出就是沒有錯誤,可以繼續往下做
[root@ceph nginx-1.26.1]# make -j 4
- -j 指定並行編譯的程序數為4
[root@ceph nginx-1.26.1]# make install
6.3 啟動舊版nginx
由於我們指定的安裝路徑是/usr/local/nginx,所以他會在這個目錄下生成一個sbin的目錄,這個目錄裡面有一個二進位制檔案nginx,執行他就可以啟動nginx
[root@ceph nginx-1.26.1]# cd /usr/local/nginx/sbin/
[root@ceph sbin]# ./nginx
[root@ceph sbin]# curl -I 192.168.200.210
HTTP/1.1 200 OK
Server: nginx/1.26.1
Date: Tue, 02 Jul 2024 11:27:47 GMT
Content-Type: text/html
Content-Length: 615
Last-Modified: Tue, 02 Jul 2024 11:25:09 GMT
Connection: keep-alive
ETag: "6683e395-267"
Accept-Ranges: bytes
在server這一欄我們可以看見nginx的版本是1.26.1
6.4 下載新版nginx
現在我們將nginx升級到1.27.0
[root@ceph sbin]# cd /opt/
[root@ceph opt]# wget https://nginx.org/download/nginx-1.27.0.tar.gz
[root@ceph opt]# tar -zxf nginx-1.27.0.tar.gz
[root@ceph opt]# cd nginx-1.27.0/
[root@ceph nginx-1.27.0]# ./configure --prefix=/usr/local/nginx
[root@ceph nginx-1.27.0]# make -j 4
這裡非常需要注意,一定不要去執行make install
了,因為執行這個命令的話會將原來的nginx全部覆蓋掉,我們只需要替換掉nginx的二進位制檔案就好了
我們來到objs目錄
[root@ceph nginx-1.27.0]# ls
auto CHANGES.ru configure html Makefile objs src
CHANGES conf contrib LICENSE man README
[root@ceph nginx-1.27.0]# cd objs/
[root@ceph objs]# ls
autoconf.err nginx ngx_auto_config.h ngx_modules.c src
Makefile nginx.8 ngx_auto_headers.h ngx_modules.o
這裡面就有一個nginx的二進位制檔案,先彆著急啟動,我們先將老版本的nginx二進位制檔案進行備份
[root@ceph objs]# cp /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx.bak
[root@ceph objs]# cd /usr/local/nginx/sbin/
[root@ceph sbin]# cp /opt/nginx-1.27.0/objs/nginx .
cp: overwrite './nginx'? y
[root@ceph sbin]# ./nginx -v
nginx version: nginx/1.27.0
現在我們就已經將1.27.0的二進位制檔案複製到這個地方來了,接下來我們需要將nginx1.27.0也給啟動起來。
你這時候可能會有疑問,80埠不是已經被老版本的nginx給佔用了嗎,我現在在啟動不會報錯嗎?答案肯定是會,所以我們在啟動之前還需要進行一個操作,給老版本的nginx'傳送一個USR2
的訊號
[root@ceph sbin]# ps -ef |grep nginx
root 46538 1 0 19:27 ? 00:00:00 nginx: master process ./nginx
nobody 46539 46538 0 19:27 ? 00:00:00 nginx: worker process
root 49680 15412 0 19:36 pts/0 00:00:00 grep --color=auto nginx
我們查到nginx master的程序id是46538,接下來就是發訊號了
[root@ceph sbin]# kill -s USR2 46538
# 然後我們再啟動nginx
[root@ceph sbin]# ps -ef |grep nginx
root 46538 1 0 19:27 ? 00:00:00 nginx: master process ./nginx
nobody 46539 46538 0 19:27 ? 00:00:00 nginx: worker process
root 49708 46538 0 19:37 ? 00:00:00 nginx: master process ./nginx
nobody 49709 49708 0 19:37 ? 00:00:00 nginx: worker process
root 49761 15412 0 19:38 pts/0 00:00:00 grep --color=auto nginx
看到了嗎?除了老版本的46538之外,還有一個新的nginx master程序,49708
嘗試訪問
[root@ceph sbin]# curl 192.168.200.210 -I
HTTP/1.1 200 OK
Server: nginx/1.27.0
Date: Tue, 02 Jul 2024 11:39:04 GMT
Content-Type: text/html
Content-Length: 615
Last-Modified: Tue, 02 Jul 2024 11:25:09 GMT
Connection: keep-alive
ETag: "6683e395-267"
Accept-Ranges: bytes
看,他現在處理連線的版本就是1.27.0了,如果老版本的nginx還有連線在處理的話也是不會受到影響的,等我們確認沒問題之後我們只需要將老版本給kill掉
[root@ceph sbin]# kill 46538
[root@ceph sbin]# ps -ef |grep nginx
root 49708 1 0 19:37 ? 00:00:00 nginx: master process ./nginx
nobody 49709 49708 0 19:37 ? 00:00:00 nginx: worker process
root 49913 15412 0 19:40 pts/0 00:00:00 grep --color=auto nginx
這個時候老版本就成功退役了,所有的連線都交由新版本的nginx來處理,我們的熱升級就搞定了