Linux服務之nginx介紹及設定

2020-08-11 20:46:38

1. nginx簡介


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網站使用者有:百度、京東、新浪、網易、騰訊、淘寶等。

2. nginx的特性與優點


2.1 nginx的特性

nginx是一個很牛的高效能Web和反向代理伺服器,它具有很多非常優越的特性:

  • 在高連線併發的情況下,nginx是Apache伺服器不錯的替代品,能夠支援高達50000個併發連線數的響應
  • 使用epoll and kqueue作爲開發模型
  • nginx作爲負載均衡伺服器:nginx既可在內部直接支援和PHP程式對外進行服務,也可支援作爲HTTP代理伺服器對外進行服務
  • nginx採用C進行編寫,不論系統資源開銷還是CPU使用效率都比Perlbal要好很多

2.2 nginx的優點

  • 高併發連線:官方測試能夠支撐5萬併發連線,在實際生產環境中跑到2-3萬併發連線數
  • 記憶體消耗少:在3萬併發連線下,開啓的10個nginx進程才消耗150M記憶體(15M*10=150M)
  • 組態檔非常簡單:風格跟程式一樣通俗易懂
  • 成本低廉:nginx爲開源軟體,可以免費使用。而購買F5 BIG-IP、NetScaler等硬體負載均衡交換機則需要十多萬至幾十萬人民幣
  • 支援Rewrite重寫規則:能夠根據域名、URL的不同,將HTTP請求分到不同的後端伺服器羣組
  • 內建的健康檢查功能:如果Nginx Proxy後端的某台Web伺服器宕機了,不會影響前端存取
  • 節省頻寬:支援GZIP壓縮,可以新增瀏覽器本地快取的Header頭
  • 穩定性高:用於反向代理,宕機的概率微乎其微
  • 模組化設計:模組可以動態編譯
  • 外圍支援好:文件全,二次開發和模組較多
  • 支援熱部署:可以不停機過載組態檔
  • 支援事件驅動、AIO(AsyncIO,非同步IO)、mmap(Memory Map,記憶體對映)等效能優化

3. nginx的功能及應用類別


3.1 nginx的基本功能

  • 靜態資源的web伺服器,能快取開啓的檔案描述符
  • http、smtp、pop3協定的反向代理伺服器
  • 快取加速、負載均衡
  • 支援FastCGI(fpm,LNMP),uWSGI(Python)等
  • 模組化(非DSO機制 機製),過濾器zip、SSI及影象的大小調整
  • 支援SSL

3.2 nginx的擴充套件功能

  • 基於名稱和IP的虛擬主機
  • 支援keepalive
  • 支援平滑升級
  • 定製存取日誌、支援使用日誌緩衝區提高日誌儲存效能
  • 支援URL重寫
  • 支援路徑別名
  • 支援基於IP及使用者的存取控制
  • 支援速率限制,支援併發數限制

3.3 nginx的應用類別

  • 使用nginx結合FastCGI執行PHP、JSP、Perl等程式
  • 使用nginx作反向代理、負載均衡、規則過濾
  • 使用nginx執行靜態HTML網頁、圖片
  • nginx與其他新技術的結合應用

4. nginx的模組與工作原理


nginx由內核和模組組成。其中,內核的設計非常微小和簡潔,完成的工作也非常簡單,僅僅通過查詢組態檔將用戶端請求對映到一個location block(location是nginx設定中的一個指令,用於URL匹配),而在這個location中所設定的每個指令將會啓動不同的模組去完成相應的工作。

4.1 nginx的模組分類

nginx的模組從結構上分爲核心模組、基礎模組和第三方模組

  • HTTP模組、EVENT模組和MAIL模組等屬於核心模組
  • HTTP Access模組、HTTP FastCGI模組、HTTP Proxy模組和HTTP Rewrite模組屬於基本模組
  • HTTP Upstream模組、Request Hash模組、Notice模組和HTTP Access Key模組屬於第三方模組

