模塊與作業原理
nginx由內核和模塊組成,其中,內核的設計非常微小和簡潔,完成的作業也非常簡單,僅僅通過查找組態檔將客戶端請求映射到一個location block(location是nginx配置中的一個指令,用于URL匹配),而在這個location中所配置的每個指令將會啟動不同的模塊去完成相應的作業,
模塊分類
nginx的模塊從結構上分為核心模塊、基礎模塊和第三方模塊
- HTTP模塊、EVENT模塊和MAIL模塊等屬于核心模塊
- HTTP Access模塊、HTTP FastCGI模塊、HTTP Proxy模塊和HTTP Rewrite模塊屬于基本模塊
- HTTP Upstream模塊、Request Hash模塊、Notice模塊和HTTP Access Key模塊屬于第三方模塊
用戶根據自己的需要開發的模塊都屬于第三方模塊,
nginx模塊從功能上分為三類,分別是:
- Handlers(處理器模塊),此類模塊直接處理請求,并進行輸出內容和修改headers資訊等操作,handlers處理器模塊一般只能有一個
- Filters(過濾器模塊),此類模塊主要對其他處理器模塊輸出的內容進行修改操作,最后由nginx輸出
- Proxies(代理器模塊),就是nginx的HTTP Upstream之類的模塊,這些模塊主要與后端一些服務比如fastcgi等操作互動,實作服務代理和負載均衡等功能
nginx模塊分為:核心模塊、事件模塊、標準Http模塊、可選Http模塊、郵件模塊、第三方模塊和補丁等
nginx基本模塊:所謂基本模塊,指的是nginx默認的功能模塊,它們提供的指令,允許你使用定義nginx基本功能的變數,在編譯時不能被禁用,包括:
- 核心模塊:基本功能和指令,如行程管理和安全,常見的核心模塊指令,大部分是放置在組態檔的頂部
- 事件模塊:在Nginx內配置網路使用的能力,常見的events(事件)模塊指令,大部分是放置在組態檔的頂部
- 配置模塊:提供包含機制
更多的指令,請參考nginx官方檔案
nginx的作業原理
nginx的模塊直接被編譯進nginx,因此屬于靜態編譯方式,
啟動nginx后,nginx的模塊被自動加載,與Apache不一樣,首先將模塊編譯為一個so檔案,然后在組態檔中指定是否進行加載,
在決議組態檔時,nginx的每個模塊都有可能去處理某個請求,但是同一個處理請求只能由一個模塊來完成,
nginx的行程架構:
啟動nginx時,會啟動一個Master行程,這個行程不處理任何客戶端的請求,主要用來產生worker執行緒,一個worker執行緒用來處理n個request,
worker 行程中,ngx_worker_process_cycle()函式就是這個無限回圈的處理函式,在這個函式中,一個請求的簡單處理流程如下:
- 作業系統提供的機制(例如 epoll, kqueue 等)產生相關的事件,
- 接收和處理這些事件,如是接收到資料,則產生更高層的 request 物件,
- 處理 request 的 header 和 body,
- 產生回應,并發送回客戶端,
- 完成 request 的處理,
- 重新初始化定時器及其他事件,

多行程模型的處理方式:
- 首先,master行程一開始就會根據我們的配置,來建立需要listen的網路socket fd,然后fork出多個worker行程,
- 其次,根據行程的特性,新建立的worker行程,也會和master行程一樣,具有相同的設定,因此,其也會去監聽相同ip埠的套接字socket fd,
然后,這個時候有多個worker行程都在監聽同樣設定的socket fd,意味著當有一個請求進來的時候,所有的worker都會感知到,這樣就會產生所謂的“驚群現象”,為了保證只會有一個行程成功注冊到listenfd的讀事件,nginx中實作了一個“accept_mutex”類似互斥鎖,只有獲取到這個鎖的行程,才可以去注冊讀事件,其他行程全部accept 失敗, - 最后,監聽成功的worker行程,讀取請求,決議處理,回應資料回傳給客戶端,斷開連接,結束,因此,一個request請求,只需要worker行程就可以完成,
nginx模塊一次常規的HTTP請求和回應的程序

