Nginx基礎(chǔ)

Nginx是俄羅斯人編寫(xiě)的一款高性能的HTTP和反向代理服務(wù)器,在高連接并發(fā)的情況下,它能夠支持高達(dá)50000個(gè)并發(fā)連接數(shù)的響應(yīng),但是內(nèi)存、CPU等系統(tǒng)資源消耗卻很低,運(yùn)行很穩(wěn)定。

Nginx的優(yōu)勢(shì)

為什么選擇Nginx?因?yàn)樗哂幸韵绿攸c(diǎn):

  1. 速度快,先天的事件驅(qū)動(dòng)型設(shè)計(jì)、全異步的網(wǎng)絡(luò)I/O處理機(jī)制、極少的進(jìn)程間切換。
  2. 擴(kuò)展性強(qiáng),它支持很多第三方模塊。
  3. 可靠性好,Nginx是基于多進(jìn)程設(shè)計(jì),每個(gè)worker進(jìn)程相對(duì)獨(dú)立,master進(jìn)程在1個(gè)worker進(jìn)程出錯(cuò)時(shí)可以快速“拉起”新的worker子進(jìn)程提供服務(wù)。
  4. 低內(nèi)存消耗,10000個(gè)非活躍的HTTP Keep-Alive連接在Nginx中僅消耗2.5MB的內(nèi)存。
  5. 高并發(fā),單機(jī)支持10萬(wàn)以上的并發(fā)連接。
  6. 熱部署,master管理進(jìn)程與worker工作進(jìn)程的分離設(shè)計(jì),使得Nginx能夠提供熱部署功能。
  7. 最自由的BSD許可協(xié)議,BSD許可協(xié)議不只是允許用戶免費(fèi)使用Nginx,它還允許用戶在自己的項(xiàng)目中直接使用或修改Nginx源碼,然后發(fā)布。

Nginx先天的事件驅(qū)動(dòng)型設(shè)計(jì)、全異步的網(wǎng)絡(luò)I/O處理機(jī)制、極少的進(jìn)程間切換以及許多優(yōu)化設(shè)計(jì),都使得Nginx天生善于處理高并發(fā)壓力下的互聯(lián)網(wǎng)請(qǐng)求,同時(shí)Nginx降低了資源消耗,可以把服務(wù)器硬件資源“壓榨”到極致。

Nginx的作用

Nginx一般處于應(yīng)用的網(wǎng)關(guān)位置,常用來(lái)做靜態(tài)資源服務(wù)器、負(fù)載均衡和反向代理(路由功能)。

  • 靜態(tài)資源服務(wù)器:在mvvm模式中,充當(dāng)文件讀取職責(zé),一般用來(lái)做動(dòng)靜分離。
  • 負(fù)載均衡:對(duì)后臺(tái)服務(wù)器集群進(jìn)行負(fù)載。
  • 反向代理:域名/路徑,進(jìn)行路由選擇后臺(tái)服務(wù)器。

Nginx基礎(chǔ)概念

nginx是基于多進(jìn)程設(shè)計(jì),通過(guò)ps -ef|grep nginx我們可以查看nginx的進(jìn)程:

[root@localhost sbin]# ps -ef|grep nginx
root       7400      1  0 16:53 ?        00:00:00 nginx: master process ./nginx
nobody     9841   7400  0 17:29 ?        00:00:00 nginx: worker process
nobody     9842   7400  0 17:29 ?        00:00:00 nginx: worker process

通過(guò)命令我們可以發(fā)現(xiàn),nginx對(duì)應(yīng)了多個(gè)進(jìn)程,主進(jìn)程master和工作進(jìn)程worker一般情況下,worker進(jìn)程的數(shù)量與服務(wù)器上的CPU核心數(shù)相等,如果配置了緩存還會(huì)有緩存加載器進(jìn)程(cache loader)和緩存管理器進(jìn)程(cache manager)等。但是所用進(jìn)程都只包含一個(gè)線程,并且進(jìn)程之間主要通過(guò)共享內(nèi)存的方式來(lái)進(jìn)行通信。主進(jìn)程以root用戶權(quán)運(yùn)行,其他進(jìn)程是以nginx.config配置文件配置的用戶運(yùn)行,模式是nobody。

