本篇來聊聊Nginx/OpenResty詳解,Nginx的基礎(chǔ)配置吧
Nginx的基礎(chǔ)配置
本節(jié)介紹Nginx的基礎(chǔ)配置,包括事件模型配置、虛擬主機配置、錯誤頁面配置、長連接配置、訪問日志配置等。然后,本節(jié)還會介紹在配置過程中可能會使用到的Nginx內(nèi)置變量。

events事件驅(qū)動配置
一個典型的events事件模型配置塊的示例如下:
events {
use epoll; #使用epoll類型IO多路復(fù)用模型
worker_connections 204800; #最大連接數(shù)限制為20萬
accept_mutex on; #各個Worker通過鎖來獲取新連接
}1.worker_connections指令
worker_connections指令用于配置每個Worker進程能夠打開的最大并發(fā)連接數(shù)量,指令參數(shù)為連接數(shù)的上限。
順便說一下,配置文件中的符號“#”是注釋符號,后邊的字符串起到注釋說明的作用。
2.use指令
use指令用于配置IO多路復(fù)用模型,有多種模型可配置,常用的有select、epoll兩種。
Linux系統(tǒng)下,select類型IO多路復(fù)用模型有兩個較大的缺陷:缺陷之一,單服務(wù)進程并發(fā)數(shù)不夠,默認(rèn)最大的客戶端連接數(shù)為1024/2048,因為Linux系統(tǒng)一個進程所打開的FD文件描述符是有限制的,由FD_SETSIZE設(shè)置,默認(rèn)值是1024/2048,因此select模型的最大并發(fā)數(shù)被相應(yīng)限制了;缺陷之二,性能問題,每次IO事件查詢都會線性掃描全部的FD集合,連接數(shù)越大,性能越會線性下降??傊?,select類型IO多路復(fù)用模型的性能是不高的。使用Nginx的目標(biāo)之一是為了高性能和高并發(fā)。所以,在Linux系統(tǒng)下建議使用epoll類型的IO多路復(fù)用模型。epoll模型是在Linux 2.6內(nèi)核中實現(xiàn)的,是select系統(tǒng)調(diào)用的增強版本。epoll模型中有專門的IO就緒隊列,不再像select模型一樣進行全體連接掃描,時間復(fù)雜度從select模型的O(n)下降到了O(1)。在IO事件的查詢效率上,無論上百萬連接還是數(shù)十個連接,對于epoll模型而言差距是不大的;而對select模型而言,效率的差距就非常巨大了。
select、epoll都是常見的IO多路復(fù)用模型。本質(zhì)上都是查詢多個FD描述符,一旦某個描述符的IO事件就緒(一般是讀就緒或者寫就緒),就進行相應(yīng)的讀寫操作,而且都是在讀寫事件就緒后,應(yīng)用程序自己負(fù)責(zé)進行讀寫。所以,select、epoll本質(zhì)上都是同步I/O,因為它們的讀寫過程是阻塞的。雖然不是異步I/O,但是通過合理的設(shè)計,epoll類型的IO多路復(fù)用模型的性能還是非常高,足以應(yīng)對目前的高并發(fā)處理要求。
如果沒有配置IO多路復(fù)用模型,在Windows平臺下,Nginx默認(rèn)的IO多路復(fù)用模型為select。這一點可以通過設(shè)置errors_log的日志級別為debug,打開日志文件可以看出來,具體如下:
... [notice] 3928#18648: using the "select" event method
... [notice] 3928#18648: openresty/1.13.6.2至于Nginx在Linux平臺上默認(rèn)的事件驅(qū)動模型,大家可按照統(tǒng)一的方法自行實驗。
3.accept_mutex指令
accept_mutex指令用于配置各個Worker進程是否通過互斥鎖有序接收新的連接請求。on參數(shù)表示各個Worker通過互斥鎖有序接收新請求;off參數(shù)指每個新請求到達(dá)時會通知(喚醒)所有的Worker進程參與爭搶,但只有一個進程可獲得連接。
配置off參數(shù)會造成“驚群”問題影響性能。accept_mutex指令的參數(shù)默認(rèn)為on。

