Nginx http server

Ubuntu PPA

  • Nginx安裝
  • Offical PPA

    • sudo add-apt-repository ppa:nginx/stable
    • sudo apt-get update
    • sudo apt-get install nginx-full
  • 設定檔如下:

/etc/nginx
├── conf.d
├── fastcgi.conf
├── fastcgi_params
├── koi-utf
├── koi-win
├── mime.types
├── modules-available
├── modules-enabled
│   ├── 50-mod-http-auth-pam.conf -> /usr/share/nginx/modules-available/mod-http-auth-pam.conf
│   ├── 50-mod-http-echo.conf -> /usr/share/nginx/modules-available/mod-http-echo.conf
│   ├── 50-mod-http-geoip.conf -> /usr/share/nginx/modules-available/mod-http-geoip.conf
│   ├── 50-mod-http-image-filter.conf -> /usr/share/nginx/modules-available/mod-http-image-filter.conf
│   ├── 50-mod-http-subs-filter.conf -> /usr/share/nginx/modules-available/mod-http-subs-filter.conf
│   ├── 50-mod-http-upstream-fair.conf -> /usr/share/nginx/modules-available/mod-http-upstream-fair.conf
│   ├── 50-mod-http-xslt-filter.conf -> /usr/share/nginx/modules-available/mod-http-xslt-filter.conf
│   ├── 50-mod-mail.conf -> /usr/share/nginx/modules-available/mod-mail.conf
│   └── 50-mod-stream.conf -> /usr/share/nginx/modules-available/mod-stream.conf
├── nginx.conf
├── proxy_params
├── scgi_params
├── sites-available
│   ├── default
│   └── par67
├── sites-enabled
│   └── par67 -> /etc/nginx/sites-available/par67
├── snippets
│   ├── fastcgi-php.conf
│   └── snakeoil.conf
├── uwsgi_params
└── win-utf
  • service nginx start/stop/status:nginx服務啟動/停止/狀態。
nginx version: nginx/1.10.1
Usage: nginx [-?hvVtTq] [-s signal] [-c filename] [-p prefix] [-g directives]

Options:
  -?,-h         : this help
  -v            : show version and exit
  -V            : show version and configure options then exit
  -t            : test configuration and exit
  -T            : test configuration, dump it and exit
  -q            : suppress non-error messages during configuration testing
  -s signal     : send signal to a master process: stop, quit, reopen, reload
  -p prefix     : set prefix path (default: /usr/share/nginx/)
  -c filename   : set configuration file (default: /etc/nginx/nginx.conf)
  -g directives : set global directives out of configuration file

nginx在啟動後,在unix系統中會以daemon的方式在後臺運行,後臺進程包含一個master進程和多個worker進程。我們也可以手動地關掉後臺模式,讓nginx在前臺運行,並且通過配置讓nginx取消master進程,從而可以使nginx以單進程方式運行。很顯然,生產環境下我們肯定不會這麼做,所以關閉後臺模式,一般是用來調試用的,在後面的章節裡面,我們會詳細地講解如何調試nginx。所以,我們可以看到,nginx是以多進程的方式來工作的,當然nginx也是支援多執行緒的方式的,只是我們主流的方式還是多進程的方式,也是nginx的預設方式。

  • nginx在啟動後,會有一個master進程和多個worker進程。master進程主要用來管理worker進程,包含:接收來自外界的信號,向各worker進程發送信號,監控worker進程的運行狀態,當worker進程退出後(異常情況下),會自動重新開機新的worker進程。
  • 而基本的網路事件,則是放在worker進程中來處理了。多個worker進程之間是對等的,他們同等競爭來自用戶端的請求,各進程互相之間是獨立的。
  • 一個請求,只可能在一個worker進程中處理,一個worker進程,不可能處理其它進程的請求。worker進程的個數是可以設置的,一般我們會設置與機器cpu核數一致,這裡面的原因與nginx的進程模型以及事件處理模型是分不開的。
  • 在nginx啟動後,如果我們要操作nginx,從上圖中我們可以看到,master來管理worker進程,所以我們只需要與master進程通信就行了。

    • master進程會接收來自外界發來的信號,再根據信號做不同的事情。所以我們要控制nginx,只需要通過kill向master進程發送信號就行了。
    • 比如kill -HUP pid,則是告訴nginx重啟nginx,我們一般用這個信號來重啟nginx,或重新載入配置,因為是從容地重啟,因此服務是不中斷的。
    • master進程在接收到HUP信號後是怎麼做的呢?首先master進程在接到信號後,會先重新載入設定檔,然後再啟動新的worker進程,並向所有老的worker進程發送信號,告訴他們可以光榮退休了。新的worker在啟動後,就開始接收新的請求,而老的worker在收到來自master的信號後,就不再接收新的請求,並且在當前進程中的所有未處理完的請求處理完成後,再退出。
  • 現在,我們知道了當我們在操作nginx的時候,nginx內部做了些什麼事情,那麼,worker進程又是如何處理請求的呢?

    • 我們前面有提到,worker進程之間是平等的,每個進程,處理請求的機會也是一樣的。當我們提供80埠的http服務時,一個連接請求過來,每個進程都有可能處理這個連接,怎麼做到的呢?
    • 首先,每個worker進程都是從master進程fork過來,在master進程裡面,先建立好需要listen的socket(listenfd)之後,然後再fork出多個worker進程。
    • 所有worker進程的listenfd會在新連接到來時變得可讀,為保證只有一個進程處理該連接,所有worker進程在註冊listenfd讀事件前搶accept_mutex,搶到互斥鎖的那個進程註冊listenfd讀事件,在讀事件裡調用accept接受該連接。
    • 當一個worker進程在accept這個連接之後,就開始讀取請求,解析請求,處理請求,產生資料後,再返回給用戶端,最後才斷開連接,這樣一個完整的請求就是這樣的了。我們可以看到,一個請求,完全由worker進程來處理,而且只在一個worker進程中處理。
    • 那麼,nginx採用這種進程模型有什麼好處呢?當然,好處肯定會很多了。首先,對於每個worker進程來說,獨立的進程,不需要加鎖,所以省掉了鎖帶來的開銷,同時在程式設計以及問題查找時,也會方便很多。
    • 其次,採用獨立的進程,可以讓互相之間不會影響,一個進程退出後,其它進程還在工作,服務不會中斷,master進程則很快啟動新的worker進程。當然,worker進程的異常退出,肯定是程式有bug了,異常退出,會導致當前worker上的所有請求失敗,不過不會影響到所有請求,所以降低了風險。

