別拿Nginx基礎當祕籍

一、Nginx簡介

    Nginx是什麼?

    Nginx跟Apache一樣都是提供Web服務功能的軟件,但卻通過nginx模塊提供了比Apache更多更強大的功能。它採用的是事件驅動結構,使用異步套接字來接收客戶端請求,是一種非阻塞結構,不使用單獨的線程處理,極大的減少了服務器內存和CPU的開銷

    Nginx的基本功能

        提供靜態資源的web服務器,能緩存打開的文件文件描述符

        支持http、smtp、pop3協議的反向代理服務器

        支持緩存和簡單的負載均衡和容錯

        支持FastCGI

        支持高度模塊化定製,但不支持DSO機制

        支持SSL

    Nginx的擴展功能

        支持基於名稱和基於IP的虛擬主機

        支持KeepAlive

        支持平滑升級

        支持訪問日誌定製

        支持URL重寫

        支持路徑別名

        支持基於IP和基於用戶的訪問控制

        支持速率控制和併發數限制

    Nginx與Apache相比,最大的優勢在於其較低的內存消耗上,據說1w個keepalive連接僅消耗2.5M內存。總之,Nginx能滿足你所有需求。官方文檔:http://nginx.org/en/docs/

Nginx的基本框架

一個master進程生成一個或多個worker進程,每個worker基於事件驅動(epoll機制)、消息通知機制響應N個http請求

wKioL1Se2tTgKOaBAAKlI5zf6aM449.jpg

附:Nginx高度概述框架

wKiom1Se2l6yrFPxAAMjspNaoOY325.jpg

二、Nginx 1.6.2版本的編譯安裝

    Nginx的代碼是由一個核心和一系列的模塊組成, 核心主要用於提供Web Server的基本功能,以及Web和Mail反向代理的功能;還用於啓用網絡協議,創建必要的運行時環境以及確保不同的模塊之間平滑地進行交互。不過,大多跟協議相關的功能和某應用特有的功能都是由nginx的模塊實現的。這些功能模塊大致可以分爲事件模塊、階段性處理器、輸出過濾器、變量處理器、協議、upstream和負載均衡幾個類別,這些共同組成了nginx的http功能。事件模塊主要用於提供OS獨立的(不同操作系統的事件機制有所不同)事件通知機制如kqueue或epoll等。協議模塊則負責實現nginx通過http、tls/ssl、smtp、pop3以及imap與對應的客戶端建立會話。下面爲讀者朋友詳解一下,Nginx-1.6.2版本的編譯安裝。

    從官網下載好源碼包並解壓到/usr/src目錄中:tar xf nginx-1.6.2.tar.gz -C /usr/src

    爲防止編譯安裝過程中出現問題,yum安裝Development Tools和Server Platform Development包組

    添加nginx系統組:groupadd -r nginx

    添加nginx系統用戶:useradd -g nginx -r nginx

    切換到nginx的解壓目錄中,準備執行編譯安裝相關操作:cd /usr/src/nginx-1.6.2/;建議編譯安裝之前先使用./configure --help 根據自己的需求添加模塊。

    編譯安裝

./configure --prefix=/usr/local/nginx --conf-path=/etc/nginx/nginx.conf --user=nginx --group=nginx --error-log-path=/var/log/nginx/error_log  --http-log-path=/var/log/nginx/access_log --pid-path=/var/run/nginx/nginx.pid  --with-http_ssl_module  --with-http_gzip_static_module  --with-http_stub_status_module  --with-http_mp4_module  --http-proxy-temp-path=/var/tmp/nginx/proxy  --http-fastcgi-temp-path=/var/tmp/nginx/fastcgi --http-client-body-temp-path=/var/tmp/nginx/client --with-pcre

注:若出現編譯錯誤,大多數是缺少對應模塊功能的開發包,比如--with-pcre,若事先沒有安裝支持正則表示式的開發包pcre-devel,很有可能會報錯。

make

make install

wKioL1SfS-7SeY-tAAUuPUX3f8s569.jpg

爲nginx提供服務腳本

vim /etc/init.d/nginx

