nginx
(發音同engine x)是一款輕量級的Web伺服器/反向代理伺服器及電子郵件(IMAP/POP3)代理伺服器,並在一個BSD-like協定下發行。
nginx
由俄羅斯的程式設計師Igor Sysoev所開發,最初供俄國大型的入口網站及搜尋引擎Rambler使用。
第一個公開版本0.1.0發佈於2004年10月4日。其將原始碼以類BSD許可證的形式發佈,因它的穩定性、豐富的功能集、範例組態檔和低系統資源的消耗而聞名。2011年6月1日,nginx 1.0.4發佈。
nginx
的特點是佔有記憶體少,併發能力強,事實上nginx
的併發能力確實在同類型的網頁伺服器中表現較好,中國大陸使用nginx
網站使用者有:百度、京東、新浪、網易、騰訊、淘寶等。
nginx
是一個很牛的高效能Web和反向代理伺服器,它具有很多非常優越的特性:
nginx
由內核和模組組成。其中,內核的設計非常微小和簡潔,完成的工作也非常簡單,僅僅通過查詢組態檔將用戶端請求對映到一個location block(location是nginx設定中的一個指令,用於URL匹配),而在這個location中所設定的每個指令將會啓動不同的模組去完成相應的工作。
nginx的模組從結構上分爲核心模組、基礎模組和第三方模組
使用者根據自己的需要開發的模組都屬於第三方模組。正是有瞭如此多模組的支撐,nginx的功能纔會如此強大
nginx模組從功能上分爲三類,分別是:
nginx模組分爲:核心模組、事件模組、標準Http模組、可選Http模組、郵件模組、第三方模組和修補程式等
nginx基本模組:所謂基本模組,指的是nginx預設的功能模組,它們提供的指令,允許你使用定義nginx基本功能的變數,在編譯時不能被禁用,包括:
具體的指令,請參考nginx
的官方文件
nginx
的模組直接被編譯進nginx
,因此屬於靜態編譯方式。
啓動nginx
後,nginx
的模組被自動載入,與Apache
不一樣,首先將模組編譯爲一個so檔案,然後在組態檔中指定是否進行載入。
在解析組態檔時,nginx
的每個模組都有可能去處理某個請求,但是同一個處理請求只能由一個模組來完成。
nginx
的進程架構:
啓動nginx
時,會啓動一個Master
進程,這個進程不處理任何用戶端的請求,主要用來產生worker
執行緒,一個worker
執行緒用來處理n個request
。
下圖展示了nginx
模組一次常規的HTTP請求和響應的過程
下圖展示了基本的WEB服務請求步驟
//安裝依賴包
[root@longnian ~]# yum -y install pcre-devel openssl openssl-devel gd-devel gcc gcc-c++ wget
[root@longnian ~]# yum -y groups mark install 'Development Tools'
Loaded plugins: fastestmirror
There is no installed groups file.
Maybe run: yum groups mark convert (see man yum)
Loading mirror speeds from cached hostfile
Marked install: Development Tools
//建立系統使用者nginx
[root@longnian ~]# useradd -r -M -s /sbin/nologin nginx
[root@longnian ~]# id nginx
uid=996(nginx) gid=994(nginx) groups=994(nginx)
//建立日誌存放目錄
[root@longnian ~]# mkdir -p /var/log/nginx
[root@longnian ~]# chown -R nginx.nginx /var/log/nginx
//下載nginx並安裝
[root@longnian ~]# wget http://nginx.org/download/nginx-1.18.0.tar.gz
[root@longnian src]# tar xf nginx-1.18.0.tar.gz
[root@longnian src]# cd nginx-1.18.0
[root@longnian nginx-1.18.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@longnian nginx-1.18.0]# make -j $(grep 'processor' /proc/cpuinfo | wc -l) && make install
//設定環境變數
[root@longnian ~]# echo 'export PATH=/usr/local/nginx/sbin:$PATH' > /etc/profile.d/nginx.sh
[root@longnian ~]# source /etc/profile.d/nginx.sh
[root@longnian ~]# ss -anlt
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 *:80 *:*
LISTEN 0 128 *:22 *:*
LISTEN 0 128 :::22 :::*
LISTEN 0 100 ::1:25
存取網頁
主組態檔:/usr/local/nginx/conf/nginx.conf
nginx
常見的組態檔及其作用
組態檔 | 作用 |
---|---|
nginx.conf | nginx的基本組態檔 |
mime.types | MIME型別關聯的擴充套件檔案 |
fastcgi.conf | 與fastcgi相關的設定 |
proxy.conf | 與proxy相關的設定 |
sites.conf | 設定nginx提供的網站,包括虛擬主機 |
nginx.conf的內容分爲以下幾段:
設定指令:要以分號結尾,語法格式如下:
derective value1 [value2 ...];
支援使用變數:
set var_name value
daemon {on|off}; //是否以守護行程方式執行nginx,偵錯時應設定爲off
master_process {on|off}; //是否以master/worker模型來執行nginx,偵錯時可以設定爲off
error_log 位置 級別; //設定錯誤日誌
error_log裡的位置和級別能有以下可選項:
位置 | 級別 |
---|---|
file stderr syslog:server=address[,parameter=value] memory:size debug:若要使用 |
debug級別,需要在編譯nginx時使用–with-debug選項 info notice warn error crit alert emerg |
user USERNAME [GROUPNAME]; //指定執行worker進程的使用者和組
pid /path/to/pid_file; //指定nginx守護行程的pid檔案
worker_rlimit_nofile number; //設定所有worker進程最大可以開啓的檔案數,預設爲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核心
timer_resolution interval; //計時器解析度。降低此值,可減少gettimeofday()系統呼叫的次數
worker_priority number; //指明worker進程的nice值
accept_mutex {off|on}; //master排程使用者請求至各worker進程時使用的負載均衡鎖;on表示能讓多個worker輪流地、序列化地去響應新請求
lock_file file; //accept_mutex用到的互斥鎖鎖檔案路徑
use [epoll | rtsig | select | poll]; //指明使用的事件模型,建議讓nginx自行選擇
worker_connections #; //每個進程能夠接受的最大連線數
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; //發送響應報文的超時時長
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;
include fastcgi_params;
}
http{…}:設定http相關,由ngx_http_core_module模組引入。nginx的HTTP設定主要包括四個區塊,結構如下:
http {//協定級別
include mime.types;
default_type application/octet-stream;
keepalive_timeout 65;
gzip on;
upstream {//負載均衡設定
...
}
server {//伺服器級別,每個server類似於httpd中的一個<VirtualHost>
listen 80;
server_name localhost;
location / {//請求級別,類似於httpd中的<Location>,用於定義URL與本地檔案系統的對映關係
root html;
index index.html index.htm;
}
}
}
http{}段設定指令:
server {}:定義一個虛擬主機,範例如下:
server {
listen 80;
server_name www.idfsoft.com;
root "/vhosts/web";
}
listen:指定監聽的地址和埠
listen address[:port];
listen port;
server_name NAME […]; 後面可跟多個主機,名稱可使用正則表達式或萬用字元
當有多個server時,匹配順序如下:
root path;
設定資源路徑對映,用於指明請求的URL所對應的資源所在的檔案系統上的起始路徑
alias path;
用於location設定段,定義路徑別名
index file;
預設主頁面
index index.php index.html;
error_page code [...] [=code] URI | @name
根據http響應狀態碼來指明特用的錯誤頁面,例如 error_page 404 /404_customed.html
[=code]:以指定的響應碼進行響應,而不是預設的原來的響應,預設表示以新資源的響應碼爲其響應碼,例如 error_page 404 =200 /404_customed.html
log_format
定義日誌格式
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;
//注意:此處可用變數爲nginx各模組內建變數
關於location區段的詳解,請檢視這篇nginx服務之location區段匹配規則詳解
auth_basic "歡迎資訊";
auth_basic_user_file "/path/to/user_auth_file"
user_auth_file內容格式爲:
username:password
這裏的密碼爲加密後的密碼串,建議用htpasswd來建立此檔案:
htpasswd -c -m /path/to/.user_auth_file USERNAME
關於https設定和開啓狀態介面的詳解請看這篇nginx服務之設定https和監控狀態頁面
語法:rewrite regex replacement flag;
,如:
rewrite ^/images/(.*\.jpg)$ /imgs/$1 break;
此處的$1用於參照(.*.jpg)匹配到的內容,又如:
rewrite ^/bbs/(.*)$ http://www.idfsoft.com/index.html redirect;
如上例所示,replacement可以是某個路徑,也可以是某個URL
//下載一張照片,建立一個目錄存放照片
[root@localhost html]# ls
50x.html imgs index.html index.php
[root@localhost html]# cd imgs/
[root@localhost imgs]# ls
1.jpg
[root@localhost imgs]# pwd
/usr/local/nginx/html/imgs
在瀏覽器裡存取一下
設定rewrite
因爲我這裏存取是用的http://192.168.159.144/imgs/1.jpg,設定完rewrite之後,在網頁上用http://192.168.159.144/images/1.jpg也能成功存取到
設定如下:
//修改組態檔,新增rewrite
[root@localhost ~]# vim /usr/local/nginx/conf/nginx.conf
..........
location /images {
rewrite ^/images/(.*\.jpg)$ /imgs/$1 last;
}
//這裏的意思說當網頁上存取images/1.jpg的時候,會跳轉到後面imgs/1/jpg
//從而到達隱藏自己照片的路徑的目的,安全性就大大提高了
//重讀下組態檔
[root@localhost ~]# nginx -s reload
去瀏覽器存取
成功達到效果!!!
上面做的那種效果是讓存取直接跳轉到自己本地存放照片的目錄下
現在要做的是,讓存取的內容直接跳轉到網路上來存取,自己來定義網站,我這裏就讓它跳轉到百度!
設定如下:
//修改組態檔
[root@localhost ~]# vim /usr/local/nginx/conf/nginx.conf
..........
location /images {
rewrite ^/images/(.*\.jpg)$ https://www.bilibili.com/ break;
}
//重讀下組態檔
[root@localhost ~]# nginx -s reload
在瀏覽器上存取
成功跳轉!!
現在用下last的效果,在組態檔裡寫兩個,然後看看效果!!
//修改組態檔
[root@localhost ~]# vim /usr/local/nginx/conf/nginx.conf
..........
location /images {
rewrite ^/images/(.*\.jpg)$ /imgs/$1 last;
}
location /imgs {
rewrite ^/imgs/(.*\.jpg)$ https://www.bilibili.com/ last;
}
//這裏的意思是說,首先在網頁上存取images/1.jpg,這時會跳轉到本地存放照片的imgs目錄去
//然後這時因爲是存取到了imgs,然後再次跳轉,轉到了bilibili網站
[root@localhost ~]# nginx -s reload
這個存取和上面例二的效果是一樣的,只不過這裏中間通過了一次imgs的跳轉,而不是直接從images跳轉到bilibili下
常見的flag
flag | 作用 |
---|---|
last | 基本上都用這個flag,表示當前的匹配結束,繼續下一個匹配,最多匹配10個到20個 一旦此rewrite規則重寫完成後,就不再被後面其它的rewrite規則進行處理 而是由UserAgent重新對重寫後的URL再一次發起請求,並從頭開始執行類似的過程 |
break | 中止Rewrite,不再繼續匹配 一旦此rewrite規則重寫完成後,由UserAgent對新的URL重新發起請求, 且不再會被當前location內的任何rewrite規則所檢查 |
redirect | 以臨時重定向的HTTP狀態302返回新的URL |
permanent | 以永久重定向的HTTP狀態301返回新的URL |
rewrite模組的作用是用來執行URL重定向。這個機制 機製有利於去掉惡意存取的url,也有利於搜尋引擎優化(SEO)
nginx使用的語法源於Perl相容正則表達式(PCRE)庫,基本語法如下:
識別符號 | 意義 |
---|---|
^ | 必須以^後的實體開頭 |
$ | 必須以$前的實體結尾 |
. | 匹配任意字元 |
[] | 匹配指定字元集內的任意字元 |
[^] | 匹配任何不包括在指定字元集內的任意字串 |
| | 匹配 | 之前或之後的實體 |
() | 分組,組成一組用於匹配的實體,通常會有 |
捕獲子表達式,可以捕獲放在()之間的任何文字,比如:
^(hello|sir)$ //字串爲「hi sir」捕獲的結果:$1=hi$2=sir
//這些被捕獲的數據,在後面就可以當變數一樣使用了
語法:if (condition) {...}
應用場景:
常見的condition
變數名(變數值爲空串,或者以「0」開始,則爲false,其它的均爲true)
以變數爲運算元構成的比較表達式(可使用=,!=類似的比較操作符進行測試)
正則表達式的模式匹配操作
測試指定路徑爲檔案的可能性(-f,!-f)
測試指定路徑爲目錄的可能性(-d,!-d)
測試檔案的存在性(-e,!-e)
檢查檔案是否有執行許可權(-x,!-x)
if ($http_user_agent ~ Firefox) {
rewrite ^(.*)$ /firefox/$1 break;
}
if ($http_user_agent ~ MSIE) {
rewrite ^(.*)$ /msie/$1 break;
}
if ($http_user_agent ~ Chrome) {
rewrite ^(.*)$ /chrome/$1 break;
}
設定如下
//建立目錄和主頁檔案
[root@localhost html]# ls
50x.html chrome imgs firefox index.html wordpress
[root@localhost html]# cat chrome/index.html
This is chrome test page.
[root@localhost html]# cat firefox/index.html
This is Firefox test page.
//修改組態檔
[root@localhost html]# vim /usr/local/nginx/conf/nginx.conf
...........
location / {
if ($http_user_agent ~ Firefox) {
rewrite ^(.*)$ /msie/$1 break;
}
if ($http_user_agent ~ Chrome) {
rewrite ^(.*)$ /chrome/$1 break;
}
root html;
index index.php index.jsp index.html index.htm;
}
localtion /firefox {
root html;
index index.html;
}
localtion /chrome {
root html;
index index.html;
}
//重讀組態檔
[root@localhost html]# nginx -s reload
去瀏覽器存取驗證
location ~* \.(jpg|gif|jpeg|png)$ {
valid_referers none blocked www.idfsoft.com;
if ($invalid_referer) {
rewrite ^/ http://www.idfsoft.com/403.html;
}
}
nginx
通常被用作後端伺服器的反向代理,這樣就可以很方便的實現動靜分離以及負載均衡,從而大大提高伺服器的處理能力。
nginx
實現動靜分離,其實就是在反向代理的時候,如果是靜態資源,就直接從nginx
發佈的路徑去讀取,而不需要從後臺伺服器獲取了。
但是要注意,這種情況下需要保證後端跟前端的程式保持一致,可以使用Rsync做伺服器端自動同步或者使用NFS
、MFS
分佈式共用儲存。
Http Proxy
模組,功能很多,最常用的是proxy_pass
和proxy_cache
如果要使用proxy_cache
,需要整合第三方的ngx_cache_purge
模組,用來清除指定的URL快取。這個整合需要在安裝nginx的時候去做,如:
./configure --add-module=../ngx_cache_purge-1.0 ......
nginx
通過upstream
模組來實現簡單的負載均衡,upstream
需要定義在http
段內
在upstream
段內,定義一個伺服器列表,預設的方式是輪詢,如果要確定同一個存取者發出的請求總是由同一個後端伺服器來處理,可以設定ip_hash,如:
upstream idfsoft.com {
ip_hash;
server 127.0.0.1:9080 weight=5;
server 127.0.0.1:8080 weight=5;
server 127.0.0.1:1111;
}
注意:這個方法本質還是輪詢,而且由於用戶端的ip可能是不斷變化的,比如動態ip,代理,翻牆等,因此ip_hash並不能完全保證同一個用戶端總是由同一個伺服器來處理。
定義好upstream
後,需要在server
段內新增如下內容:
server {
location / {
proxy_pass http://idfsoft.com;
}
}