Nginx設定檔結構

  • nginx設定檔由不同模組組成,通過模組化的方式實現不同的功能。
  • 配置指令分為簡單指令和塊指令。一個簡單的指令,包括名稱,用空格分隔參數,並用分號(;)結束。
  • 一個塊指令由一個或多個簡單具有相同的結構簡單指令組合而成,使用一組用{}括弧括起來表示塊結束。
  • 上下文(context):一個塊的指令包含有大括弧其他指令,它被稱為上下文(例如:事件,HTTP,伺服器,和位置)。

    • 放置在設定檔中的任何上下文以外的指令都被認為是在主上下文。
  • 主要結構如下:


#Events用於配置IO模型,如epoll、kqueue、select或poll等,它們是必備模組。
events {       
    ...
}

#http上下文專用於配置用於http的各模組
http {
      #包括用戶端類指令,檔IO類指令,hash類指令,通訊端類指令等 
      ...
      server {
          #用於定義虛擬伺服器相關的屬性,常見的指令有backlog、rcvbuf、bind及sndbuf等
           ...
      }
      server {
            ...
      }
    ...
}

基本的nginx.conf配置描述

user  www-data;        #指定運行worker進程的使用者和組
worker_processes  auto;  #worker執行緒的個數;通常應該為物理CPU核心個數減1;

error_log  logs/error.log;        #配置錯誤日誌檔位置及日誌記錄級別
error_log  logs/error.log  notice;#可用於main、http、server及location上下文中
error_log  logs/error.log  info;  #語法格式為error_log file |stderr [debug|info|notice|warn|error|crit|alert|emerg]

pid        /run/nginx.pid;          #指定pid存放路徑   

events {
    worker_connections  1024; 每個worker進程所能夠回應的最大併發請求數;
}

http {
    include       mime.types;
    default_type  application/octet-stream;

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

    sendfile        on;    #文件發送
    #tcp_nopush     on;

    keepalive_timeout  65;  #保持連接的超時時長,默認為65s

    #gzip  on;   #是否開啟gzip壓縮

    server {
        # 定義server的網址,可定義多個, 匹配順序如下
        # 1. exact name 
        # 2. Longest wildcard starting with an asterisk, such as *.example.org
        # 3. Longest wildcard ending with an asterisk, such as mail.*
        # 4. First matching regular expression
        server_name  localhost par.cse.nsysu.edu.tw;

        #定義監聽的埠
        listen       80;        

        #定義字元集
        charset koi8-r;        

        access_log  logs/host.access.log  main;  #訪問日誌檔存放路徑

        # location通常用於server上下文中,用於設定某URI的訪問屬性。location可以嵌套。 
        # location有兩種設定法 prefix string與regular expression.
        # match 順序如下:
        # 1. Test the URI against all prefix strings.
        # 2. The = (equals sign) modifier defines an exact match of the URI and a prefix string. If the exact match is found, the search stops.
        # 3. If the ^~ (caret-tilde) modifier prepends the longest matching prefix string, the regular expressions are not checked.
        # 4. Store the longest matching prefix string.
        # 5. Test the URI against regular expressions.
        # 6. Break on the first matching regular expression and use the corresponding location.
        # 7. If no regular expression matches, use the location corresponding to the stored prefix string.

        # 以路徑描述的為prefix string如下:
        location / {     
            #預設首頁檔位置,此處當前為相對路徑,/etc/nginx/html
            root   html;  

            #首頁檔順序,如果找不到index.html,則找index.htm
            index  index.html index.htm; 
        }

        # 以tilde(~)符號開頭的為大小寫有關的regular expression
        # 而tilde star(~*)符號為大小寫無關的regular expression
        location ~ \.html? {
            ...
        }   

        #以下部分根據http狀態碼重定向錯誤頁面
        #error_page  404              /404.html;

        # redirect server error pages to the static page /50x.html
        #
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }
}

參考文獻

results matching ""

    No results matching ""