使用者根據自己的需要開發的模組都屬於第三方模組。正是有瞭如此多模組的支撐,nginx的功能纔會如此強大

nginx模組從功能上分爲三類,分別是:

  • Handlers(處理器模組)。此類模組直接處理請求,並進行輸出內容和修改headers資訊等操作。handlers處理器模組一般只能有一個
  • Filters(過濾器模組)。此類模組主要對其他處理器模組輸出的內容進行修改操作,最後由nginx輸出
  • Proxies(代理器模組)。就是nginx的HTTP Upstream之類的模組,這些模組主要與後端一些服務比如fastcgi等操作互動,實現服務代理和負載均衡等功能

nginx模組分爲:核心模組、事件模組、標準Http模組、可選Http模組、郵件模組、第三方模組和修補程式等

  • nginx基本模組:所謂基本模組,指的是nginx預設的功能模組,它們提供的指令,允許你使用定義nginx基本功能的變數,在編譯時不能被禁用,包括:

    • 核心模組:基本功能和指令,如進程管理和安全。常見的核心模組指令,大部分是放置在組態檔的頂部
    • 事件模組:在Nginx內設定網路使用的能力。常見的events(事件)模組指令,大部分是放置在組態檔的頂部
    • 設定模組:提供包含機制 機製

具體的指令,請參考nginx官方文件

4.2 nginx的工作原理

nginx的模組直接被編譯進nginx,因此屬於靜態編譯方式。

啓動nginx後,nginx的模組被自動載入,與Apache不一樣,首先將模組編譯爲一個so檔案,然後在組態檔中指定是否進行載入。

在解析組態檔時,nginx的每個模組都有可能去處理某個請求,但是同一個處理請求只能由一個模組來完成。

nginx的進程架構:
啓動nginx時,會啓動一個Master進程,這個進程不處理任何用戶端的請求,主要用來產生worker執行緒,一個worker執行緒用來處理n個request
在这里插入图片描述
下圖展示了nginx模組一次常規的HTTP請求和響應的過程
在这里插入图片描述
下圖展示了基本的WEB服務請求步驟
在这里插入图片描述

5. nginx的安裝與設定


5.1 nginx的安裝和設定

//安裝依賴包
[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

存取網頁
在这里插入图片描述

6 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提供的網站,包括虛擬主機

6.1 nginx.conf設定詳解

nginx.conf的內容分爲以下幾段:

  • main設定段:全域性設定段。其中main設定段中可能包含event設定段
  • event {}:定義event模型工作特性
  • http {}:定義http協定相關的設定

設定指令:要以分號結尾,語法格式如下:

derective value1 [value2 ...];

支援使用變數:

  • 內建變數:模組會提供內建變數定義
  • 自定義變數:set var_name value

6.2 用於偵錯、定位問題的設定參數

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

6.3 正常執行必備的設定參數

user USERNAME [GROUPNAME];    //指定執行worker進程的使用者和組
pid /path/to/pid_file;    //指定nginx守護行程的pid檔案
worker_rlimit_nofile number;    //設定所有worker進程最大可以開啓的檔案數,預設爲1024
worker_rlimit_core size;    //指明所有worker進程所能夠使用的總體的最大核心檔案大小,保持預設即可

6.4 優化效能的設定參數

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值

6.5 事件相關的設定:event{}段中的設定參數

accept_mutex {off|on};    //master排程使用者請求至各worker進程時使用的負載均衡鎖;on表示能讓多個worker輪流地、序列化地去響應新請求
lock_file file;    //accept_mutex用到的互斥鎖鎖檔案路徑
use [epoll | rtsig | select | poll];    //指明使用的事件模型,建議讓nginx自行選擇
worker_connections #;    //每個進程能夠接受的最大連線數

6.6 網路連線相關的設定參數

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;    //發送響應報文的超時時長

6.7 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;
  include fastcgi_params;
}