虛擬主機配置
配置虛擬主機可使用server指令。虛擬主機的基礎(chǔ)配置包含套接字配置、虛擬主機名稱配置等。
1.虛擬主機的監(jiān)聽套接字配置
虛擬主機的監(jiān)聽套接字配置使用listen指令,具體的配置有多種形
式,分別說明如下:
(1)使用listen指令直接配置監(jiān)聽端口。
server {
listen 80;
...
}(2)使用listen指令配置監(jiān)聽的IP和端口。
server {
listen 127.0.0.1:80;
...
}2.虛擬主機名稱配置
虛擬主機名稱配置可使用server_name指令。基于微服務(wù)架構(gòu)的分布式平臺有很多類型的服務(wù),比如文件服務(wù)、后臺服務(wù)、基礎(chǔ)服務(wù)等。
很多情況下,可以通過域名前綴的方式進行URL路徑區(qū)分,演示實例如下:
后臺管理服務(wù)虛擬主機#后臺管理服務(wù)虛擬主機demo
server {
listen 80;
server_name admin.crazydemo.com; #后臺管理服務(wù)的域名前綴為admin
location / {
default_type 'text/html';
charset utf-8;
echo "this is admin server";
}
}
#文件服務(wù)虛擬主機demo
server {
listen 80;
server_name file.crazydemo.com; #文件服務(wù)的域名前綴為admin
location / {
default_type 'text/html';
charset utf-8;
echo "this is file server";
}
}
#默認(rèn)服務(wù)虛擬主機demo
server {
listen 80 default;
server_name crazydemo.com *.crazydemo.com;#如果沒有前綴,這就是默認(rèn)訪問的虛擬主機
location / {
default_type 'text/html';
charset utf-8;
echo "this is default server";
}
...
}當(dāng)然,客戶端需要能夠通過域名服務(wù)器或者本地的hosts文件解析出域名所對應(yīng)的服務(wù)器IP,HTTP請求才能最終到達(dá)Nginx服務(wù)器。故為了訪問上面配置的3個虛擬主機,修改Windows系統(tǒng)本地的hosts文件,加上以下幾條映射規(guī)則:
127.0.0.1 crazydemo.com #基礎(chǔ)服務(wù)域名
127.0.0.1 file.crazydemo.com #文件服務(wù)域名
127.0.0.1 admin.crazydemo.com #后臺管理服務(wù)域名
127.0.0.1 xxx.crazydemo.com #XXX服務(wù)重啟Nginx,在瀏覽器中訪問
http://admin.crazydemo.com/,返回的內(nèi)容如圖7-11所示。

圖7-11 多個虛擬主機配置之后的訪問結(jié)果
多個虛擬主機之間,匹配優(yōu)先級從高到低大致如下:
(1)字符串精確匹配:如果請求的域名為admin.crazydemo.com,那么首先會匹配到名稱為admin.crazydemo.com的虛擬管理主機。
(2)左側(cè)*通配符匹配:若瀏覽器請求的域名為xxx.crazydemo.com,則會匹配到*.crazydemo.com虛擬主機。為什么呢?因為配置文件中并沒有server_name為xxx.crazydemo.com的主機,所以退而求其次,名稱為*.crazydemo.com的虛擬主機按照通配符規(guī)則匹配成功。
(3)右側(cè)*通配符匹配:右側(cè)*通配符和左側(cè)*通配符匹配類似,只不過優(yōu)先級低于左側(cè)*通配符匹配。
(4)正則表達(dá)式匹配:與通配符匹配類似,不過優(yōu)先級更低。
(5)default_server:在listen指令后面如果帶有default的指令參數(shù),就代表這是默認(rèn)的、最后兜底的虛擬主機,如果前面的匹配規(guī)則都沒有命中,就只能命中default_server指定的默認(rèn)主機。