主進(jìn)程主要完成如下工作:

  1. 讀取并驗(yàn)正配置信息;
  2. 創(chuàng)建、綁定及關(guān)閉套接字;
  3. 啟動(dòng)、終止及維護(hù)worker進(jìn)程的個(gè)數(shù),管理worker進(jìn)程;
  4. 無(wú)須中止服務(wù)而重新配置工作特性;
  5. 重新打開(kāi)日志文件;

worker進(jìn)程主要完成的任務(wù)包括:

  1. 接收、傳入并處理來(lái)自客戶端的連接;
  2. 提供反向代理及過(guò)濾功能;
  3. nginx任何能完成的其它任務(wù);

nginx采用多進(jìn)程的方式主要是因?yàn)橐WCNginx的高可用和高可靠性。如果Nginx 使用了多線程,當(dāng)某一個(gè)第三方模塊引發(fā)了一個(gè)錯(cuò)誤,如:地址越界時(shí),就會(huì)導(dǎo)致整個(gè)Nginx全部掛掉; 而采用多進(jìn)程來(lái)實(shí)現(xiàn)時(shí),卻能很好的規(guī)避這個(gè)問(wèn)題,類(lèi)似于微服務(wù)的思想。

配置文件結(jié)構(gòu)

nginx.conf配置文件結(jié)構(gòu)如圖:

image.png
類(lèi)型 說(shuō)明
main 全局設(shè)置
events 設(shè)定nginx的工作模式及連接數(shù)上限
http 服務(wù)器相關(guān)屬性
server 虛擬主機(jī)設(shè)置
upstream 上游服務(wù)器設(shè)置,主要為反向代理、負(fù)載均衡相關(guān)配置
location URL匹配特定位置后的設(shè)置,路由分發(fā)
# ----------------全局模塊-------------------
#user  nobody; # 配置worker進(jìn)程的用戶權(quán)限
worker_processes  2; # 配置啟動(dòng)worker進(jìn)程數(shù)量

#error_log  logs/error.log; # 錯(cuò)誤日志文件
#error_log  logs/error.log  notice;  # 錯(cuò)誤日志文件和日志級(jí)別的配置
#error_log  logs/error.log  info;

#pid        logs/nginx.pid; # Nginx進(jìn)程PID存放路徑,做日志切割用

events {
    use epoll; # 設(shè)定nginx的工作模式,epoll是多路復(fù)用,可選值select ,poll,kqueue,epoll,rtsig,/dev/poll
    worker_connections  1024;  # 連接數(shù)上限
}