#!/bin/sh
#
# nginx - this script starts and stops the nginx daemon
#
# chkconfig:   - 85 15 
# description:  Nginx is an HTTP(S) server, HTTP(S) reverse \
#               proxy and IMAP/POP3 proxy server
# processname: nginx
# config:      /etc/nginx/nginx.conf
# config:      /etc/sysconfig/nginx
# pidfile:     /var/run/nginx.pid
 
# Source function library.
. /etc/rc.d/init.d/functions
 
# Source networking configuration.
. /etc/sysconfig/network
 
# Check that networking is up.
[ "$NETWORKING" = "no" ] && exit 0

#Nginx程序路徑 
nginx="/usr/local/nginx/sbin/nginx"
prog=$(basename $nginx)

#Nginx配置文件路徑 
NGINX_CONF_FILE="/etc/nginx/nginx.conf"
 
[ -f /etc/sysconfig/nginx ] && . /etc/sysconfig/nginx
 
lockfile=/var/lock/subsys/nginx
 
make_dirs() {
   # make required directories
   user=`nginx -V 2>&1 | grep "configure arguments:" | sed 's/[^*]*--user=\([^ ]*\).*/\1/g' -`
   options=`$nginx -V 2>&1 | grep 'configure arguments:'`
   for opt in $options; do
   if [ `echo $opt | grep '.*-temp-path'` ]; then
   value=`echo $opt | cut -d "=" -f 2`
   if [ ! -d "$value" ]; then
   # echo "creating" $value
   mkdir -p $value && chown -R $user $value
   fi
   fi
   done
}
 
start() {
[ -x $nginx ] || exit 5
[ -f $NGINX_CONF_FILE ] || exit 6
make_dirs
echo -n $"Starting $prog: "
daemon $nginx -c $NGINX_CONF_FILE
retval=$?
echo
[ $retval -eq 0 ] && touch $lockfile
return $retval
}
 
stop() {
echo -n $"Stopping $prog: "
killproc $prog -QUIT
retval=$?
echo
[ $retval -eq 0 ] && rm -f $lockfile
return $retval
}
 
restart() {
configtest || return $?
stop
sleep 1
start
}
 
reload() {
configtest || return $?
echo -n $"Reloading $prog: "
killproc $nginx -HUP
RETVAL=$?
echo
}
 
force_reload() {
restart
}
 
configtest() {
  $nginx -t -c $NGINX_CONF_FILE
}
 
rh_status() {
status $prog
}
 
rh_status_q() {
rh_status >/dev/null 2>&1
}
 
case "$1" in
start)
rh_status_q && exit 0
$1
;;
stop)
rh_status_q || exit 0
$1
;;
restart|configtest)
$1
;;
reload)
rh_status_q || exit 7
$1
;;
force-reload)
force_reload
;;
status)
rh_status
;;
condrestart|try-restart)
rh_status_q || exit 0
;;
*)
echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload|configtest}"
exit 2
esac

將服務腳本的權限設置爲可執行:chmod +x /etc/init.d/nginx

將服務加入服務列表中,並設置爲開機自啓動:chkconfig --add nginx && chkconfig nginx on

測試啓動nginx:service nginx start

wKiom1SfS8Tx9S8OAAEzATVTQUM729.jpg 

wKioL1SfTJmwHFjdAAIzH8WJ2uQ394.jpg

三、Nginx常用配置(配置文件/etc/nginx/nginx.conf)

    Nginx的主配置文件由main、http、mail等幾個段組成,這些個段通常也被稱爲Nginx的上下文,每個段的配置格式如下所示:

                                                <section> {

                                            <directive> <parameters>;

                                        }

    需要注意的是,其每一個指令都必須使用分號(;)結束,否則視爲語法錯誤。