錯誤頁面配置
錯誤頁面的配置指令為error_page,格式如下:
error_page code ... [=[response]] uri;code表示響應(yīng)碼,可以同時配置多個;uri表示錯誤頁面,一般為服務(wù)器上的靜態(tài)資源頁面。
例如,下面的例子分別為404、500等錯誤碼設(shè)置了錯誤頁面,具體設(shè)置如下:
#后臺管理服務(wù)器demo
server {
listen 80;
server_name admin.crazydemo.com;
root /var/www/;
location / {
default_type 'text/html';
charset utf-8;
echo "this is admin server";
}
#設(shè)置錯誤頁面
error_page 404 /404.html;
#設(shè)置錯誤頁面
error_page 500 502 503 504 /50x.html;
}為了防止404頁面被劫持,也就是被前面的代理服務(wù)器換掉,則可以修改響應(yīng)狀態(tài)碼,參考如下:
error_page 404 =200 /404.html #防止404頁面被劫持error_page指令除了可用于server上下文外,還可用于http、server、location、if in location等上下文。
?長連接相關(guān)配置
配置長連接的有效時長可使用keepalive_timeout指令,格式如下:
keepalive_timeout timeout [header_timeout];配置項中的timeout參數(shù)用于設(shè)置保持連接超時時長,0表示禁止長連接,默認(rèn)為75秒。
如果要配置長連接的一條連接允許的最大請求數(shù),那么可以使用keepalive_requests指令,格式如下:
keepalive_requests number;配置項中的number參數(shù)用于設(shè)置在一條長連接上允許被請求的資源的最大數(shù)量,默認(rèn)為100。
如果要配置向客戶端發(fā)送響應(yīng)報文的超時限制,那么可以使用下面的指令:
send_timeout time;配置項中的time參數(shù)用于設(shè)置Nginx向客戶端發(fā)送響應(yīng)報文的超時限制,此處時長是指兩次向客戶端寫操作之間的間隔時長,并非整個響應(yīng)過程的傳輸時長。
訪問日志配置
Nginx將客戶端的訪問日志信息記錄到指定的日志文件中,用于后期分析用戶的瀏覽行為等,此功能由ngx_http_log_module模塊負(fù)責(zé),其指令在HTTP處理流程的log階段執(zhí)行。
訪問記錄配置指令的完整格式如下:
access_log path [format [buffer=size] [gzip[=level]] [flush=time] [if=condition]];其中,path表示日志文件的本地路徑;format表示日志輸出的格式名稱。定義日志輸出格式的配置指令為log_format,它的完整格式如下:
log_format name string ...;其中,name參數(shù)用于指定格式名稱;string參數(shù)用于設(shè)置格式字符串,可以有多個。字符串中可以使用Nginx核心模塊及其他模塊的內(nèi)置變量。
下面是一個比較完整的例子:
http {
#先定義日志格式,format_main是日志格式的名字
log_format format_main '$remote_addr - $remote_user [$time_local] $request - ' ' $status - $body_bytes_sent [$http_referer]
#配置:日志文件、訪問日志格式
access_log logs/access_main.log format_main;
...
}修改配置后,需要重啟Nginx。然后在瀏覽器中訪問
http://crazydemo.com/demo/hello,在access_main.log文件中可以看到一條新增的日志記錄:
127.0.0.1 - - [12/Jan/2020:18:32:28 +0800] GET /demo/hello HTTP/1.1 - 200 - 32 [-] [Mozilla/5.0 (Windows NT 10.0; Win64; x64; r接下來,對以上實例中所有用到的Nginx內(nèi)置變量進行簡單說明,具體如下:
(1)$request:記錄用戶的HTTP請求的起始行信息。
(2)$status:記錄HTTP狀態(tài)碼,即請求返回的狀態(tài),例如200、404、502等。
(3)$remote_addr:記錄訪問網(wǎng)站的客戶端地址。
(4)$remote_user:記錄遠(yuǎn)程客戶端用戶名稱。(5)$time_local:記錄訪問時間與時區(qū)。
(6)$body_bytes_sent:記錄服務(wù)器發(fā)送給客戶端的響應(yīng)body字節(jié)數(shù)。
(7)$http_referer:記錄此次請求是從哪個鏈接訪問過來的,可以根據(jù)其進行盜鏈的監(jiān)測。
(8)$http_user_agent:記錄客戶端訪問信息,如瀏覽器、手機客戶端等。
(9)$http_x_forwarded_for:當(dāng)前端有正向代理服務(wù)器時,此參數(shù)用于保持客戶端真實的IP地址。
該參數(shù)生效的前提:前端的代理服務(wù)器上進行了相關(guān)的x_forwarded_for設(shè)置。
?Nginx核心模塊內(nèi)置變量
Nginx核心模塊ngx_http_core_module中定義了一系列存儲HTTP請求信息的變量,例如$http_user_agent、$http_cookie等。這些內(nèi)置變量在Nginx配置過程中使用較多,故對其進行介紹,具體如下:
(1)$arg_PARAMETER:請求URL中以PARAMETER為名稱的參數(shù)值。
請求參數(shù)即URL的“?”號后面的name=value形式的參數(shù)對,變量$arg_name得到的值為value。
另外,$arg_PARAMETER中的參數(shù)名稱不區(qū)分字母大小寫,例如通過變量$arg_name不僅可以匹配name參數(shù),也可以匹配NAME、Name請求參數(shù),Nginx會在匹配參數(shù)名之前自動把原始請求中的參數(shù)名調(diào)整為全部小寫的形式。
(2)$args:請求URL中的整個參數(shù)串,其作用與$query_string相同。
(3)$binary_remote_addr:二進制形式的客戶端地址。
(4)$body_bytes_sent:傳輸給客戶端的字節(jié)數(shù),響應(yīng)頭不計算在內(nèi)。
(5)$bytes_sent:傳輸給客戶端的字節(jié)數(shù),包括響應(yīng)頭和響應(yīng)體。
(6)$content_length:等同于$http_content_length,用于獲取請求體body的大小,指的是Nginx從客戶端收到的請求頭中ContentLength字段的值,不是發(fā)送給客戶端響應(yīng)中的Content-Length字段值,如果需要獲取響應(yīng)中的Content-Length字段值,就使用$sent_http_content_length變量。
(7)$request_length:請求的字節(jié)數(shù)(包括請求行、請求頭和請求體)。注意,由于$request_length是請求解析過程中不斷累加的,如果解析請求時出現(xiàn)異常,那么$request_length是已經(jīng)累加部分的長度,并不是Nginx從客戶端收到的完整請求的總字節(jié)數(shù)(包括請求行、請求頭、請求體)。
(8)$connection:TCP連接的序列號。
(9)$connection_requests:TCP連接當(dāng)前的請求數(shù)量。
(10)$content_type:請求中的Content-Type請求頭字段值。
(11)$cookie_name:請求中名稱name的cookie值。
(12)$document_root:當(dāng)前請求的文檔根目錄或別名。
(13)$uri:當(dāng)前請求中的URI(不帶請求參數(shù),參數(shù)位于$args變量)。$uri變量值不包含主機名,如“/foo/bar.html”。此參數(shù)可以修改,可以通過內(nèi)部重定向。
(14)$request_uri:包含客戶端請求參數(shù)的原始URI,不包含主機名,此參數(shù)不可以修改,例如“/foo/bar.html?name=value”。
(15)$host:請求的主機名。優(yōu)先級為:HTTP請求行的主機名>HOST請求頭字段>符合請求的服務(wù)器名。
(16)$http_name:名稱為name的請求頭的值。如果實際請求頭name中包含中畫線“-”,那么需要將中畫線“-”替換為下畫線“_”;如果實際請求頭name中包含大寫字母,那么可以替換為小寫字
母。例如獲取Accept-Language請求頭的值,變量名稱為
$http_accept_language。
(17)$msec:當(dāng)前的UNIX時間戳。UNIX時間戳是從1970年1月1日
(UTC/GMT的午夜)開始所經(jīng)過的秒數(shù),不考慮閏秒。
(18)$nginx_version:獲取Nginx版本。
(19)$pid:獲取Worker工作進程的PID。
(20)$proxy_protocol_addr:代理訪問服務(wù)器的客戶端地址,如果是直接訪問,那么該值為空字符串。
(21)$realpath_root:當(dāng)前請求的文檔根目錄或別名的真實路徑,會將所有符號連接轉(zhuǎn)換為真實路徑。
(22)$remote_addr:客戶端請求地址。
(23)$remote_port:客戶端請求端口。
(24)$request_body:客戶端請求主體。此變量可在location中使用,將請求主體通過proxy_pass、fastcgi_pass、uwsgi_pass和scgi_pass傳遞給下一級的代理服務(wù)器。
(25)$request_completion:如果請求成功,那么值為OK;如果請求未完成或者請求不是一個范圍請求的最后一部分,那么值為空。
(26)$request_filename:當(dāng)前請求的文件路徑,由root或alias指令與URI請求結(jié)合生成。(27)$request_length:請求的長度,包括請求的地址、HTTP請求頭和請求主體。
(28)$request_method:HTTP請求方法,比如GET或POST等。
(29)$request_time:處理客戶端請求使用的時間,從讀取客戶端的第一個字節(jié)開始計時。
(30)$scheme:請求使用的Web協(xié)議,如HTTP或HTTPS。
(31)$sent_http_name:設(shè)置任意名稱為name的HTTP響應(yīng)頭字段。例如,如果需要設(shè)置響應(yīng)頭Content-Length,那么將“-”替換為下畫線,大寫字母替換為小寫字母,變量為$sent_http_content_length。
(32)$server_addr:服務(wù)器端地址為了避免訪問操作系統(tǒng)內(nèi)核,應(yīng)將IP地址提前設(shè)置在配置文件中。
(33)$server_name:虛擬主機的服務(wù)器名,如crazydemo.com。
(34)$server_port:虛擬主機的服務(wù)器端口。
(35)$server_protocol:服務(wù)器的HTTP版本,通常為HTTP/1.0或HTTP/1.1。
(36)$status:HTTP響應(yīng)代碼。
本文給大家講解的內(nèi)容是Nginx/OpenResty詳解,Nginx的基礎(chǔ)配置
下篇文章給大家講解的是 Nginx/OpenResty詳解,location路由規(guī)則配置詳解;
覺得文章不錯的朋友可以轉(zhuǎn)發(fā)此文關(guān)注小編;
感謝大家的支持!
本文就是愿天堂沒有BUG給大家分享的內(nèi)容,大家有收獲的話可以分享下,想學(xué)習(xí)更多的話可以到微信公眾號里找我,我等你哦。