http {
    include       mime.types; # 引入外部文件,降低主文件的復(fù)雜度
    default_type  application/octet-stream; # 設(shè)置mime_types

    # 設(shè)置訪問(wèn)日志的格式和地址
    #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; # 配置允許sendfile方式傳輸文件,開(kāi)啟高效文件傳輸模式(zero copy 方式),避免內(nèi)核態(tài)數(shù)據(jù)和用戶態(tài)區(qū)數(shù)據(jù)之間的拷貝。
    #tcp_nopush     on; # 開(kāi)啟TCP_NOPUSH套接字(sendfile開(kāi)啟時(shí)有用)

    #keepalive_timeout  0; #  配置連接超時(shí)時(shí)間
    keepalive_timeout  65;

    #gzip  on; # 設(shè)置是否開(kāi)啟gzip壓縮模塊
    
    # 負(fù)載均衡配置,默認(rèn)使用輪詢,下面是基于權(quán)重。
    upstream nginx {
        #       ip_hash;
        server 172.17.0.4:8081 weight=2;
        server 172.17.0.5:8081 weight=1;
    }

    # 虛擬主機(jī)的配置
    server {
        listen       80; # 虛擬主機(jī)的服務(wù)端口
        server_name  localhost; # 用來(lái)指定ip或者域名,多個(gè)域名用空格分開(kāi)??梢允褂?通配符或正則表達(dá)式,如:server_name  ~^www\.(.+)\.com$;

        #charset koi8-r; # 字符集配置

        #access_log  logs/host.access.log  main;
        # 地址匹配設(shè)置,支持正則匹配,也支持條件匹配,這里是默認(rèn)請(qǐng)求地址,用戶可以location命令對(duì)nginx進(jìn)行動(dòng)態(tài)和靜態(tài)網(wǎng)頁(yè)過(guò)濾處理
        location / {
            root   html; # 虛擬主機(jī)的網(wǎng)頁(yè)根目錄
            index  index.html index.htm; # 默認(rèn)訪問(wèn)首頁(yè)文件
        }

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

        location /proxy_pass_uri {
            # 返反向代理配置
            proxy_pass http://www.xxx.com;
        }

        # proxy the PHP scripts to Apache listening on 127.0.0.1:80
        #
        #location ~ \.php$ {
        #    proxy_pass   http://127.0.0.1;
        #}

        # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
        #
        #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;
        #}

        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        #
        #location ~ /\.ht {
        #    deny  all;
        #}
    }


    # another virtual host using mix of IP-, name-, and port-based configuration
    #
    #server {
    #    listen       8000;
    #    listen       somename:8080;
    #    server_name  somename  alias  another.alias;

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


    # HTTPS server
    #
    #server {
    #    listen       443 ssl;
    #    server_name  localhost;

    #    ssl_certificate      cert.pem;
    #    ssl_certificate_key  cert.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;
    #    }
    #}

}

location 規(guī)則

語(yǔ)法:location[=|~|~*|^~|@]/uri/{...}

location 規(guī)則如下:

  1. =表示把URI作為字符串,以便與參數(shù)中的uri做完全的精準(zhǔn)匹配,如:
location = /aaa {
  # 只有用戶請(qǐng)求/aaa時(shí)才會(huì)匹配這個(gè)規(guī)則
}
  1. ~表示匹配URI時(shí)是字母大小寫(xiě)敏感的。
  2. ~*表示匹配URI時(shí)忽略字母大小寫(xiě)問(wèn)題。
  3. ^~表示匹配URI時(shí)只需要其前半部分與uri參數(shù)匹配即可。例如:
location ^~ /aaa {
  # 表示以/aaa開(kāi)頭的請(qǐng)求都會(huì)匹配這個(gè)規(guī)則
}
  1. ~*表示使用正則表達(dá)式,如:
location ~* \.(gif|jpg|png)$ {
  # 表示以.gif、.jpg和.png 結(jié)尾的請(qǐng)求都會(huì)匹配這個(gè)規(guī)則
}
image.png

Rewrite(地址從定向)

rewrite是實(shí)現(xiàn)URL重定向的重要指令,他根據(jù)regex(正則表達(dá)式)來(lái)匹配內(nèi)容跳轉(zhuǎn)到replacement,結(jié)尾是flag標(biāo)記:

  • 指令語(yǔ)法:rewrite regex replacement [flag];
  • 應(yīng)用位置:server、location、if

regex是正則表達(dá)式;replacement是替換值,新值;flag是處理標(biāo)志。

rewrite 最后一項(xiàng)flag參數(shù):

標(biāo)記符號(hào) 說(shuō)明
last 本條規(guī)則匹配完成后繼續(xù)向下匹配新的location URI規(guī)則
break 本條規(guī)則匹配完成后終止,不在匹配任何規(guī)則
redirect 返回302臨時(shí)重定向
permanent 返回301永久重定向
image.png

簡(jiǎn)單例子1:
rewrite ^/(.*) http://www.baidu.com/ permanent; # 匹配成功后跳轉(zhuǎn)到百度,執(zhí)行永久301跳轉(zhuǎn)