main配置段的常用參數

    A、保證Nginx正常運行的相關配置:

    user USERNAME GROUP  指定運行worker進程的用戶和組,如果在編譯中沒有指定,需將註釋去掉,以nobody身份運行worker進程

    pid /PATH/TO/PID_FILE  指定Nginx的pid文件,如果在編譯中沒有指定,需要在main配置段中定義

    worker_rlimit_nofile NUM  設定worker進程所能夠打開的文件描述符個數的最大值。

    worker_rlimit_sigpending NUM  指定每個用戶能夠發往worker進程的信號的數量

    B、優化性能的相關配置

    worker_process NUM 設定master進程啓動的worker進程數,具體需要看CPU的核心數,生產環境中常將其設置爲cpu核心數減1

    worker_cpu_affinity CPUMASK…… 綁定worker進程至指定CPU上,如:

                                    worker_processes     4;

                            worker_cpu_affinity 0001 0010 0100 1000;

    timer_resolution INTERVAL 設定更新緩存的時間間隔,如:timer_resolution  100ms;

    worker_priority nice_NUM 設定worker進程運行的優先級(按nice值設置),默認爲0;如:worker_priority -20

    C、事件event相關的配置(以下配置需寫在event {……}中)

    worker_connections NUM  每個worker進程所能夠響應的最大併發請求數,它與worker_processes共同決定能響應的最大客戶數maxclients的值。

                                    maxclients = worker_processes * worker_connections

    而在反向代理場景中,其計算方法與上述公式不同,因爲默認情況下瀏覽器將打開2個連接,而nginx會爲每一個連接打開2個文件描述符,因此,其maxclients的計算方法爲:

                            maxclients = worker_processes * worker_connections/4

    accept_mutex on|off 是否打開Nginx的負載均衡鎖,設爲on時,能使多個worker進程輪流地、序列化地與響應新請求

    lock_file /PATH/TO/LOCK_FILE 負載均衡鎖的路徑

    accept_mutex_delay INTERVAL 等待負載均衡鎖的時間間隔

    use epoll|rgsig|select|poll 設定worker進程使用的事件模型IO,建議讓Nginx自動選擇

    D、用於調試、定位問題的相關配置

    daemon off|on  是否以守護進程的方式啓動nginx,定位問題時設爲off,正常環境爲on

    master_process on|off  是否以master/worker模型來運行nginx

    error_log /PATH/TO/error_log debug|info|notice|warn|error|crit|alert|emerg  設定錯誤日誌文件及其級別;出於調試的目的,可以使用debug級別,但此級別只有在編譯nginx時使用了--with-debug選項纔有效;要禁用錯誤日誌,不能使用“error_log off;”,而要使用類似如下選項:                                             error_log /dev/null crit


http上下文專用於配置用於http的各模塊,此類指令非常的多,每個模塊都有其專用指定。其配置框架:

http {
    upstreamserver {
            ....
    }
    server {
        #定義虛擬主機
        listen IP:PORT;
        server_name SER_NAME
        location /URL {
            if ...{
                ...
            }
        root "/path/to/somewhere";
        ...
        }
    }
    server {
        ……
    }
}

注:與http配置相關的指令必須放在http、server、location、upstream、if塊中

http配置段的常用參數

    A、虛擬主機的相關配置

    server {……} 用於定義一個虛擬主機

    listen IP_ADDR [:port] [default_server] 設定監聽的端口號,可以省略IP和port其中之一,還可以添加default_server參數將其設置成默認服務器,用於匹配客戶端的host請求

    server_name Serv_NAME…… 設定主機名,後可跟多個主機名,主機名稱還可以使用通配符和正則表達式(要以~開頭)

注:其匹配次序爲:

 

wKioL1SfT42QuQCgAAG-bYW0vFs469.jpg

    location [=|~|~*|^~] /URI {……} 允許根據用戶請求的URI來匹配定義的各location,匹配到時,此請求將被相應的location塊中的配置所處理,location可以嵌套

其中=表示精確匹配

    ~、~*都表示正則表達式模式匹配,只是前者在匹配時區分字符大小寫

    ^~表示作URI左半部分匹配,匹配時不檢查正則表達式

注:其匹配次序:

wKiom1SfTxaTqXQQAAEzdNMeFZQ131.jpg

處於同一優先級的URI,排在前面的先被匹配

root 設置web資源路徑映射;用於指明請求的URL所對應的文檔的根目錄路徑;如:

                        location /images/ {

                                    root "/web/imgs/";

}