6.8 常需要進行調整的參數

  • worker_processes
  • worker_connections
  • worker_cpu_affinity
  • worker_priority

6.9 nginx作爲web伺服器時使用的設定:http{}段的設定參數

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時,匹配順序如下:

  1. 先做精確匹配檢查
  2. 左側萬用字元匹配檢查,如*.idfsoft.com
  3. 右側萬用字元匹配檢查,如mail.*
  4. 正則表達式匹配檢查,如~ ^.*.idfsoft.com$
  5. default_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各模組內建變數

6.10 location區段

關於location區段的詳解,請檢視這篇nginx服務之location區段匹配規則詳解

6.11 基於使用者認證

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

6.12 https設定和開啓狀態介面

關於https設定和開啓狀態介面的詳解請看這篇nginx服務之設定https和監控狀態頁面

6.13 rewrite

語法:rewrite regex replacement flag;,如:

rewrite ^/images/(.*\.jpg)$ /imgs/$1 break;

此處的$1用於參照(.*.jpg)匹配到的內容,又如:

rewrite ^/bbs/(.*)$ http://www.idfsoft.com/index.html redirect;

如上例所示,replacement可以是某個路徑,也可以是某個URL

6.13.1 舉例說明(1)

//下載一張照片,建立一個目錄存放照片
[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

去瀏覽器存取
在这里插入图片描述
成功達到效果!!!

6.13.2 舉例說明(2)

上面做的那種效果是讓存取直接跳轉到自己本地存放照片的目錄下
現在要做的是,讓存取的內容直接跳轉到網路上來存取,自己來定義網站,我這裏就讓它跳轉到百度!

設定如下:

//修改組態檔
[root@localhost ~]# vim /usr/local/nginx/conf/nginx.conf
..........
 location /images {
            rewrite ^/images/(.*\.jpg)$ https://www.bilibili.com/ break;
        }

//重讀下組態檔
[root@localhost ~]# nginx -s reload

在瀏覽器上存取
在这里插入图片描述
成功跳轉!!
在这里插入图片描述

6.13.3 舉例說明(3)

現在用下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

//這些被捕獲的數據,在後面就可以當變數一樣使用了

6.14 if

語法:if (condition) {...}

應用場景:

  • server段
  • location段

常見的condition

  • 變數名(變數值爲空串,或者以「0」開始,則爲false,其它的均爲true)

  • 以變數爲運算元構成的比較表達式(可使用=,!=類似的比較操作符進行測試)

  • 正則表達式的模式匹配操作

    • ~:區分大小寫的模式匹配檢查
    • ~*:不區分大小寫的模式匹配檢查
    • !和!*:對上面兩種測試取反
  • 測試指定路徑爲檔案的可能性(-f,!-f)

  • 測試指定路徑爲目錄的可能性(-d,!-d)

  • 測試檔案的存在性(-e,!-e)

  • 檢查檔案是否有執行許可權(-x,!-x)

6.14.1 基於瀏覽器實現分離案例

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

去瀏覽器存取驗證
在这里插入图片描述
在这里插入图片描述

6.14.2 防盜鏈案例

location ~* \.(jpg|gif|jpeg|png)$ {
  valid_referers none blocked www.idfsoft.com;
  if ($invalid_referer) {
    rewrite ^/ http://www.idfsoft.com/403.html;
  }
}

6.15 反向代理與負載均衡

nginx通常被用作後端伺服器的反向代理,這樣就可以很方便的實現動靜分離以及負載均衡,從而大大提高伺服器的處理能力。

nginx實現動靜分離,其實就是在反向代理的時候,如果是靜態資源,就直接從nginx發佈的路徑去讀取,而不需要從後臺伺服器獲取了。

但是要注意,這種情況下需要保證後端跟前端的程式保持一致,可以使用Rsync做伺服器端自動同步或者使用NFSMFS分佈式共用儲存。

Http Proxy模組,功能很多,最常用的是proxy_passproxy_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;
  }
}