簡(jiǎn)單例子2:

location ~ /b/d {
    rewrite ^/  /c.html break;
    root   html/static/;
}

若rewrite正則匹配命中,則修改為path = /c.html;若不命中,就不執(zhí)行替換。命中后就變成了在html/static文件夾下查找c.html。

反向代理

server {
    listen 80;
    server_name  process.enjoy.com;

    #后臺(tái)服務(wù)原始路徑:172.17.0.4:8081/nginx/enjoy/getInfo

    #無(wú)/,訪問(wèn)路徑:http://process.enjoy.com/nginx/enjoy/getInfo
    location /nginx/enjoy { #匹配路徑/nginx/enjoy,剩余路徑/getInfo
    proxy_pass http://172.17.0.4:8081;#此處未關(guān)閉,傳遞整個(gè)路徑/nginx/enjoy/getInfo到目標(biāo)ip:port
        # proxy_pass http://172.17.0.4:8081/nginx/enjoy;
    }
    # 有/,訪問(wèn)路徑:http://process.enjoy.com/dynamic/nginx/enjoy/getInfo
    location /dynamic {#匹配路徑/dynamic,剩余路徑/nginx/enjoy/getInfo
        proxy_pass http://172.17.0.4:8081/;#此處關(guān)閉,只傳遞/nginx/enjoy/getInfo到目標(biāo)ip:port
    }

    #訪問(wèn)路徑:http://process.enjoy.com/static/a.html ---b.html/c.html   
    location /static {#匹配路徑/static,剩余路徑/a.html
    #   root html/;#root聲明,在html文件夾,查找/static/a.html文件
    }
    
    #訪問(wèn)路徑:http://process.enjoy.com/target/a.html ---b.html/c.html
    location /target {#匹配路徑/target,剩余路徑/a.html
        alias html/static/;##alias聲明,在html/static/文件夾,查找a.html文件
    }   
   
}
image.png

匹配過(guò)程

url=http://172.17.0.4:8081/nginx/enjoy/getInfo?a=1&b=2=域名+端口+path+param的匹配過(guò)程:

  1. 根據(jù)域名/IP+端口來(lái)定位虛擬主機(jī)(server)。
  2. 進(jìn)行path與location的匹配,其中完整的path=匹配path(path1)+剩余path(path2)
  3. 在根據(jù)代理規(guī)則進(jìn)行代理。

代理規(guī)則

  1. root:在目錄里查找path1+path2路徑。
  2. alias:在目錄里找path2路徑。
  3. proxy_pass= ip:port/:轉(zhuǎn)發(fā)ip+端口+path2路徑。
  4. proxy_pass= ip:port:轉(zhuǎn)發(fā)ip+端口+path1+path2路徑。
  5. 若url以/結(jié)尾,認(rèn)為是目錄,會(huì)執(zhí)行index命令,找文件路徑為目錄+path2;否則不執(zhí)行index,表示直達(dá)文件。

負(fù)載均衡配置

  • 語(yǔ)法:upstream name {...}
  • 配置塊:http

upstream塊定義了一個(gè)上游服務(wù)器的集群,便于反向代理中的proxy_pass使用。

簡(jiǎn)單例子:

upstream backend {
    # ip_hash;
    server backend1.example.com weight=2;
    server backend2.example.com weight=1;
}

server {
    location /proxy_pass_uri {
        # 返反向代理配置
        proxy_pass http://backend;
    }
}

默認(rèn)使用輪詢,可以通過(guò)weight=2來(lái)設(shè)置權(quán)重。ip_hash表示基于IP做hash,這樣可以保證同一個(gè)IP的請(qǐng)求始終落在同一個(gè)機(jī)器上。

nginx詳細(xì)配置可以參考《深入理解Nginx:模塊開(kāi)發(fā)與架構(gòu)解析(第2版)》第二章

日志配置和及切割

編寫(xiě)shell,vim /usr/local/nginx/sbin/logcut.sh:

#!/bin/bash
#設(shè)置日志文件存放目錄
LOG_HOME="/usr/local/nginx/logs/"
#備分文件名稱(chēng)
LOG_PATH_BAK="$(date -d yesterday +%Y%m%d%H%M)"
#重命名日志文件
mv ${LOG_HOME}/access.log ${LOG_HOME}/access.${LOG_PATH_BAK}.log
mv ${LOG_HOME}/error.log ${LOG_HOME}/error.${LOG_PATH_BAK}.log
#向nginx主進(jìn)程發(fā)信號(hào)重新打開(kāi)日志
kill -USR1 `cat ${LOG_HOME}/nginx.pid`

配置cron,使用crontab -e命令,將下面的代碼加到文件最后:

*/1 * * * * /usr/local/nginx/sbin/logcut.sh

然后執(zhí)行如下命令:

/etc/init.d/rsyslog start; #系統(tǒng)日志,如不開(kāi)啟,看不到定時(shí)任務(wù)日志
/etc/rc.d/init.d/crond start; #定時(shí)任務(wù)開(kāi)啟

查看系統(tǒng)日志tail -f /var/log/cron

[root@localhost logs]# tail -f /var/log/cron
May  8 18:01:01 localhost run-parts(/etc/cron.hourly)[12056]: starting 0anacron
May  8 18:01:01 localhost run-parts(/etc/cron.hourly)[12067]: finished 0anacron
May  8 18:01:01 localhost run-parts(/etc/cron.hourly)[12056]: starting mcelog.cron
May  8 18:01:01 localhost run-parts(/etc/cron.hourly)[12075]: finished mcelog.cron
May  8 18:10:01 localhost CROND[12654]: (root) CMD (/usr/lib64/sa/sa1 1 1)

Nginx的內(nèi)置變量

名稱(chēng) 說(shuō)明
$host 請(qǐng)求中的主機(jī)頭(Host)字段,如果請(qǐng)求中的主機(jī)頭不可用或者空,則為處理請(qǐng)求的server名稱(chēng)
$http_HEADER HTTP請(qǐng)求頭中的內(nèi)容,HEADER為HTTP請(qǐng)求中的內(nèi)容轉(zhuǎn)為小寫(xiě),-變?yōu)開(kāi)(破折號(hào)變?yōu)橄聞澗€),例如:$http_user_agent(Uaer-Agent的值)
$remote_addr 客戶端的IP地址。
$remote_port 客戶端的端口。
$request_method 這個(gè)變量是客戶端請(qǐng)求的動(dòng)作,通常為GET或POST。
$request_uri 這個(gè)變量等于包含一些客戶端請(qǐng)求參數(shù)的原始URI
$scheme 所用的協(xié)議,比如http或者是https
$server_name 服務(wù)器名稱(chēng)。
$server_port 請(qǐng)求到達(dá)服務(wù)器的端口號(hào)。
$server_protocol 請(qǐng)求使用的協(xié)議,通常是HTTP/1.0或HTTP/1.1。
$uri 請(qǐng)求中的當(dāng)前URI(不帶請(qǐng)求參數(shù),參數(shù)位于$args)

if語(yǔ)句,常用正則

正則 說(shuō)明
= ,!= 比較的一個(gè)變量和字符串。
~, ~* 與正則表達(dá)式匹配的變量,如果這個(gè)正則表達(dá)式中包含
-f,!-f 檢查一個(gè)文件是否存在。
-d, !-d 檢查一個(gè)目錄是否存在。
-e,!-e 檢查一個(gè)文件、目錄、符號(hào)鏈接是否存在。
-x, !-x 檢查一個(gè)文件是否可執(zhí)行。
  • 靜態(tài)資源: location ~ /rex/.*\.(htm|js|css)$
  • 域名校驗(yàn):if ( $http_origin ~ http://(.*).enjoy.com)
  • 瀏覽器校驗(yàn):if ($http_user_agent ~ Firefox)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容