1. 程式人生 > 實用技巧 >Linux服務之nginx介紹及配置

Linux服務之nginx介紹及配置

目錄

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;
  }
}