alias 定義路徑別名,

                         location /images/ {

    root "/web/imgs/";

        }

注:root表示路徑爲對應location的“ /” URL;alias表示路徑映射,即location中的URL是相對於alias後所設定的路徑而言

index 設定默認的主頁面

error_page STATUS …… URL 根據http狀態碼重定向至錯誤頁面

error_page STATUS=NEW_STATUS URL 以指定的狀態碼響應客戶端

如:                 server {

                        listen       80;

                        server_name  www.stu24.com;

                        location / {

                             root   html;

                           index  index.html index.htm;

                        }

                        error_page   500 502 503 504  /50x.html;

                        location = /50x.html {

                                root   html;

                        }

        }

    B、網絡連接相關的配置

    keepalive_timeout TIMEOUT 長連接的超時時長,默認爲75s

    keepalive_requests NUM 在一次長連接上允許承載最大資源請求數

    keepalive_disable [msie6|safari|none] 在某些瀏覽器上禁用保持連接

    tcp_nodelay on|off 是否對長連接使用tcp_nodelay選項,開啓之後能有效的提高數據的實時響應性。

    client_header_timeout TIMEOUT 讀取http Request報文首部的超時時長

    client_body_timeout TIMEOUT 讀取http Request報文body部分的超時時長

    send_timeout TIMEOUT 讀取http Response報文的超時時長

    C、對客戶端請求進行限制的相關配置

    limit_except METHOD {...} 通過limit_except後面指定的方法名來限制用戶請求,如:

limit_except GET {

allow 172.16.0.0/16;

deny all;

}

    client_body_max_size SIZE 限制請求報文中body部分的上限,通過檢測請求報文首部中的"Content_Length"來判定,例如,用戶試圖上傳一個10GB的文件,Nginx在收完包頭後,發現Content-Length超過client_max_body_size定義的值,就直接發送413 ("Request Entity Too Large")響應給客戶端

    limit_rate SPEED 限制客戶端每秒種傳輸的字節數,默認爲0,表示無限制;

    D、對內存或磁盤資源進行分配

    client_body_in_file_only on|clean|off 請求報文的body部分是否可暫存於磁盤;on表示允許,並且即使請求結束,也不會刪除暫存的內容;clean表示會刪除;off(默認)不允許暫存; 

    client_body_in_single_buffer on|off 請求報文的body部分是否可暫存於內存buffer中。當然,如果HTTP包體的大小超過了下面client_body_buffer_size設置的值,包體還是會寫入到磁盤文件中

    client_body_buffer_size size 設定內存buffer的大小

    client_body_temp_path DIR [level1 [level2 [level3 [level4]]]] 請求報文的body部分的臨時存放目錄,在接收HTTP包體時,如果包體的大小大於client_body_buffer_size,則會以一個遞增的整數命名並存放到client_body_temp_path指定的目錄中。後面跟着的level1、level2、level3,是爲了防止一個目錄下的文件數量太多,從而導致性能下降,因此使用了level參數,這樣可以按照臨時文件名最多再加三層目錄。例如:client_body_temp_path /var/tmp/nginx/client  1 2

    client_header_buffer_size SIZE 存儲超大HTTP頭部的內存buffer大小

    E、MIME類型相關的配置

    types {……} 定義MIME types至文件的擴展名;例如:

types {

text/html .html;

image/jpeg  .jpg;

}

    default_type MIME-TYPE 當找不到相應的MIME type與文件擴展名之間的映射時,使用默認的MIME-TYPE作爲HTTP header中的Content-Type

    F、文件操作優化相關的配置

    sendfile on|off 是否啓用sendfile系統調用來發送文件,設爲on,表示減少內核態與用戶態之間的兩次內存複製,這樣就會從磁盤中讀取文件後直接在內核態發送到網卡設備,提高了發送文件的效率。

    aio on|off 是否啓用異步I/O,與sendfile功能互斥

    directio size|off 是否使用O_DIRECT選項去請求讀取文件,與sendfile功能互斥;

    open_file_cache max=N[inactive=time]|off 是否打開文件緩存

nginx可以緩存以下三種信息:

(1) 文件句柄、文件大小和最近一次修改時間;

(2) 打開目錄的目錄結構;

(3) 沒有找到的或者沒有權限操作的文件的相關信息;

max=N表示可緩存的最大條目上限;一旦到達上限,則會使用LRU從緩存中刪除最近最少使用的條目;

inactive=time: 在inactive指定的時長內沒有被訪問過的緩存條目就會淘汰;

如:open_file_cache max=1000 inactive=20s;

    open_file_cache_errors on|off 是否緩存打開文件錯誤的信息

    open_file_cache_min_uses INTERVAL檢查一次緩存中緩存條目有效性的時間間隔;默認60s;

    講了一大堆,其實我們重點關注以下幾項就足以應付生產環境中的需求了:

server{}, location{}, listen, server_name, root, alias, keepalive_timeout,keepalive_requests, error_page

    Nginx優化相關配置

    A、基於IP的訪問控制

    在http, server, location中使用 allow, deny指令定義,匹配法則類似於iptables,自上而下依次匹配,如:

                        location / {

                            deny  192.168.1.1;

                            allow 192.168.1.0/24;

                            allow 10.1.1.0/16;

                            deny  all;

                        }

    B、基於用戶的basic認證配置

    auth_basic "AUTH_NAME"

    auth_basic_user_file /PATH/TO/PASSWD_FILE,建議使用htpasswd命令創建用戶賬號文件;

例如:

                        location /wp-login.php {

                            auth_basic 'Welcome WordPress';

                            auth_basic_user_file  /home/mypwd/pass;

                        }        

    C、基於gzip實現響應報文壓縮 

    gzip on|off  是否開啓gzip壓縮,開啓之後節省網絡帶寬,卻增加了服務器CPU的開銷

    gzip_http_version 1.1|1.0  設定啓用gzip壓縮時客戶端請求使用的http協議版本號

    gzip_min_length LENGTH 設定最小壓縮的頁面,注:若頁面過小,可能導致頁面越壓越大,單位爲B,如:gzip_min_length 1024

    gzip_buffers NUM SIZE 設定存儲壓縮後的響應報文的緩存區數量及大小,默認爲一個頁面的大小,具體大小依賴於系統平臺,不是4K就是8K(getconf PAGE_SIZE 獲取系統內存頁面大小),例如:gzip_buffers 4 8k

    gzip_comp_level 3 設定gzip的壓縮級別,1壓縮比最小處理速度最快,9壓縮比最大但處理最慢,同時也最消耗CPU,一般設置爲3就可以了

    gzip_types MIME_TYPE設定gzip壓縮的MIME類型

    gzip_proxied [off|expired|no-cache|no-store|private|no_last_modified|no_etag|auth|any] 根據某些請求和應答來決定是否在對代理請求的應答啓用壓縮,代理請求取決於請求頭中的“Via”字段,指令中可以同時指定多個不同的參數:

                            off 爲所有代理請求禁用壓縮。

                            expired 當“Expires”頭禁用緩存時啓用壓縮。

                            no-cache 當“Cache-Control”頭設置爲no-cache時啓用壓縮。

                            no-store  當“Cache-Control”頭設置爲no-store時啓用壓縮。

                            private  當“Cache-Control”頭設置爲private時啓用壓縮。

                            no_last_modified  當“Last-Modified”沒有定義時啓用壓縮。

                            no_etag  沒有“ETag”頭時啓用壓縮。

                            auth 當有一個“Authorization”頭時啓用壓縮。

                            any  爲所有請求啓用壓縮。

                            gzip_disable 設定在某些瀏覽器上不啓用gzip壓縮

gzip使用實例:

                gzip on;
                gzip_comp_level 3;
                gzip_buffers 4 8k;
                gzip_http_version 1.1;
                gzip_disable "MSIE [1-6]";
                gzip_types text/plain application/x-javascript text/css text/javascript application/x-httpd-php image/jpeg image/gif image/png;

    D、定製響應首部

    add_header key value [always],如:add_header  Content-Type 'text/html; charset=utf-8';

    expires TIME,設定緩存時間 如:

                location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)${
                           expires 30d;
                 }

    E、定製訪問日誌

    log_format NAME LOG_FORMAT 設置日誌的記錄格式,

    access_log 指定日誌文件的存放路徑、格式和緩存大小,也可以使用off關閉日誌功能,如:

