Web服务之Nginx浅析
一、Nginx
? ?簡介:
? ?nginx [engine x]是Igor Sysoev編寫的一個高性能的HTTP和反向代理服務器,另外它也可以作為郵件代理服務器。
? ?在大多數情況下都是用來做靜態web服務器和反向代理服務器,在作為反向代理服務器的時候,Nginx可以對后端的real server做負載均衡,基于應用層的負載均衡,但是他僅支持一些常見的協議,如:http、mysql、ftp、smtp。
? ?特性:
? Nginx是一款面向性能設計的HTTP服務器,相較于Apache、lighttpd具有占有內存少,穩定性高等優勢。與舊版本(<=2.2)的Apache不同,nginx不采用每客戶機一線程的設計模型,而是充分使用異步邏輯,削減了上下文調度開銷,所以并發服務能力更強。整體采用模塊化設計,有豐富的模塊庫和第三方模塊庫,配置靈活。 在Linux操作系統下,nginx使用epoll事件模型,得益于此,nginx在Linux操作系統下效率相當高。同時Nginx在OpenBSD或FreeBSD操作系統上采用類似于epoll的高效事件模型kqueue。
? ?相較apache來說,Nginx在靜態web,反向代理,性能,高并發等功能上比apache要強大,但是apache在穩定性,動態網站的方面比Nginx優秀.隨著互聯網的規模越來越大,apache已經解決不了C10k(并發訪問量超過10k)的問題了,所以出現了新的應用程序,就如Nginx,目前Nginx的穩定版是1.4.x系列.
? ?Nginx在官方測試的結果中,能夠支持五萬個平行連接,而在實際的運作中,是可以支持二萬至四萬個平行鏈接。
? ?整體采用模塊化設計是nginx的一個重大特點,甚至http服務器核心功能也是一個模塊。要注意的是:nginx的模塊是靜態的,添加和刪除模塊都要對nginx進行重新編譯,這一點與Apache的動態模塊完全不同。
? ?自PHP-5.3.3起,PHP-FPM加入到了PHP核心,編譯時加上--enable-fpm即可提供支持。 PHP-FPM以守護進程在后臺運行,Nginx響應請求后,自行處理靜態請求,PHP請求則經過fastcgi_pass交由PHP-FPM處理,處理完畢后返回。 Nginx和PHP-FPM的組合,是一種穩定、高效的PHP運行方式,效率要比傳統的Apache和mod_php高出不少。
? ?
二、Nginx的HTTP特性
? 基本的HTTP服務器特性:
靜態資源的web服務器,能緩存打開的文件描述符
可以做反向代理服務器,緩存加速反向代理,簡單的負載均衡以及容錯
支持FastCGI,uwsgi,SCGI,和memcached服務的緩存加速支持
靜態模塊化架構,非DSO機制,支持多種過濾器,如gzip,SSI和圖像大小調整等
支持SSL
? ?擴展的HTTP服務器特性:
支持基于名稱和IP做虛擬主機
支持keepalive
支持平滑的升級,平滑的配置文件更新
支持定制訪問日志,支持日志緩存以提高性能,快速的日志輪轉
3xx-5xx錯誤代碼重定向
支持url rewrite
根據客戶端地址執行不同的功能支持路徑別名
支持基于IP和用戶認證
支持速率限制,并發限制
三、Nginx的基本架構
? ?Nginx會啟動一個master進程和多個worker線程/進程,每個worker進程可以響應多個請求,啟動的worker數量可以自行設置。worker進程以非特權用戶(ngnix)運行。
? ?一般而言,設置的worker數量應該比cpu的核心數少一到兩個,如24個核心的cpu,應該設置22-23個worker進程數。
? ?Nginx是基于事件驅動:kqueue,epoll(Linux),/dev/poll;支持消息通知機制:select,pool,rt signals;支持sendfile:服務器響應請求時,由內核直接響應,而不用經過用戶空間。支持文件AIO,異步IO,支持mmap,內存映射。
四、Ngnix配置文件解析
1.配置文件層次
main { //全局配置 } http{server{ //虛擬主機location ** { //URI訪問屬性}} }2.main段
? ?基礎設置 ? ?
# user username [groupname]; //指定運行worker進程的用戶和組 # worker_processes 1; //啟動的worker的數量,性能優化關鍵點 #error_log logs/error.log; //錯誤日志文件及其級別;默認為error級別;調試時可以使用debug級別,但要求在編譯時必須使用--with-debug啟用debug功能; #error_log logs/error.log notice; //同上,但是級別為notice #error_log logs/error.log info; //同上,但是級別為 info #pid logs/nginx.pid; //指定Nginx的pid文件 #events { # worker_connections 1024; //worker進程的個數;通常其數值應該為CPU的物理核心數減1或減2;Nginx的最大并發數為worker_processes*worker_connections # }? ? 擴展設置:與性能優化相關
# worker_rlimit_nofile 9999; //指定一個worker進程所能夠打開的最大文件句柄數,可以使用ulimit -n查看單個文件可以打開的最大句柄數,(socket連接也算在里面)。系統默認值1024,此值需大于等于worker_connections,但是如果是代理服務器,此值應大于等于worker_connections的兩倍 # worker_rlimit_sigpending 12; //設定每個用戶能夠發往worker進程的信號的數量 # worker_cpu_affinity cpumask; //與上面的worker_processes有關,讓worker運行在指定的cpu上,如有4顆cpu,4個process,那就分別是0001,0010,0100,1000,表示第0,1,2,3顆cpu,性能優化關鍵點 # ssl_engine ssldevice; //在存在ssl硬件加速器的服務器上,指定所使用的ssl硬件加速設備; # timer_resolution t; //每次內核事件調用返回時,都會使用gettimeofday()來更新nginx緩存時鐘;timer_resolution用于定義每隔多久才會由gettimeofday()更新一次緩存時鐘;x86-64系統上,gettimeofday()代價已經很小,可以忽略此配置; # worker_priority number; //worker的優先級,值越小,優先級越高,對于性能的增強也是很關鍵的(-20,20),默認是0,對系統的性能增強很關鍵 ? ? 擴展設置:與事件相關
? ? 擴展設置:用于調試、定位問題
// 只在調試時使用 # daemon on|off; //是否讓ningx運行后臺;默認為on,調試時可以設置為off,使得所有信息去接輸出控制臺; # master_process on|off; //是否以master/worker模式運行nginx;默認為on;調試時可設置off以方便追蹤;3.http段
# 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 0; # keepalive_timeout 65; # #gzip on; # server { //定義虛擬主機 # listen 80; //監聽的端口listen address[:port];listen port # server_name localhost; //定義基于主機名或IP的虛擬主機,可跟多個主機名 # server_name_hash_bucket_size //快速主機名查找使用hash主機名 # #charset koi8-r; # #access_log logs/host.access.log main; # location / { # root html; //設置web資源的路徑,可以放在http,server和location中 # index index.html index.htm; #定義默認主頁,自左向右匹配 # } # # #error_page 404 [=200] /404.html; #錯誤頁面重定向,[=200表示請求狀態碼也編程200] # # redirect server error pages to the static page /50x.html # error_page 500 502 503 504 /50x.html; # location = /50x.html { # root html; # } # }? ? ?server段:
# listen address[:port]; 或 # listen port; #default_server//定義此server為http中默認的server;如果所有的server中沒有任何一個listen使用此參數,那么第一個server即為默認server; # rcvbuf=SIZE//接收緩沖大小; # sndbuf=SIZE//發送緩沖大小; # ssl: https server; # server_name [...];//server_name可以跟多個主機名,名稱中可以使用通配符和正則表達式(通常以~開頭);當nginx收到一個請求時,會取出其首部的server的值,而后跟眾server_name進行比較;比較方式://(1) 先做精確匹配;www.magedu.com//(2) 左側通配符匹配;*.magedu.com//(3) 右側通配符匹配;www.abc.com, www.*//(4) 正則表達式匹配: ~^.*\.magedu\.com$ # server_name_hash_bucket_size 32|64|128;//為了實現快速主機查找,nginx使用hash表來保存主機名;系統默認沒有此項,也不是太重要 ?
? ? location段
# location [ = | ~ | ~* | ^~ ] uri { ... } //只能在server和location中,一個server中可以有多個location// =:精確匹配;優先級最高// ~:正則表達式模式匹配,匹配時區分字符大小寫//~*:正則表達式模式匹配,匹配時忽略字符大小寫//^~: URI前半部分匹配,不檢查正則表達式 # location @name { ... }//功能:允許根據用戶請求的URI來匹配指定的各location以進行訪問配置;匹配到時,將被location塊中的配置所處理; # location /i/ { # alias /data/w3/p_w_picpaths/;//路徑別名,訪問/i/top.gif時將由/data/w3/p_w_picpaths/top.gif文件來響應 # } # location ~* ^/documents/(.*)$ { # root /www/htdocs; # try_files $uri /docu/$1 /temp.html;//try_files path1 [path2 ...] uri;自左至右嘗試讀取由path所指定路徑,在第一次找到即停止并返回;如果所有path均不存在,則返回最后一個uri; # }? ? 其他參數設置:網絡連接相關
# keepalive_timeout time; //保持連接的超時時長;默認為75秒;可以定義在http, server, location中 # keepalive_requests n; //在一次長連接上允許承載的最大請求數;上下文:http,server,location # keepalive_disable [msie6 | safari | none ]; //對指定的瀏覽器禁止使用長連接;有些瀏覽器不支持長連接 # tcp_nodelay on|off; //對keepalive連接是否使用TCP_NODELAY選項;默認on;把多個確認報文合成一個響應,確認延遲 # client_header_timeout time; //讀取http請求首部的超時時長; # client_body_timeout time; //讀取http請求包體的超時時長; # send_timeout time; //發送響應的超時時長;? ? 其他參數設置:對客戶端請求限制
# limit_except method ... { ... } //指定對范圍之外的其它方法的訪問控制;指定method為GET方法的同時,nginx會自動添加HEAD方法。上下文:location如: limit_except GET {allow 192.168.1.0/32;deny all;}請留意上面的例子將對除GET和HEAD方法以外的所有HTTP方法的請求進行訪問限制。 # client_max_body_size SIZE; //http請求包體的最大值;常用于限定客戶所能夠請求的最大包體;根據請求首部中的Content-Length來檢測,以避免無用的傳輸;上下文:http, server, location # limit_rate speed; //限制客戶端每秒鐘傳輸的字節數;默認為0,表示沒有限制;上下文:http, server, location, # limit_rate_after time; //nginx向客戶發送響應報文時,如果時長超出了此處指定的時長,則后續的發送過程開始限速;如:下載站上下文:http, server, location,? ? 其他參數設置:對客戶端請求的特殊處理
# ignore_invalid_headers on|off//是否忽略不合法的http首部;默認為on; off意味著請求首部中出現不合規的首部將拒絕響應;只能用于server和http; # log_not_found on|off;//是否將文件找不到的信息也記錄進錯誤日志中;默認為on;上下文:http, server, location # resolver address;//指定nginx使用的dns服務器地址;上下文: http, server, location # resover_timeout time;//指定DNS解析超時時長,默認為30s,建議5秒; 上下文:http, server, location # server_tokens on|off;//是否在錯誤頁面中顯示nginx的版本號;默認on,上下文:http, server, location? ? 其他參數設置:文件操作的優化
# sendfile on|off//是否啟用sendfile功能;由內核直接響應用戶請求,默認off上下文:http, server, location, if in location # aio on|off//是否啟用aio功能;完全異步 # open_file_cache max=N [inactive=time]|off//是否打開文件緩存功能;上下文: http, server, locationmax: 緩存條目的最大值;當滿了以后將根據LRU(最近最少使用)算法進行置換;inactive: 某緩存條目在指定時長時沒有被訪問過時,將自動被刪除;默認為60s;緩存的信息包括: 文件句柄、文件大小和上次修改時間;已經打開的目錄結構;沒有找到或沒有訪問權限的信息; # open_file_cache_errors on|off//是否緩存文件找不到或沒有權限訪問等相關信息;默認off;上下文:http, server, location # open_file_cache_valid time;//多長時間檢查一次緩存中的條目是否超出非活動時長,默認為60s; 上下文:http, server, location # open_file_cache_min_use #;//在inactive指定的時長內被訪問超此處指定的次數地,才不會被刪除;默認1分鐘;上下文:http, server, location? ?http核心模塊的內置變量
# $uri: #當前請求的uri,不帶參數;參數 ?=12等之類的 # $request_uri: #請求的uri,帶完整參數; # $host: #http請求報文中host首部;如果請求中沒有host首部,則以處理此請求的虛擬主機的主機名代替; # $hostname: #nginx服務運行在的主機的主機名; # $remote_addr: #客戶端IP # $remote_port: #客戶端Port # $remote_user: #使用用戶認證時客戶端用戶輸入的用戶名; # $request_filename: #用戶請求中的URI經過本地root或alias轉換后映射的本地的文件路徑;用的很多 # $request_method: #請求方法 # $server_addr: #服務器地址 # $server_name: #服務器名稱 # $server_port: #服務器端口 # $server_protocol: #服務器向客戶端發送響應時的協議,如http/1.1, http/1.0 # $scheme: #在請求中使用scheme, 如https://www.magedu.com/中的https; # $http_HEADER: #匹配請求報文中指定的HEADER,$http_host匹配請求報文中的host首部 # $sent_http_HEADER: #匹配響應報文中指定的HEADER,例如$http_content_type匹配響應報文中的content-type首部; # $document_root: #當前請求映射到的root配置;五、Nginx編譯安裝
1)部署開發環境 # yum -y install "Development tools" "Server Platform Development" 2)解決依賴 pcre-devel openssl-devel # yum -y install pcre-devel openssl-devel 3) 設置用戶 # groupadd -r nginx # useradd -r -g nginx nginx 4)編譯安裝nginx-1.4.7 # tar xf nginx-1.4.7.tar.gz # cd nginx-1.4.7 # ./configure --prefix=/usr --sbin-path=/usr/sbin/nginx \ --conf-path=/etc/nginx/nginx.conf --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 \--user=nginx --group=nginx --with-http_ssl_module \ --with-http_flv_module --with-http_stub_status_module \ --with-http_gzip_static_module --http-client-body-temp-path=\ /var/tmp/nginx/client/ --http-proxy-temp-path=/var/tmp/nginx/proxy/ \ --http-fastcgi-temp-path=/var/tmp/nginx/fcgi/ \ --http-uwsgi-temp-path=/var/tmp/nginx/uwsgi --http-scgi-temp-path=\ /var/tmp/nginx/scgi --with-pcre # make && make install 5)檢測配置文件語法 # /usr/sbin/nginx -t 6) 提供啟動腳本 # vim /etc/rc.d/init.d/nginx內容如下 # 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 0nginx="/usr/sbin/nginx" prog=$(basename $nginx)NGINX_CONF_FILE="/etc/nginx/nginx.conf"[ -f /etc/sysconfig/nginx ] && . /etc/sysconfig/nginxlockfile=/var/lock/subsys/nginxmake_dirs() {# make required directoriesuser=`nginx -V 2>&1 | grep "configure arguments:" | sed 's/[^*]*--user=\([^ ]*\).*/\1/g' -`options=`$nginx -V 2>&1 | grep 'configure arguments:'`for opt in $options; doif [ `echo $opt | grep '.*-temp-path'` ]; thenvalue=`echo $opt | cut -d "=" -f 2`if [ ! -d "$value" ]; then# echo "creating" $valuemkdir -p $value && chown -R $user $valuefifidone }start() {[ -x $nginx ] || exit 5[ -f $NGINX_CONF_FILE ] || exit 6make_dirsecho -n $"Starting $prog: "daemon $nginx -c $NGINX_CONF_FILEretval=$?echo[ $retval -eq 0 ] && touch $lockfilereturn $retval }stop() {echo -n $"Stopping $prog: "killproc $prog -QUITretval=$?echo[ $retval -eq 0 ] && rm -f $lockfilereturn $retval }restart() {configtest || return $?stopsleep 1start }reload() {configtest || return $?echo -n $"Reloading $prog: "killproc $nginx -HUPRETVAL=$?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" instart)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 7)添加到系統服務并開機啟動 # chkconfig --add nginx # chkconfig nginx on # chkconfig --list nigx 8) 設置nginx配置文件的語法高亮 # mkdir ./vim/syntax -pv # cd .vim/syntax # wget http://www.vim.org/scripts/download_script.php?src_id=19394 # cd .vim # vim filetype.vim 內容如下au BufRead,BufNewFile /etc/nginx/*,/usr/local/nginx/conf/* if &ft == '' | setfiletype nginx | endif 9)啟動服務 # service nginx start # pa aux | grep nginx
六、配置使用Nginx
1.配置虛擬主機
server {listen 80;server_name www.a.com;root /web/a }2.設置訪問控制access模塊,只有兩個選項:allow和deny
server {listen 80;server_name www.a.com;root /web/a;allow 192.168.0.0/16;deny all;}3.用戶認證
location /admin/ {auth_basic "admin";auth_basic_user_file /etc/nginx/.htpasswd;root /web/a/;} # 使用htpasswd -c -m /path/to/somefile username 創建密碼文件4.下載點設置
5.SSL示例
6.stub_status狀態頁
location /server-status {stub_status on;}7.gzip壓縮
http {gzip on; #開啟壓縮功能,可以放在http,servergzip_http_version 1.0; #壓縮后使用那種http協議構建響應報文gzip_comp_level 2; #壓縮級別gzip_types text/plain text/css application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript application/json; #僅對這些格式的內容進行壓縮gzip_disable msie6; #對IE6不使用壓縮機制}8.URL rewrite, 地址重寫
# rewrite regex replacement [flag]; //上下文 server,location,ifflag參數:last:停止執行當前這一輪的ngx_http_rewrite_module指令集,然后查找匹配改變后URI的新location;break:停止執行當前這一輪的ngx_http_rewrite_module指令集;redirect:在replacement字符串未以“http://”或“https://”開頭時,使用返回狀態碼為302的臨時重定向;permanent:返回狀態碼為301的永久重定向。 # rewrite_log on|off //開啟或者關閉將ngx_http_rewrite_module模塊指令的處理日志以notice級別記錄到錯誤日志中。默認為off; # return code //用于結束rewrite規則,并且為客戶返回狀態碼;可以使用的狀態碼有204, 400, 402-406, 500-504等; location /down/ { #可以沒有down1文件夾root /web/b;rewrite ^/down1/(.*\.(jpg|gif|png))$ /p_w_picpath/$1 last;#訪問網址是www.a.com/down1,實際目錄是www.a.com/p_w_picpath}9.防盜鏈
#ngx_http_referer_module//此模塊允許攔截“Referer”請求頭中含有非法值的請求,阻止它們訪問站點。 需要注意的是偽造一個有效的“Referer”請求頭是相當容易的, 因此這個模塊的預期目的不在于徹底地阻止這些非法請求,而是為了阻止由正常瀏覽器發出的大規模此類請求。 還有一點需要注意,即使正常瀏覽器發送的合法請求,也可能沒有“Referer”請求頭。 定義: # location /photos/ { # valid_referers none blocked server_names # *.example.com example.* www.example.org/galleries/ # ~\.google\.; # if ($invalid_referer) {//如果是以上指定范圍外的,則返回 403錯誤 # return 403; # } # } 該指令的參數:none # 缺少“Referer”請求頭;blocked # “Referer” 請求頭存在,但是它的值被防火墻或者代理服務器刪除; 這些值都不以“http://” 或者 “https://”字符串作為開頭;server_names # “Referer” 請求頭包含某個虛擬主機名;轉載于:https://blog.51cto.com/hoolee/1413195
總結
以上是生活随笔為你收集整理的Web服务之Nginx浅析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: MVC, MVP, MVVM比较以及区别
- 下一篇: 细说Nginx配置文件