一個典型的HTTP處理周期:
7. 客戶端發送HTTP請求
8. Nginx基于組態檔中的位置選擇一個合適的處理模塊
9. (如果有)負載均衡模塊選擇一臺后端服務器
10. 處理模塊進行處理并把輸出緩沖放到第一個過濾模塊上
11. 第一個過濾模塊處理后輸出給第二個過濾模塊
12. 然后第二個過濾模塊又到第三個
13. 依此類推 –> 最后把回應發給客戶端,
Nginx本身做的作業實際很少,當它接到一個HTTP請求時,它僅僅是通過查找組態檔將此次請求映射到一個location block,而此location中所配置的各個指令則會啟動不同的模塊去完成作業,因此模塊可以看做Nginx真正的勞動作業者,
基本的WEB服務請求步驟

- 建立連接 — 接受一個客戶端連接,或者如果不希望與這個客戶端建立連接,就將其關閉,
- 接收請求 — 從網路中讀取一條 HTTP 請求報文,
- 處理請求 — 對請求報文進行解釋,并采取行動,
- 訪問資源 — 訪問報文中指定的資源,
- 構建回應 — 創建帶有正確首部的 HTTP 回應報文,
- 發送回應 — 將回應回送給客戶端,
- 記錄事務處理程序 — 將與已完成事務有關的內容記錄在一個日志檔案中,
nginx部署
nginx的安裝
# 關閉防火墻和selinux
[root@localhost ~]# systemctl disable --now firewalld
Removed /etc/systemd/system/multi-user.target.wants/firewalld.service.
Removed /etc/systemd/system/dbus-org.fedoraproject.FirewallD1.service.
[root@localhost ~]# sed -ri 's/^(SELINUX=).*/\1disabled/g' /etc/selinux/config
[root@localhost ~]# reboot
[root@localhost ~]# getenforce 0
Disabled
# 創建系統用戶nginx
[root@localhost ~]# useradd -r -M -s /sbin/nologin nginx
# 安裝依賴環境
[root@localhost ~]# yum -y install pcre-devel openssl openssl-devel gd-devel gcc gcc-c++ vim wget make
[root@localhost ~]# yum -y groups mark install 'Development Tools'
# 創建日志存放目錄
[root@localhost ~]# mkdir -p /var/log/nginx
[root@localhost ~]# chown -R nginx.nginx /var/log/nginx
# 下載nginx
[root@localhost ~]# cd /usr/src/
[root@localhost src]# wget http://nginx.org/download/nginx-1.12.0.tar.gz
# 編譯安裝
[root@localhost src]# ls
debug kernels nginx-1.12.0.tar.gz
[root@localhost src]# tar xf nginx-1.12.0.tar.gz
[root@localhost src]# cd nginx-1.12.0
[root@localhost nginx-1.12.0]# ./configure \
--prefix=/usr/local/nginx \
--user=nginx \
--group=nginx \
--with-debug \
--with-http_ssl_module \
--with-http_realip_module \
--with-http_image_filter_module \
--with-http_gunzip_module \
--with-http_gzip_static_module \
--with-http_stub_status_module \
--http-log-path=/var/log/nginx/access.log \
--error-log-path=/var/log/nginx/error.log
[root@localhost nginx-1.12.0]# make -j $(grep 'processor' /proc/cpuinfo | wc -l) && make install
# 配置環境變數
[root@localhost ~]# echo 'export PATH=/usr/local/nginx/sbin:$PATH' > /etc/profile.d/nginx.sh
[root@localhost ~]# . /etc/profile.d/nginx.sh
# 啟動nginx
[root@localhost ~]# nginx
[root@localhost ~]# ss -anlt
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 0.0.0.0:80 0.0.0.0:*
LISTEN 0 128 0.0.0.0:22 0.0.0.0:*
LISTEN 0 128 [::]:22 [::]:*
# 寫service檔案讓nginx開機自啟
[root@localhost ~]# cat > /usr/lib/systemd/system/nginx.service <<EOF
[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
EOF
[root@localhost ~]# systemctl daemon-reload
[root@localhost ~]# systemctl enable --now nginx
Created symlink /etc/systemd/system/multi-user.target.wants/nginx.service → /usr/lib/systemd/system/nginx.service.
Job for nginx.service failed because the control process exited with error code.
See "systemctl status nginx.service" and "journalctl -xe" for details.

nginx的組態檔詳解
主組態檔:/usr/local/nginx/conf/nginx.conf
- 默認啟動nginx時,使用的組態檔是:安裝路徑/conf/nginx.conf檔案
- 可以在啟動nginx時通過-c選項來指定要讀取的組態檔
nginx常見的組態檔及其作用
| 組態檔 | 作用 |
|---|---|
| nginx.conf | nginx的基本組態檔 |
| mime.types | MIME型別關聯的擴展檔案 |
| fastcgi.conf | 與fastcgi相關的配置 |
| proxy.conf | 與proxy相關的配置 |
| sites.conf | 配置nginx提供的網站,包括虛擬主機 |
nginx.conf的內容分為以下幾段:
- main配置段:全域配置段,其中main配置段中可能包含event配置段
- event {}:定義event模型作業特性
- http {}:定義http協議相關的配置
配置指令:要以分號結尾,語法格式如下:
derective value1 [value2 ...];
支持使用變數:
- 內置變數:模塊會提供內建變數定義
- 自定義變數:set var_name value
用于除錯、定位問題的配置引數
是否以守護行程方式運行Nginx
守護行程(daemon)是脫離終端并且在后臺運行的行程,它脫離終端是為了避免行程執行程序中的資訊在任何終端上顯示,這樣一來,行程也不會被任何終端所產生的資訊所打斷,Nginx毫無疑問是一個需要以守護行程方式運行的服務,因此,默認都是以這種方式運行的,
daemon {on|off}; //是否以守護行程方式運行nginx,除錯時應設定為off
master_process {on|off}; //是否以master/worker模型來運行nginx,除錯時可以設定為off
error_log 位置 級別; //配置錯誤日志
[root@localhost ~]# vim /usr/local/nginx/conf/nginx.conf
#user nobody;
worker_processes 1;
daemon off;
[root@localhost ~]# nginx -s stop;nginx
正常運行必備的配置引數
不過Nginx還是提供了關閉守護行程的模式,之所以提供這種模式,是為了方便跟蹤除錯Nginx,畢竟用gdb除錯行程時最煩瑣的就是如何繼續跟進fork出的子行程了,
# user USERNAME [GROUPNAME] //指定允許worker行程的用戶和組
[root@localhost ~]# vim /usr/local/nginx/conf/nginx.conf
user nginx nginx;
# pid /path/to/pid_file //指定nginx守護行程的pid檔案
[root@localhost ~]# vim /usr/local/nginx/conf/nginx.conf
pid logs/nginx.pid;
[root@localhost ~]# ls /usr/local/nginx/logs/
nginx.pid
[root@localhost ~]# systemctl stop nginx.service
[root@localhost ~]# ls /usr/local/nginx/logs/
# worker_rlimit_nofile number //設定所有woker行程最大可以打開的檔案數,默認1024
# worker_rlimit_core size //指明所有worker行程所能夠使用的總體的最大核心檔案大小,保持默認即可
優化性能的配置引數
worker_processes n; //啟動n個worker行程,這里的n為了避免背景關系切換,通常設定為cpu總核心數-1或等于總核心數
worker_cpu_affinity cpumask ...; //將行程系結到某cpu中,避免頻繁重繪快取
//cpumask:使用8位二進制表示cpu核心,如:
0000 0001 //第一顆cpu核心
0000 0010 //第二顆cpu核心
0000 0100 //第三顆cpu核心
0000 1000 //第四顆cpu核心
0001 0000 //第五顆cpu核心
0010 0000 //第六顆cpu核心
0100 0000 //第七顆cpu核心
1000 0000 //第八顆cpu核心
#查看cpu
[root@localhost ~]# vim /usr/local/nginx/conf/nginx.conf
worker_processes 3;
worker_cpu_affinity 0001 0010 0100;
[root@localhost ~]# systemctl restart nginx.service
[root@localhost ~]# ps -ef | grep nginx
root 1571 1 0 23:13 ? 00:00:00 nginx: master process /usr/local/nginx/sbin/nginx
nginx 1572 1571 0 23:13 ? 00:00:00 nginx: worker process
nginx 1573 1571 0 23:13 ? 00:00:00 nginx: worker process
nginx 1574 1571 0 23:13 ? 00:00:00 nginx: worker process
root 1576 1485 0 23:13 pts/0 00:00:00 grep --color=auto nginx
[root@localhost ~]# top
top - 23:31:29 up 22 min, 1 user, load average: 0.00, 0.00, 0.00
Tasks: 223 total, 1 running, 222 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
MiB Mem : 3752.0 total, 3300.8 free, 216.8 used, 234.4 buff/cache
MiB Swap: 4044.0 total, 4044.0 free, 0.0 used. 3305.5 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1 root 20 0 242256 10628 8180 S 0.0 0.3 0:00.92 systemd
2 root 20 0 0 0 0 S 0.0 0.0 0:00.00 kthreadd
3 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 rcu_gp
#按shift+f ,輸入nginx,回車
Locate string nginx
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1485 root 20 0 26516 4928 3452 S 0.0 0.1 0:00.03 bash
1571 root 20 0 80256 1092 56 S 0.0 0.0 0:00.00 nginx
1572 nginx 20 0 111708 6276 4700 S 0.0 0.2 0:00.00 nginx
1573 nginx 20 0 111708 6276 4700 S 0.0 0.2 0:00.00 nginx
1574 nginx 20 0 111708 6276 4700 S 0.0 0.2 0:00.00 nginx
# 按f, 將游標移到 P = Last Used Cpu (SMP)
Fields Management for window 1:Def, whose current sort field is %CPU
Navigate with Up/Dn, Right selects for move then <Enter> or Left commits,
'd' or <Space> toggles display, 's' sets sort. Use 'q' or <Esc> to end!
* PID = Process Id WCHAN = Sleeping in Function
* USER = Effective User Name Flags = Task Flags <sched.h>
* PR = Priority CGROUPS = Control Groups
* NI = Nice Value SUPGIDS = Supp Groups IDs
* VIRT = Virtual Image (KiB) SUPGRPS = Supp Groups Names
* RES = Resident Size (KiB) TGID = Thread Group Id
* SHR = Shared Memory (KiB) OOMa = OOMEM Adjustment
* S = Process Status OOMs = OOMEM Score current
* %CPU = CPU Usage ENVIRON = Environment vars
* %MEM = Memory Usage (RES) vMj = Major Faults delta
* TIME+ = CPU Time, hundredths vMn = Minor Faults delta
* COMMAND = Command Name/Line USED = Res+Swap Size (KiB)
PPID = Parent Process pid nsIPC = IPC namespace Inode
UID = Effective User Id nsMNT = MNT namespace Inode
RUID = Real User Id nsNET = NET namespace Inode
RUSER = Real User Name nsPID = PID namespace Inode
SUID = Saved User Id nsUSER = USER namespace Inode
SUSER = Saved User Name nsUTS = UTS namespace Inode
GID = Group Id LXC = LXC container name
GROUP = Group Name RSan = RES Anonymous (KiB)
PGRP = Process Group Id RSfd = RES File-based (KiB)
TTY = Controlling Tty RSlk = RES Locked (KiB)
TPGID = Tty Process Grp Id RSsh = RES Shared (KiB)
SID = Session Id CGNAME = Control Group name
nTH = Number of Threads NU = Last Used NUMA node
P = Last Used Cpu (SMP)
TIME = CPU Time
SWAP = Swapped Size (KiB)
CODE = Code Size (KiB)
DATA = Data+Stack (KiB)
nMaj = Major Page Faults
nMin = Minor Page Faults
nDRT = Dirty Pages Count
# 空格選擇,按q
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND P
1571 root 20 0 80256 1092 56 S 0.0 0.0 0:00.00 nginx 2
1572 nginx 20 0 111708 6276 4700 S 0.0 0.2 0:00.00 nginx 0
1573 nginx 20 0 111708 6276 4700 S 0.0 0.2 0:00.00 nginx 1
1574 nginx 20 0 111708 6276 4700 S 0.0 0.2 0:00.00 nginx 2
timer_resolution interval; //計時器決議度,降低此值,可減少gettimeofday()系統呼叫的次數
worker_priority number; //指明worker行程的nice值 number取19~-20,數值越低優先級越高
[root@localhost ~]# vim /usr/local/nginx/conf/nginx.conf
worker_priority -20;
[root@localhost ~]# systemctl restart nginx.service
[root@localhost ~]# ps -elf |grep nginx
1 S root 1750 1 0 80 0 - 20064 - 00:21 ? 00:00:00 nginx: master process /usr/local/nginx/sbin/nginx
5 S nginx 1751 1750 0 60 -20 - 27927 do_epo 00:21 ? 00:00:00 nginx: worker process
5 S nginx 1752 1750 0 60 -20 - 27927 do_epo 00:21 ? 00:00:00 nginx: worker process
5 S nginx 1753 1750 0 60 -20 - 27927 do_epo 00:21 ? 00:00:00 nginx: worker process
0 S root 1756 1485 0 80 0 - 3086 - 00:22 pts/0 00:00:00 grep --color=auto nginx
事件相關的配置:event{}段中的配置引數
accept_mutex {off|on}; //master調度用戶請求至各worker行程時使用的負載均衡鎖;on表示能讓多個worker輪流地、序列化地去回應新請求
lock_file file; //accept_mutex用到的互斥鎖鎖檔案路徑
use [epoll | rtsig | select | poll]; //指明使用的事件模型,建議讓nginx自行選擇
worker_connections #; //每個行程能夠接受的最大連接數
[root@localhost ~]# vim /usr/local/nginx/conf/nginx.conf
events {
worker_connections 10240;
}
[root@localhost ~]# dnf -y install httpd-tools
[root@localhost ~]# ab -n 3000 http://192.168.8.132/index.html
This is ApacheBench, Version 2.3 <$Revision: 1843412 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking 192.168.8.132 (be patient)
Completed 300 requests
Completed 600 requests
Completed 900 requests
Completed 1200 requests
Completed 1500 requests
Completed 1800 requests
Completed 2100 requests
Completed 2400 requests
Completed 2700 requests
Completed 3000 requests
Finished 3000 requests
Server Software: nginx/1.20.1
Server Hostname: 192.168.111.141
Server Port: 80
Document Path: /index.html
Document Length: 612 bytes
Concurrency Level: 1
Time taken for tests: 0.376 seconds
Complete requests: 3000
Failed requests: 0
Total transferred: 2535000 bytes
HTML transferred: 1836000 bytes
Requests per second: 7974.21 [#/sec] (mean)
Time per request: 0.125 [ms] (mean)
Time per request: 0.125 [ms] (mean, across all concurrent requests)
Transfer rate: 6580.28 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.0 0 0
Processing: 0 0 0.0 0 1
Waiting: 0 0 0.0 0 1
Total: 0 0 0.0 0 1
Percentage of the requests served within a certain time (ms)
50% 0
66% 0
75% 0
80% 0
90% 0
95% 0
98% 0
99% 0
100% 1 (longest request)
網路連接相關的配置引數
keepalive_timeout number; //長連接的超時時長,默認為65s
keepalive_requests number; //在一個長連接上所能夠允許請求的最大資源數
keepalive_disable [msie6|safari|none]; //為指定型別的UserAgent禁用長連接
tcp_nodelay on|off; //是否對長連接使用TCP_NODELAY選項,為了提升用戶體驗,通常設為on
client_header_timeout number; //讀取http請求報文首部的超時時長
client_body_timeout number; //讀取http請求報文body部分的超時時長
send_timeout number; //發送回應報文的超時時長
fastcgi的相關配置引數
# LNMP: php需啟用fpm模型
location ~ \.php$ {
root html;
fastcgi_pass 127.0.0.1:9000; //定義反向代理
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; //.php檔案路徑
include fastcgi_params;
}
nginx.conf組態檔案例
更改默認埠號以及行程數和指定特定組態檔
[root@localhost conf]# head nginx.conf
#user nobody;
worker_processes 1;
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid logs/nginx.pid;
// 使用80埠
server {
listen 80;
server_name localhost;
// 使用源檔案運行行程數如下
[root@localhost conf]# ps -ef | grep nginx
root 257815 1 0 16:46 ? 00:00:00 nginx: master process /usr/local/nginx/sbin/nginx
nginx 257816 257815 0 16:46 ? 00:00:00 nginx: worker process
root 258199 102060 0 16:46 pts/0 00:00:00 grep --color=auto nginx
// 將源檔案以及mime.types檔案copy一份到/opt目錄中
[root@localhost conf]# cp nginx.conf /opt/
[root@localhost conf]# cp mime.types /opt/
[root@localhost conf]# cd /opt/
[root@localhost opt]# ls
mime.types nginx.conf
[root@localhost opt]# nginx -t -c /opt/nginx.conf
nginx: the configuration file /opt/nginx.conf syntax is ok
nginx: configuration file /opt/nginx.conf test is successful
// 修改 worker_rlimit_nofile number; 引數為4
#user nobody;
worker_processes 4;
server {
listen 8070;
server_name localhost;
使用nginx服務控制命令重啟并指定組態檔路徑
[root@localhost opt]# nginx -s stop;nginx -c /opt/nginx.conf
[root@localhost ~]# ss -antl
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 0 128 0.0.0.0:22 0.0.0.0:*
LISTEN 0 128 0.0.0.0:8070 0.0.0.0:*
LISTEN 0 128 [::]:22 [::]:*
[root@localhost ~]# ps -ef | grep nginx
root 276931 1 0 16:56 ? 00:00:00 nginx: master process nginx -c /opt/nginx.conf
nginx 276932 276931 0 16:56 ? 00:00:00 nginx: worker process
nginx 276933 276931 0 16:56 ? 00:00:00 nginx: worker process
nginx 276934 276931 0 16:56 ? 00:00:00 nginx: worker process
nginx 276935 276931 0 16:56 ? 00:00:00 nginx: worker process
root 283466 276242 0 16:58 pts/2 00:00:00 grep --color=auto nginx
報錯

解決方法
[root@localhost nginx-1.12.0]# vim objs/Makefile
CFLAGS = -pipe -O -W -Wall -Wpointer-arith -Wno-unused-parameter -Werrori -g
// 找到 -Werrori 后將其去掉

[root@localhost nginx-1.12.0]# vim src/os/unix/ngx_user.c
#ifdef __GLIBC__
/* work around the glibc bug */
cd.current_salt[0] = ~salt[0];
#endif
// 把cd.current_salt[0] = ~salt[0];前后加上/* cd.current_salt[0] = ~salt[0];*/
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/337660.html
標籤:其他
上一篇:某網路公司面試技術題匯總