log_format  access  ‘$remote_addr – $remote_user [$time_local] “$request” ‘
‘$status $body_bytes_sent “$http_referer” ‘
‘”$http_user_agent” $http_x_forwarded_for’;
access_log  /var/log/access.log   access

        $remote_addr 與$http_x_forwarded_for 用以記錄客戶端的ip地址;

        $remote_user  用來記錄客戶端用戶名稱;

        $time_local    用來記錄訪問時間與時區;

        $request   用來記錄請求的url與http協議;

        $status   用來記錄請求狀態;成功是200,

        $body_bytes_sent  記錄發送給客戶端文件主體內容大小;

        $http_referer  用來記錄從那個頁面鏈接訪問過來的;

        $http_user_agent  記錄客戶端瀏覽器的相關信息;

    F、定義合法引用,防盜鏈

    valid_referers none | blocked | server_names | string ...如:

location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)${
                    valid_referers none blocked www.stu24.com stu24.com;
                    if ($invalid_referer){
                               return 403;
                    }
}

    G、定義路徑重寫,與正則表達式結合if判斷使用

    rewrite regex replacement [flag]

flag標記有四種格式:

            last 相當於Apache中的L

            break 中止Rewirte,不在繼續匹配

            redirect  返回臨時重定向的HTTP狀態302,相當於Apache中的R

            permanent 返回永久重定向的HTTP狀態301,相當於Apache中的R=301

    if (condition) {

    ...

    }

條件conditon可以是如下任何內容:

            一個變量名;false如果這個變量是空字符串或者以0開始的字符串;

            使用= ,!= 比較的一個變量和字符串

            使用~, ~*與正則表達式匹配的變量,如果這個正則表達式中包含},;則整個表達式需要用" 或' 包圍

            使用-f ,!-f 檢查一個文件是否存在

            使用-d, !-d 檢查一個目錄是否存在

            使用-e ,!-e 檢查一個文件、目錄、符號鏈接是否存在

            使用-x , !-x 檢查一個文件是否可執行

    return STATUS URL 結束規則時執行並返回狀態碼給客戶端

    set VARIABLE VALUE 定義一個變量,並給變量賦值

例如:將訪問的URL是 stu24.com重定向爲www.stu24.com

    if ($host != 'www.stu24.com' ) {
        rewrite ^/(.*)$ http://www.stu24.com/$1 permanent;
    }


附錄:nginx有以下內置變量

    $args, 請求中的參數;

    $content_length, HTTP請求信息裏的"Content-Length";

    $content_type, 請求信息裏的"Content-Type";

    $document_root, 針對當前請求的根路徑設置值;

    $document_uri, 與$uri相同;

    $host, 請求信息中的"Host",如果請求中沒有Host行,則等於設置的服務器名;

    $limit_rate, 對連接速率的限制;

    $request_method, 請求的方法,比如"GET"、"POST"等;

    $remote_addr, 客戶端地址;

    $remote_port, 客戶端端口號;

    $remote_user, 客戶端用戶名,認證用;

    $request_filename, 當前請求的文件路徑名

    $request_uri, 請求的URI,帶查詢字符串;

    $query_string, 與$args相同;

    $scheme, 所用的協議,比如http或者是https,比如:

    rewrite ^(.+)$  $scheme://example.com$1  redirect;

    $server_protocol, 請求的協議版本,"HTTP/1.0"或"HTTP/1.1";

    $server_addr, 服務器地址,如果沒有用listen指明服務器地址,使用這個變量將發起一次系統調用以取得地址(造成資源浪費);

    $server_name, 請求到達的服務器名;

    $server_port, 請求到達的服務器端口號;

    $uri, 請求的URI,可能和最初的值有不同,比如經過重定向之類的。

這些變量可以用在rewrite規則裏,也可以打印日誌的時候用

部分內容引用《深入理解nginx:模塊開發與架構解析》

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章