nginx(1)

下一篇:nginx(2)javascript

1、engin X

市場的服務器很是的多,這裏簡單介紹幾種經常使用的。php

  • Apache:源代碼開放,跨平臺,可移植,且支持的模塊很是豐富,雖然在速度性能上不如其餘輕量級的web服務器,屬於重量級產品,消耗的內存比其餘的服務器更高。
  • Lighttpd:德國人寫的開源軟件。功能也很是豐富,擁有內存開銷低,CPU佔用率低,性能好,以及模塊豐富等特色。支持FastCGI,CGI,Auth,輸出壓縮,URL重寫以及Alias等等重要功能。與nginx相同,是輕量級別的服務器。
  • Tomcat: Tomcat實現了Apache-Jakarta規範,且比絕大多數的商業服務器要好,可是對靜態文件,高併發處理的能力比較弱。
  • IBM WebSphere:功能完善、開放的Web應用程序服務器,是IBM電子商務計劃的核心部分,基於Java的應用環境。是IBM的一整套產品,範圍從簡單到高級,直到企業級。
  • Microsoft IIS: 微軟的Web服務器,只能運行於微軟的平臺上,提供了圖形化的管理工具。

1.1 簡介

  相對於httpd(apache),nginx是比較新的服務器了,現代服務器程序中,併發的壓力愈來愈大,以httpd中的prefork模型爲例,因爲使用的是select函數,有1024的併發限制(關於linux io模型:http://www.cnblogs.com/carl10086/p/5926153.html ),對於上萬個併發請求而言,prefork顯得力不從心,所以出現了一個著名的問題C10K,一萬個併發請求問題,而nginx就是被設計用來解決C10k問題的 ,nginx是一個開源的HTTP server和reverse proxy(反向代理服務器),一樣也是一個IMAP/POP3 proxy。css

nginx從2014年開始推出企業版,同時也一如既往維護着開源版本,針對nginx,也有不少的二次開發版本,好比阿里巴巴的tengine還有openresty等等...html

1.2 選擇Nginx的理由

(1) 高併發鏈接:官方測試5W的併發,實際生產中可支撐2~4W的併發。
nginx使用的是epoll(linux 2.6內核),即信號驅動(signal driver)的IO的模型。java

(2) 內存消耗很是少: Nginx+PHP(FastCGI)服務器在3W併發下,開啓10個Nginx進程的消耗爲150MB左右內存左右(15*10MB),而開啓的64個php-cgi進程消耗1280MB內存,同等硬件環境下,Nginx的併發處理能力應該是Apache的5~10倍。node

(3) 成本低:nginx採用的是2-clause BSD-like協議,能夠免費被用於商業用途。linux

其餘的優勢:nginx

  • 配置簡單
  • 支持Rewrite:豐富的Rewrite
  • 內置健康監測
  • 節省帶寬:能夠壓縮
  • 穩定:企業級
  • 支持熱部署:甚至於在不中止服務的狀況下進行nginx升級

1.3 基本功能

(1) 靜態資源的web服務器程序員

(2) http的反向代理服務器web

(3) pop3, smpt, imap4等郵件協議的反向代理

(4) 能緩存打開的文件(元數據),支持FastCGI (php-fpm),uWSGI(Python Web Framework)等協議

(5) 模塊化,好比一些著名的模塊功能:壓縮模塊zip,SSI模塊,SSL模塊...

1.4 架構簡介

nginx架構文檔地址:http://www.aosabook.org/en/nginx.html

 

 

 

 說明: 

  (1) master/worker 一個master進程,能夠生成一個或者多個worker進程,其中

    maseter: 加載配置文件、管理worker進程、平滑升級

    worker: Http服務,http代理,fastcig代理...

  (2) 支持Advanced I/O,sendfile, AIO, mmap etc

  (3) 支持Multiplexing via kevent 事件驅動機制,在Linux上是epoll,在FreeBSD上是kqueue,在Solaris上市/dev/poll

  (4) 代理時還支持緩存功能:有2個組件Cache loader, Cache manager

  (5) 模塊類型:

      核心模塊:core module

      Standard HTTP module

      Optional HTTP modules

      Mail Modules

      3rd party modules

 

1.5 安裝

Nginx的一些模塊須要其餘第三方庫的支持:
gzip須要zlib
rewrite須要pcre
ssl須要openssl
所以,若是在centos環境下:

yum -y install zlib zlib-devel openssl openssl-devel pcre pcre-devel

支持centos通用軟件的大多數安裝方式。

(1) yum源安裝

由epel(著名可信任的第三方Yum源)提供,所以須要配置epel源,這裏簡單配置一個阿里的epel源,虛擬機是Centos7:

 wget -P /etc/yum.repos.d/ http://mirrors.aliyun.com/repo/epel-7.repo  
yum info nginx #查看nginx版本

發現yum源中提供的nginx版本是:

Available Packages
Name        : nginx
Arch        : x86_64
Epoch       : 1
Version     : 1.10.2
Release     : 1.el7
Size        : 505 k
Repo        : epel
Summary     : A high performance web server and reverse proxy server
URL         : http://nginx.org/
License     : BSD
Description : Nginx is a web server and a reverse proxy server for HTTP, SMTP, POP3 and
            : IMAP protocols, with a strong focus on high concurrency, performance and low
            : memory usage.

 

(2) 源碼編譯安裝

# 準備編譯環境:
yum groupinstall "Development Tools" "Server Platform Development"
# 若是須要ssl模塊,依賴於ssl
yum install -y openssl-devel
# 若是用到url重寫,依賴於pcre
yum install -y pcre-devel
# 若是啓用壓縮
yum install -y zlib
useradd -r nginx
# 下載源代碼,這裏用的版本是1.8.1,而且解壓縮到/usr/local目錄下
# 查看幫助: ./configure --help | less
./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 --lock-path=/var/lock/nginx.lock --with-http_ssl_module --with-http_stub_status_module --with-http_gzip_static_module --with-debug
make && make install

 

 2、基本配置

官方文檔:http://nginx.org/en/docs/

主配置文件nginx.conf,主配置文件中可使用Include的方式引入其餘的配置文件,注意配置文件中每一個指令都必須以;結尾,而且支持使用變量以及自定義變量的方式。

首先來看一個簡單的配置以瞭解其大致結構:

# For more information on configuration, see:
#   * Official English Documentation: http://nginx.org/en/docs/
#   * Official Russian Documentation: http://nginx.org/ru/docs/

# 使用的用戶和組
user nginx;
# 指定工做衍生的進程數(通常等於CPU的總數或者總核數的2倍)
worker_processes 2;
# 指定錯誤日誌的存放路徑,級別有{debug|info|notice|warn|error|crit}
error_log /var/log/nginx/error.log crit;
# 指定pid存放的路徑
pid /run/nginx.pid;

# Load dynamic modules. See /usr/share/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;

#指定文件描述符的數量
worker_rlimit_nofile 51200;
events {
    # 指定使用的網絡I/O模型,Linux推薦使用epoll,FreeBSD推薦kqueue
    use epoll;
    # 容許的鏈接數
    worker_connections 51200;
}

http {
    include             /etc/nginx/mime.types;
    default_type        application/octet-stream;
    # 設置字符集,若是一個網站有多種字符集這裏不設置,讓程序員在HTML經過Meta標籤設置
    #charset utf8;

    client_header_buffer_size 32k;
    large_client_header_buffers 4 32k;
    
    # 設置客戶端可以上傳文件的大小
    client_max_body_size 8m;
    sendfile            on;
    tcp_nopush          on;
    tcp_nodelay         on;
    keepalive_timeout   65;
    types_hash_max_size 2048;

    # 開啓gzip壓縮
    gzip                on;
    gzip_min_length     1k;
    gzip_buffers        4 16k;
    gzip_http_version   1.1;
    gzip_comp_level     2;
    gzip_types          text/plain application/x-javascript text/css application/xml;
    gzip_vary           on;

    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  /var/log/nginx/access.log  main;



    # Load modular configuration files from the /etc/nginx/conf.d directory.
    # See http://nginx.org/en/docs/ngx_core_module.html#include
    # for more information.
    include /etc/nginx/conf.d/*.conf;

    server {
        listen       80;
        server_name  www.ysz211.com ysz211.com;
        index        index.html index.htm index.jsp
        root         /usr/share/nginx/html;
        
        # Load configuration files for the default server block.
        include /etc/nginx/default.d/*.conf;

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

        location ~ .*\.(js|css)$ {
            expires   1h;
        }

        error_page 404 /404.html;
            location = /40x.html {
        }

        error_page 500 502 503 504 /50x.html;
            location = /50x.html {
        }
    }

# Settings for a TLS enabled server.
#
#    server {
#        listen       443 ssl http2 default_server;
#        listen       [::]:443 ssl http2 default_server;
#        server_name  _;
#        root         /usr/share/nginx/html;
#
#        ssl_certificate "/etc/pki/nginx/server.crt";
#        ssl_certificate_key "/etc/pki/nginx/private/server.key";
#        ssl_session_cache shared:SSL:1m;
#        ssl_session_timeout  10m;
#        ssl_ciphers HIGH:!aNULL:!MD5;
#        ssl_prefer_server_ciphers on;
#
#        # Load configuration files for the default server block.
#        include /etc/nginx/default.d/*.conf;
#
#        location / {
#        }
#
#        error_page 404 /404.html;
#            location = /40x.html {
#        }
#
#        error_page 500 502 503 504 /50x.html;
#            location = /50x.html {
#        }
#    }

}

經過上面配置,能夠發現:

  • 主配置即全局配置,對http模塊以及Mail模塊都會生效
  • event{...}: 事件驅動的相關配置
  • http{...}: http模塊的配置段
  • mail{...}: mail模塊的配置段,若是沒有mail模塊,則無需該配置段
  • main配置段中通常用來配置全局功能

3、虛擬主機配置

什麼是虛擬主機?
假如你要在一臺服務器上部署多個應用,或者是多個網站,你須要對服務器上的應用進行邏輯上的區分,一個虛擬主機就是一個"應用"。每臺虛擬主機均可以是一個獨立的網站,能夠有獨立的域名,具備完整的Internet服務器功能(WWW FTP Email)等,同一臺主機上的虛擬主機之間是徹底獨立的。從訪問者的角度而言,每一臺虛擬主機和一臺獨立的主機徹底同樣。

虛擬主機是邏輯上的主機概念,不是物理上的。

基於IP的虛擬主機:

Linux、FreeBSD操做系統都支持IP別名。IP別名的概念很是簡單:在一塊物理網卡上綁定多個IP地址。這裏使用ip別名來模擬基於IP的虛擬主機。

ifconfig eno16777736:1 192.168.1.210 broadcast 192.168.1.255 netmask 255.255.255.0 up
route add -host 192.168.1.210 dev eno16777736:1

相關nginx配置以下:

    server {
        listen       192.168.1.211:80;
        server_name  192.168.1.211;
        # Load configuration files for the default server block.
        access_log /var/log/nginx/server1.access.log combined;
        location / {
            root /usr/share/nginx/first;
            index index.html index.htm index.jsp;
        }
    }

    server {
        listen       192.168.1.210:80;
        server_name  192.168.1.210;
        # Load configuration files for the default server block.
        access_log /var/log/nginx/server2.access.log combined;
        location / {
            index index.html index.htm index.jsp;
            root /usr/share/nginx/second;
        }
    }

基於域名的虛擬主機:

最多見的虛擬主機。只須要把多個域名配置到DNS服務器便可。這種技術可使多個虛擬主機可使用一個IP地址,有效的解決了IP地址不足的問題。

    server {
        listen       80;
        server_name  www.ysz211.com;
        # Load configuration files for the default server block.
        access_log /var/log/nginx/server1.access.log combined;
        location / {
            root /usr/share/nginx/first;
            index index.html index.htm index.jsp;
        }
    }

    server {
        listen       80;
        server_name  web.ysz211.com;
        # Load configuration files for the default server block.
        access_log /var/log/nginx/server2.access.log combined;
        location / {
            index index.html index.htm index.jsp;
            root /usr/share/nginx/second;
        }
    }

4、日誌切割

與Nginx日誌相關的指令主要有2條,一條是log_format,用來設置日誌的格式,另一條是access_log,用來指定存放路徑、格式和緩存大小。兩條指令在Nginx配置文件中的位置能夠在http{...}之間,也能夠在虛擬主機之間,即server{....}之間。

用log_format指令來設置日誌格式:

語法:

log_format name string ...;

其中name表示定義的格式名稱,string表示格式樣式。log_format有一個默認的無須設置的combined日誌格式,至關於apachecombined日誌格式,其參數以下所示:

log_format combined '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent"';

也能夠本身定義一份日誌的記錄格式,不過要注意,log_format指令設置的name名稱要在Nginx配置文件中是不能重複的。

當有代理服務器時,後端服務器Nginx$remote_addr拿到的是ip地址,通常代理服務器會記錄X-Forwarded-For信息的IP地址,纔是真是IP。此時能夠自定義mylogformat

log_format mylogformat '$http_x_forwarded_for - [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent"';

用access_log指令指定日誌存放的路徑:

語法:

access_log path [format [buffer=size] [gzip[=level]] [flush=time] [if=condition]];
access_log off;

其中path表示存放路徑,format表示格式名稱,buffer=size表示內置緩衝區的大小。

用法以下:
(1) access_log off 表示關閉日誌
(2) 可使用默認的combined格式的日誌,示例:

access_log /data1/logs/filename.log;

或者

access_log /data1/logs/filename.log combined;

(3) 也可使用自定義的日誌記錄

access_log /data1/logs/access.log mylogformat buffer=32k;

(4) 在0.7.4以後的版本,access_log指令中的日誌文件路徑能夠包含變量,例如:

access_log /data1/logs/$server_name.log combined;

可是此時會有限制:

  • Nginx設置的用戶和組必須對該路徑有權限
  • 緩衝沒法被使用
  • 必須使用open_log_file_cache指令來設置常常被使用的日誌文件的描述符緩存來提升性能

open_log_file_cache用法:

open_log_file_cache max=N [inactive=time] [min_uses=N] [valid=time];
open_log_file_cache off;
  • max: 設置緩存中的最大文件描述符數量。若是超過,使用LRU算法清除
  • inactive:設置一個時間,若是在設置的時間內沒有使用文件描述符,則自動刪除,默認是10s
  • min_uses: 在inactive時間內,日誌文件超過被使用的次數,則日誌文件的描述符記錄緩存,默認爲1
  • valid: 設置多長時間檢查一次,查看變量指令的日誌文件路徑與文件名是否仍然存在。默認是60s。
  • off: 禁止使用緩存。

例如:

open_log_file_cache max=1000 inactive=20s min_uses=2 valied=1m;

日誌文件的切割:

生產環境中,因爲訪問日誌的文件增加速度很是快,所以,必須對日誌文件進行定時切割,即按照時間進行切割,最經常使用是按照天。
nginx不自動支持日誌的輪轉,可是若是指定了pid,可使用kill -USER1 nginx進程號的方式來讓nginx從新生成一份access_log文件。

#!/bin/bash
# 這個腳本必須在天天的00:00運行
logs_path="/data1/logs/"
yesterday_path=${logs_path}$(date -d "yesterday" + "%Y")/$(date -d "yesterday" + "%m")/
mkdir -p ${yesterday_path}
mv ${logs_path}access.log ${yesterday_path}access_$(date -d "yesterday" +"%Y%m%d").log
kill -USER1 `cat /run/nginx.pid`

最後配置crontab定時任務便可。

crontab -e
00 00 * * * /bin/bash /usr/local/nginx/sbin/cut_nginx_log.sh

附:參數說明

(1) Nginx運行基礎配置

  • use
Syntax:    use method;
Default:    —
Context:    events

 指明Linux的IO模型,不用指明,默認nginx會自動使用linux系統中最高效的方式

  •  user USERNAME [GROUPNAME];

    nginx中是master worker架構,這裏指定的是Nginx worker進程的屬組 屬主

    user nginx nginx

  • pid /PATH/TO/PID_FILE;

     指定nginx進程的pid文件

    pid /var/run/nginx.pid

  • worker_rlimit_nofile #;

     指定一個worker進程所能打開的最大文件描述數量;一個worker進程要支持併發,linux到處皆文件,一個鏈接至少一個socket文件

(2) 性能優化基礎配置

  • worker_processes #;

    用來指定worker進程的個數,統統常是物理CPU核心數量-1

    能夠設定爲"auto",實現自動設定爲當前CPU核心數量

  • worker_cpu_affinity CPUMASK CPUMARK ...;

    CPUMASK: 

         0000 0001

         0000 0010

         0000 0100

         ...

    worker和CPU綁定,無論worker運行的cpu如何切換,只能在指定的cpu上,綁定以後可使用命令ps axo command,pid,psr查看綁定狀況

  • worker_priority nice;

    指明進程的nice值[-20,19] ,nice值越小,優先級越高

  • accept_mutex 
Syntax:    accept_mutex on | off;
Default:    
accept_mutex off;
Context:    events

  接收請求的互斥機制,是否讓worker依次接收用戶請求,不然當一個請求報文到達,全部的worker都會被Notfied。不過在支持epoll()的linux內核中,若是使用時reuseport參數能夠不用配置這個。注意,在1.11.3版本以前的默認值是on。

  • lock_file
Syntax:    lock_file file;
Default:    
lock_file logs/nginx.lock;
Context:    main

  想要用accept_mutex必須利用到共享鎖文件。

 

(3) 調試基礎配置

  • daemon off|on;

    是否以守護進程運行nginx

  • master_process on|off;

     是否以master/worker模型運行nginx,正常狀況使用,調試模式下能夠關閉

  • error_log /PATH/TO/ERROR_LOG level;

     錯誤日誌文件及其類別;出於調試的須要;能夠設定爲debug:可是debug僅在編譯時候使用了 "--with-debug"選項時纔有效

 

http模塊配置

套接字以及主機相關的指令

1. server

server{

  listen PORT;

  server_name NAME;

  root /PATH/TO/DOCUMENTROOT;

}

 ...

注意

  (1) 基於port; listen在不一樣的端口

  (2) 基於hostname server_name指令指向不一樣的主機名

2. listen

Syntax:    
listen address[:port] [default_server] [ssl] [http2 | spdy] [proxy_protocol] [setfib=number] [fastopen=number] [backlog=number] [rcvbuf=size] [sndbuf=size] [accept_filter=filter] [deferred] [bind] [ipv6only=on|off] [reuseport] [so_keepalive=on|off|[keepidle]:[keepintvl]:[keepcnt]]; listen port [default_server] [ssl] [http2 | spdy] [proxy_protocol] [setfib=number] [fastopen=number] [backlog=number] [rcvbuf=size] [sndbuf=size] [accept_filter=filter] [deferred] [bind] [ipv6only=on|off] [reuseport] [so_keepalive=on|off|[keepidle]:[keepintvl]:[keepcnt]]; listen unix:path [default_server] [ssl] [http2 | spdy] [proxy_protocol] [backlog=number] [rcvbuf=size] [sndbuf=size] [accept_filter=filter] [deferred] [bind] [so_keepalive=on|off|[keepidle]:[keepintvl]:[keepcnt]]; Default: listen *:80 | *:8000; Context: server

 

    default_server: 說明是默認虛擬主機,即當客戶端使用ip訪問或者使用任意不能找到對應虛擬主機時使用的默認虛擬主機
    ssl: 限制只能經過ssl鏈接提供服務

    backlog=#: 後緩隊列的長度

    rcvbuf=#: 接收緩衝大小

    sndbuf=#: 發送緩衝區大小

 3. server_name name ....;

  指明當前虛擬主機的主機名,後面可使用一個或者多個空白字符分隔的多個主機,支持使用*表示任意長度,支持~開始表示的正則表達式

  當一個客戶端的請求中的主機名能夠和多個虛擬主機名相匹配時,依照以下的次序進行匹配:

  首先,精確匹配 www.baidu.com

  其次, 左側匹配 *.baidu.com

  右側匹配:www..baidu.*

  正則表達式: ~^.*\.baidu\.com$

  再找不到,就是default_server

 

4. tcp_nodelay on|off;

Syntax:    tcp_nodelay on | off;
Default:    
tcp_nodelay on;
Context:    http, server, location

  原文連接:http://www.cnblogs.com/yezuozuoloveqi/articles/4705607.html

  keepalive模式下的鏈接是否使用TCP_NODELAY選項

   TCP_NODELAY和TCP_CORK基本上控制了包的「Nagle化」,Nagle化在這裏的含義是採用Nagle算法把較小的包組裝爲更大的幀。JohnNagle是Nagle算法的發明人,後者就是用他的名字來命名的,他在1984年首次用這種方法來嘗試解決福特汽車公司的網絡擁塞問題(欲瞭解詳情請參看IETFRFC896)。他解決的問題就是所謂的silly window syndrome,中文稱「愚蠢窗口症候羣」,具體含義是,由於廣泛終端應用程序每產生一次擊鍵操做就會發送一個包,而典型狀況下一個包會擁有一個字節的數據載荷以及40個字節長的包頭,因而產生4000%的過載,很輕易地就能令網絡發生擁塞,。Nagle化後來成了一種標準而且當即在因特網上得以實現。它如今已經成爲缺省配置了,但在咱們看來,有些場合下把這一選項關掉也是合乎須要的。
如今讓咱們假設某個應用程序發出了一個請求,但願發送小塊數據。咱們能夠選擇當即發送數據或者等待產生更多的數據而後再一次發送兩種策略。若是咱們立刻發送數據,那麼交互性的以及客戶/服務器型的應用程序將極大地受益。若是請求當即發出那麼響應時間也會快一些。以上操做能夠經過設置套接字的TCP_NODELAY=on選項來完成,這樣就禁用了Nagle算法。
另一種狀況則須要咱們等到數據量達到最大時才經過網絡一次發送所有數據,這種數據傳輸方式有益於大量數據的通訊性能,典型的應用就是文件服務器。應用Nagle算法在這種狀況下就會產生問題。可是,若是你正在發送大量數據,你能夠設置TCP_CORK選項禁用Nagle化,其方式正好同TCP_NODELAY相反(TCP_CORK和TCP_NODELAY是互相排斥的)。

 

5. tcp_nopush

 linux 下是tcp_cork,上面的意思就是說,當使用sendfile函數時,tcp_nopush才起做用,它和指令tcp_nodelay是互斥的。tcp_cork是linux下tcp/ip傳輸的一個標準了,這個標準的大概的意思是,通常狀況下,在tcp交互的過程當中,當應用程序接收到數據包後立刻傳送出去,不等待,而tcp_cork選項是數據包不會立刻傳送出去,等到數據包最大時,一次性的傳輸出去,這樣有助於解決網絡堵塞,已是默認了。
也就是說tcp_nopush = on 會設置調用tcp_cork方法,這個也是默認的,結果就是數據包不會立刻傳送出去,等到數據包最大時,一次性的傳輸出去,這樣有助於解決網絡堵塞。
以快遞投遞舉例說明一下(如下是個人理解,也許是不正確的),當快遞東西時,快遞員收到一個包裹,立刻投遞,這樣保證了即時性,可是會耗費大量的人力物力,在網絡上表現就是會引發網絡堵塞,而當快遞收到一個包裹,把包裹放到集散地,等必定數量後統一投遞,這樣就是tcp_cork的選項乾的事情,這樣的話,會最大化的利用網絡資源,雖然有一點點延遲。
對於nginx配置文件中的tcp_nopush,默認就是tcp_nopush,不須要特別指定,這個選項對於www,ftp等大文件頗有幫助

 

6. sendfile on|off

如今流行的web 服務器裏面都提供 sendfile 選項用來提升服務器性能,那到底sendfile是什麼,怎麼影響性能的呢?sendfile其實是 Linux2.0+之後的推出的一個系統調用,web服務器能夠經過調整自身的配置來決定是否利用sendfile這個系統調用。先來看一下不用sendfile的傳統網絡傳輸過程:

1 read(file,tmp_buf, len);
2 write(socket,tmp_buf, len);

硬盤 >> kernel buffer >> user buffer>> kernel socket buffer >>協議棧

通常來講一個網絡應用是經過讀硬盤數據,而後寫數據到socket來完成網絡傳輸的。上面2行代碼解釋了這一點,不過上面2行簡單的代碼掩蓋了底層的不少操做。來看看底層是怎麼執行上面2行代碼的:

  1. 系統調用read()產生一個上下文切換:從user mode切換到kernel mode,而後DMA執行拷貝,把文件數據從硬盤讀到一個kernel buffer裏。
  2. 數據從kernel buffer拷貝到 user buffer,而後系統調用 read()返回,這時又產生一個上下文切換:從kernel mode 切換到user mode。
  3. 系統調用write()產生一個上下文切換:從user mode切換到kernel mode,而後把步驟2讀到user buffer的數據拷貝到kernel buffer(數據第2次拷貝到 kernel buffer),不過此次是個不一樣的kernelbuffer,這個buffer和socket相關聯。
  4. 系統調用write()返回,產生一個上下文切換:從 kernel mode 切換到 user mode(第4次切換了),而後 DMA 從 kernel buffer拷貝數據到協議棧(第4次拷貝了)。

上面4個步驟有4次上下文切換,有4次拷貝,咱們發現若是能減小切換次數和拷貝次數將會有效提高性能。在kernel2.0+版本中,系統調用sendfile()就是用來簡化上面步驟提高性能的。sendfile()不但能減小切換次數並且還能減小拷貝次數。


再來看一下用sendfile()來進行網絡傳輸的過程:

sendfile(socket,file, len);
硬盤 >> kernel buffer (快速拷貝到kernelsocket buffer) >>協議棧

  1. 系統調用sendfile()經過DMA把硬盤數據拷貝到kernel buffer,後數據被kernel直接拷貝到另一個與socket相關的kernel buffer。這裏沒有user mode和kernel mode之間的切換,在kernel中直接完成了從一個buffer到另外一個buffer的拷貝。
  2. DMA把數據從kernelbuffer直接拷貝給協議棧沒有切換,也不須要數據從user mode拷貝到kernel mode,由於數據就在kernel裏。

步驟減小了,切換減小了,拷貝減小了,天然性能就提高了。這就是爲http://write.blog.csdn.net/postedit什麼說在Nginx配置文件裏打開sendfile on選項能提升web server性能的緣由。

 

路徑相關的配置

7.  root

Syntax:    root path;
Default:    
root html;
Context:    http, server, location, if in location

 

   設置web資源的路徑映射地址:用於指明請求的URL對應的文檔目錄路徑,即根路徑

   可用的上下文:

    http: 表示全部的虛擬主機

    server: 某一個虛擬主機

    location: 某一個地址

      if:某個條件

 

8. location 

官方文檔:http://nginx.org/en/docs/http/ngx_http_core_module.html#location

 

Syntax:    location [ = | ~ | ~* | ^~ ] uri { ... }
location @name { ... }
Default:    —
Context:    server, location

 

  根據用戶請求的uri來匹配,根據優先級自上而下,用來對不一樣的資源作不一樣的配置

  =: URI的精確匹配

  ^~: 左半部分匹配 不區分大小寫

  ~: 正則表達式的匹配 區分大小寫

  ~*: 正則表達式匹配,不區分大小寫

  不帶符號

9. alias

Syntax:    alias path;
Default:    —
Context:    location

定義路徑別名,新的文檔映射

location ~ ^/users/(.+\.(?:gif|jpe?g|png))$ {
    alias /data/w3/images/$1;
}

/users/1.png -> /data/w3/images/1.png

 

10. index

  指明默認主頁面

 

11. error_page

Syntax:    error_page code ... [=[response]] uri;
Default:    —
Context:    http, server, location, if in location

文檔: http://nginx.org/en/docs/http/ngx_http_core_module.html#error_page

根據http資源的響應碼來實現錯誤重定向

 主要有2種用法:

 error_page 404 /404.html

 error_page 404 =200 /404.html (以指定響應狀態碼進行響應)

 /404.html 是一個url而不是文件映射

 

12. try_files

Syntax:    try_files file ... uri;
try_files file ... =code;
Default:    —
Context:    server, location

嘗試查找第1到第N-1個文件,若是找到即當作資源返回,不然,跳轉至最後一個uri(注意:必須必須不能匹配至當前的location,而應該配置到其餘的location中,不然會死循環)

 

客戶端請求相關的配置:

13. keepalive_timeout

Syntax:    keepalive_timeout timeout [header_timeout];
Default:    
keepalive_timeout 75s;
Context:    http, server, location

客戶端每一次和服務端發送請求報文,服務器端返回響應報問,每次鏈接都須要三次握手,每次斷開都須要4次握手,keepalive則能夠是虛鏈路不關閉,timeout則是keepalive的超時時長,即超出多少時間就不使用keep_alive,默認是75s,0表示禁止長鏈接

 

14. keepalive_requests

同上,表示keepalive鏈接以後所容許的最大資源數量,默認是100

15. keepalive_disable none | browser ...;

指明在何種瀏覽器中禁止keep_alive功能,none 表示哪一種都不由用

16. send_timeout #;

Syntax:    send_timeout time;
Default:    
send_timeout 60s;
Context:    http, server, location

Set a timeout for transmitting a reponse to the client. The timeout is set only between two successive write operations, not for the transmission of the whole repsonse. If the client does not receive anything within this time, the default value is 60s.

客戶端的速度很是慢或者響應報文內容很是長時,怎麼都發不完,此時必須設置一個超時時長,不能讓服務器一直陪着這個單獨的客戶端傳輸,所以須要設置超時時長。

17. client_body_buffer_size size;

Syntax:    client_body_buffer_size size;
Default:    
client_body_buffer_size 8k|16k;
Context:    http, server, location

Sets buffer size for reading client request body. In case the request body is larger than the buffer, the whole body or only its part is written to a temporary file. By default, buffer size is equal to two memory pages. This is 8K on x86, other 32-bit platforms, and x86-64. It is usually 16K on other 64-bit platforms.

接收客戶端請求報文的body部分的緩衝區大小,64位平臺通常是16K,超出緩衝區大小,暫存至磁盤上.

18. client_body_temp_path path [level1 [level2] [level3]]

Syntax:    client_body_temp_path path [level1 [level2 [level3]]];
Default:    
client_body_temp_path client_body_temp;
Context:    http, server, location

能夠分級存儲,高併發的狀況下,若是大量的請求緩衝區都放置不下,臨時文件很是多,所以咱們必須按照必定的規律進行存儲,提升查找速度,這裏指建立多少個1級目錄,2級目錄,3級目錄

/var/tmp/body 2 1 2 

說明: 2表示第一級有(2個16進制數字個數) 2^8 個第一級目錄,依次類推...

對客戶端的請求進行限制

19. limit_rate

Syntax:    limit_rate rate;
Default:    
limit_rate 0;
Context:    http, server, location, if in location

Limits the rate of response transmission to a client. The rate is specified in bytes per second.

20. limit_except

Syntax:    limit_except method ... { ... }
Default:    —
Context:    location

Limits allowed HTTP methods inside a location

limit_except GET POST{

  allow 192.168.1.0/24;

  deny all;

}

表示除了GET HEAD POST以外的方法僅僅容許192.168.1.0/24網絡中的主機使用

文件操做優化相關

21. aio

Syntax:    aio on | off | threads[=pool];
Default:    
aio off;
Context:    http, server, location
This directive appeared in version 0.8.11.

是否啓用aio

22. directio

Syntax:    directio size | off;
Default:    
directio off;
Context:    http, server, location
This directive appeared in version 0.7.7.

是否啓用直接io,即不使用緩衝,都性能有影響,可是數據更可靠,由於緩衝中的數據仍是有可能丟失的

23. open_file_cache

Syntax:    open_file_cache off;
open_file_cache max=N [inactive=time];
Default:    
open_file_cache off;
Context:    http, server, location

  經常使用的優化選項當打開較多文件的時候是否緩存, 可是nginx不會緩存文件的內容,能夠緩存如下三種信息:

    (1) 文件的描述符、文件大小和最近一次的修改時間;

    (2) 打開的目錄的結構

    (3) 不存在的文件信息,以及其餘否認回答例如沒有權限

  max=N表示緩存的最大條目的上年;一旦達到上限,使用LRU算法

  inactive=time: 非活躍時間

24. open_file_cache_errors on | off;

  是否緩存找不到其路徑的文件或者沒有權限訪問的文件相關信息

25. open_file_cache_valid time;

Syntax:    open_file_cache_valid time;
Default:    
open_file_cache_valid 60s;
Context:    http, server, location

Sets a time after which open_file_cache elements should be validated.

緩存過時算法:在open_file_cache_valid的規定時間內該資源文件必須被訪問open_file_cache_min_uses次

26. open_file_cache_min_uses

Syntax:    output_buffers number size;
Default:    
output_buffers 2 32k;
Context:    http, server, location

nginx_http_access_module相關配置:即http 訪問控制,基於ip

27. allow

Syntax:    allow address | CIDR | unix: | all;
Default:    —
Context:    http, server, location, limit_except

 

28. deny

Syntax:    deny address | CIDR | unix: | all;
Default:    —
Context:    http, server, location, limit_except

https配置模塊

關於ssl安全套接字層的具體狀況,請參照另外一篇文檔:http://www.cnblogs.com/carl10086/p/5905918.html

nginx官方https文檔:http://nginx.org/en/docs/http/ngx_http_ssl_module.html

若是你是編譯安裝且一開始指定了ssl模塊的話,配置文件中會有默認的443端口的虛擬主機配置,注意到,這裏跟httpd同樣,目前還不支持1個ip多個https虛擬主機的配置,通常狀況是這樣的,查看默認配置文件以下

 

 # HTTPS server
  
   server {
        #監聽443端口,而且強制爲ssl
        listen       443 ssl;
        #驗證證書時可能要用
        server_name  www.ysz206.com;
        #證書文件地址
       ssl_certificate      cert.pem;
       #私鑰地址
       ssl_certificate_key  cert.key;
      #ssl會話緩存
       ssl_session_cache    shared:SSL:1m;
       ssl_session_timeout  5m;
     # ssl中用到的加密算法
      ssl_ciphers  HIGH:!aNULL:!MD5;
      # 開啓偏向服務器的解密算法
      ssl_prefer_server_ciphers  on;

    location / {
        root   html;
       index  index.html index.htm;
      }
   }

說明:

Syntax:    ssl_session_cache off | none | [builtin[:size]] [shared:name:size];
Default:    
ssl_session_cache none;
Context:    http, server

 

ssl中會給服務器帶來更大的壓力,所以能夠考慮使用緩存會話來優化性能,固然這也有必定的安全風險 

ssl_session cache能夠設置以下策略

off: 不使用緩存

none: 官方說法 the use of a session cache is gently disallowed: nginx tells a client that sessions may be reuses, but does not actually store sessions parameters in the cache.

builtin: 使用OpenSSL自帶的緩存,不一樣worker間不能共享,緩存默認大小是20480個session會話。並且會形成內存碎片

shared: 由nginx實現的緩存策略,能夠被多個worker共享,相對於builtin有更高的命中率

如何在ysz206上使用ssl,很是簡單,跟httpd同樣,在nginx下面創建一個ssl文件夾,生成私鑰,生成證書,在ysz202上給證書進行簽名,簽名成功以後可使用以下配置,參考以下配置:

server {
        listen       443 ssl;
        server_name  www.ysz206.com;

        ssl_certificate      /etc/nginx/ssl/nginx.crt;
        ssl_certificate_key  /etc/nginx/ssl/nginx.key;

        ssl_session_cache    shared:SSL:1m;
        ssl_session_timeout  5m;

        ssl_ciphers  HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers  on;

        location / {
            root   html;
            index  index.html index.htm;
        }
    }

日誌模塊

官方文檔:http://nginx.org/en/docs/http/ngx_http_log_module.html

1. access_log 和 log_format

Syntax:    access_log path [format [buffer=size] [gzip[=level]] [flush=time] [if=condition]];
access_log off;
Default:    
access_log logs/access.log combined;
Context:    http, server, location, if in location, limit_except

access_log定義日誌,引用logformat中定義的格式,例如:

log_format compression '$remote_addr - $remote_user [$time_local] '
                       '"$request" $status $bytes_sent '
                       '"$http_referer" "$http_user_agent" "$gzip_ratio"';

access_log /spool/logs/nginx-access.log compression buffer=32k;

2. open_log_file_cache

linux中任何一個打開的文件均可以經過fid(文件描述符file descriptor)來追蹤

Defines a cache that stores the file descriptors of frequently used logs whose names contain variables.

在有大量日誌文件的時候,open_log_file_cache對性能的提高仍是不可忽視的

max: set the maximum number of the descriptors in a ache,即最大緩存條目,默認是10個

inactive: sets the tiime after which the cached descriptor is closed,緩存失效時長

min_uses:最少使用次數

valid: 驗證緩存條目有效性的頻率

跟以前的session緩存同樣,緩存有效性在於必須在inactive時間中最少使用min_uses次

 Example:

open_log_file_cache max=1000 inactive=20s valid=1m min_uses=2;

rewrite模塊

Syntax:    rewrite regex replacement [flag];
Default:    —
Context:    server, location, if

rewrite模塊用來重寫request URI的,在rewrite模塊中可使用pcre的正則表達式,可是正則表達式引擎都是比較消耗系統資源的。

大體流程:

  把用戶請求的URI基於regex作檢查,匹配到時替換爲replacement指定的字符串;若是是replacement是以http://或者https://開頭的絕對地址,則替換結果會以重定向的方式直接返回給客戶端,不然會在同一個location中的多個rewrite規則中自上而下逐條檢測,可使用flag來控制循環功能,經常使用的flag以下:

  last: 重寫完成以後中止對當前uri在當前location中的後續其餘重寫操做,改成對新url的新一輪處理;

  break: 重寫完成以後中止對當前uri在當前locatioin中後續其餘重寫操做;

  redirect: 重寫完成以後會返回一個客戶端的臨時重定向,由客戶端從新發起請求(302)

  permanent: 重寫完成以後會返回給客戶端一個永久的重定向,由客戶端從新對新的url發送請求(301)

 

1. rewirte指定: 重寫指令

server {
      ...
      rewrite ^(/download/.*)/media/(.*)\..*$ $1/mp3/$2.mp3 break;
      rewrite ^(/download/.*)/audio/(.*)\..*$ $1/mp3/$2.ra  break;
      return  403;
      ...
 }

使用 last有可能出現死循環,好比有一個rewrite (.*)\.txt$ $1.html last,而另外一個location中恰好有rewrite (.*)\.html $1.txt last,則會出現死循環,用break的效果可能不同,請自行測試。

 2. rewrite_log on | off;

  是否啓用重寫日誌;啓用時,日誌信息會發往錯誤日誌;

3. if指令

Syntax:    if (condition) { ... }
Default:    —
Context:    server, location

跟if語句差很少

比較表達式:
  ==,!=
  ~:模式匹配,區分字符大小寫;
  ~*:模式匹配,不區分字符大小寫;
  !~:模式不匹配,區分字符大小寫;
  !~*: 模式不匹配,不區分字符大小寫;
文件及目錄判斷:
  -f, !-f:是否存在且爲普通文件;
  -d, !-d: 是否存在且爲目錄;
  -e, !-e:是否存在;
  -x, !-x:是否存在且可執行;

demo:

if ($http_user_agent ~ MSIE) {
    rewrite ^(.*)$ /msie/$1 break;
}

if ($http_cookie ~* "id=([^;]+)(?:;|$)") {
    set $id $1;
}

if ($request_method = POST) {
    return 405;
}

if ($slow) {
    limit_rate 10k;
}

if ($invalid_referer) {
    return 403;
}

  

 4. return指令

Syntax:    return code [text];
return code URL;
return URL;
Default:    —
Context:    server, location, if

Stops processing and returns the specified code to a client. The non-standard code 444 closes a connetcion without sending a response header.

能夠返回code url,不過是重定向應該指定302,301等。

5. set指令

Syntax:    set $variable value;
Default:    —
Context:    server, location, if

用戶自定義變量

gzip模塊

用cpu的時間換取帶寬

配置demo以下:

gzip            on;
gzip_min_length 1000;
gzip_proxied    expired no-cache no-store private auth;
gzip_types      text/plain application/xml text/css application/json application/javascript
gzip_disable   msie6;
gzip_comp_level 6;

1. gzip_comp_level指令

Syntax:    gzip_comp_level level;
Default:    
gzip_comp_level 1;
Context:    http, server, location

指定壓縮比例,1-9

2.gzip_disable指令

Syntax:    gzip_disable regex ...;
Default:    —
Context:    http, server, location
This directive appeared in version 0.6.23.

有些瀏覽器不支持,regex是匹配客戶端瀏覽器類型的模式,匹配到的不進行壓縮

3. gzip_min_length

Syntax:    gzip_min_length length;
Default:    
gzip_min_length 20;
Context:    http, server, location

最小壓縮長度

 

4. gzip_http_version

Syntax:    gzip_http_version 1.0 | 1.1;
Default:    
gzip_http_version 1.1;
Context:    http, server, location

指定支持壓縮的最小http協議版本

5. gzip_types

Syntax:    gzip_types mime-type ...;
Default:    
gzip_types text/html;
Context:    http, server, location

指定壓縮額資源內容類型

6. gzip_proxied

Syntax:    gzip_proxied off | expired | no-cache | no-store | private | no_last_modified | no_etag | auth | any ...;
Default:    
gzip_proxied off;
Context:    http, server, location

Enables or disables gzipping of response for proxied requests depending on the request and response. 對代理的請求基於何種屬性判斷其是否應該啓用壓縮功能;

off: 全部被代理的請求統統禁止壓縮

expired: 若是一個響應報文首部包含expired字段,且有一個過時值,那就使用壓縮

....具體請參考文檔,大同小異

相關文章
相關標籤/搜索