nginx-知識點整理

一、Nginx Proxy代理

1、代理原理

(1)反向代理:需要有一個負(fù)載均衡設(shè)備(即反向代理服務(wù)器)來分發(fā)用戶請求,將用戶請求分發(fā)到后端正真提供服務(wù)的服務(wù)器上。服務(wù)器返回自己的服務(wù)到負(fù)載均衡設(shè)備,負(fù)載均衡設(shè)備將服務(wù)器的服務(wù)返回用戶。
(2)正向代理:正向代理的過程隱藏了真實的請求客戶端,服務(wù)器不知道真實的客戶端是誰,客戶端請求的服務(wù)都被代理服務(wù)器代替請求。我們常說的代理也就是正向代理,正向代理代理的是請求方,也就是客戶端。

2、正向和反代的區(qū)別?

正向代理中代理的對象是客戶端。
反向代理中代理的對象是服務(wù)端。

3、nginx Proxy 配置

代理模塊:ngx_http_proxy_module
模擬:兩臺Nginx真實服務(wù)器

a、Nginx-1 啟動網(wǎng)站(內(nèi)容)
IP:192.168.124.19 已編譯安裝好,檢查Nginx是否啟動,是否可以訪問。
b、Nginx-2啟動代理程序
IP:192.168.124.20
yum直接安裝,啟動
編輯nginx的配置文件

[root@nginx-server ~]# vim /etc/nginx/conf.d/default.conf
server {
    server {
    listen       80;
    server_name  localhost;

    location / {
    proxy_pass http://192.168.124.19:80;
    proxy_redirect default;
    proxy_set_header Host $http_host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

    proxy_connect_timeout 30;
    proxy_send_timeout 60;
    proxy_read_timeout 60;
    }
}
重新加載nginx配置文件
[root@nginx-server ~]# nginx -s reload

c、使用pc客戶端訪問Nginx-2服務(wù)器地址或域名,也就是http://192.168.124.20,成功訪問Nginx-1服務(wù)器頁面
d、觀察Nginx-1服務(wù)器的日志
訪問成功,記錄了客戶端的IP和代理服務(wù)器的IP。

二、Nginx負(fù)載均衡

1、upstream配置

這個配置是寫一組被代理的服務(wù)器地址,然后配置負(fù)載均衡的算法。

upstream testapp { 
      server 10.0.105.199:8081;
      server 10.0.105.202:8081;
    }
 server {
        ....
        location / {         
           proxy_pass  http://testapp;  #請求轉(zhuǎn)向 testapp 定義的服務(wù)器列表         
        } 
2、負(fù)載均衡算法

1、輪詢(默認(rèn)):每個請求按時間順序逐一分配到不同的后端服務(wù)器;
2、ip_hash:每個請求按訪問IP的hash結(jié)果分配,同一個IP客戶端固定訪問一個后端服務(wù)器??梢员WC來自同一ip的請求被打到固定的機(jī)器上,可以解決session問題。
3、url_hash:按訪問url的hash結(jié)果來分配請求,使每個url定向到同一個后端服務(wù)器。
4、fair:此種算法可以依據(jù)頁面大小和加載時間長短智能地進(jìn)行負(fù)載均衡,也就是根據(jù)后端服務(wù)器的響應(yīng)時間來分配請求,響應(yīng)時間短的優(yōu)先分配。Nginx本身是不支持 fair的,如果需要使用這種調(diào)度算法,必須下載Nginx的 upstream_fair模塊。

配置實例
1、熱備:如果有兩臺服務(wù)器,當(dāng)一個服務(wù)器發(fā)生事故的時候,才啟動第二臺服務(wù)器給提供服務(wù)。

upstream myweb { 
      server 172.17.14.2:8080; 
      server 172.17.14.3:8080 backup;  #熱備     
    }

2、輪詢:nginx默認(rèn)就是輪詢其權(quán)重都默認(rèn)1

upstream myweb { 
      server 172.17.14.2:8080; 
      server 172.17.14.3:8080;      
    }

3、加權(quán)輪詢:根據(jù)配置的權(quán)重大小二分發(fā)給不用服務(wù)器數(shù)量的請求。

upstream myweb { 
      server 172.17.14.2:8080 weight=1;
      server 172.17.14.3:8080 weight=2;
}

4、ip_hash:nginx會讓相同的客戶端IP請求相同的服務(wù)器。

upstream myweb { 
      server 172.17.14.2:8080; 
      server 172.17.14.3:8080;
      ip_hash;
    }

5、Nginx負(fù)載均衡配置狀參數(shù)

upstream myweb { 
      server 172.17.14.2:8080 weight=2 max_fails=2 fail_timeout=2;
      server 172.17.14.3:8080 weight=1 max_fails=2 fail_timeout=1;    
    }
down:表示當(dāng)前的server暫時不參與負(fù)載均衡
backup:預(yù)留的備份機(jī)器
max_fails:允許請求失敗的次數(shù),默認(rèn)為1。當(dāng)超過最大次數(shù)時,返回proxy_next_upstream 模塊定義的錯誤。
fail_timeout:經(jīng)歷了max_fails失敗后。暫停服務(wù)的時間單位秒。max_fails可以和fail_timeout一起使用。
3、Nginx會話保持

有以下幾種實現(xiàn)方式:
1、ip_hash
使用源地址哈希算法,將同一客戶端的請求總是發(fā)送同一個后端服務(wù)器。

upstream backend {
    ip_hash;
    server backend1.example.com;
    server backend2.example.com;
    server backend3.example.com down;
}

ip_hash簡單易用,但有如下的問題:
當(dāng)后端服務(wù)器宕機(jī)后,session會丟失;
來自同一個局域網(wǎng)的客戶端會被轉(zhuǎn)發(fā)到同一個后端服務(wù)器,可能會導(dǎo)致負(fù)載失衡;

2、sticky_cookie_insert
使用這個模塊會讓來自同一個客戶端的請求被傳遞到一組服務(wù)器的同一臺服務(wù)器,與ip_hash不同之處是,它不是基于IP來判斷客戶端的,而是基于cookie來判斷(需要引用第三方模塊才能實現(xiàn))
sticky模塊語法:

upstream backend {
    server backend1.example.com;
    server backend2.example.com;
    sticky_cookie_insert srv_id expires=1h domain=3evip.cn path=/;
}

expires:設(shè)置瀏覽器中保持cookie的時間
domain:定義cookie的域
path:為cookie定義路徑

3、jvm_route方式

通過session_cookie這種方式實現(xiàn)session粘性,將特定會話附屬到特定的tomcat上,從而解決session不同步問題,但是無法解決宕機(jī)后會話轉(zhuǎn)移問題。如果cookie和url中并沒有session,則這只是個簡單的round-robin負(fù)載均衡。

jvm_route原理:
1.一開始請求過來,沒有帶session信息,jvm_round就會根據(jù)round robin的方法,發(fā)到一臺Tomcat上面。
2.Tomcat添加上session信息,并返回給客戶。
3.用戶再次請求,jvm_route看到session中有后端服務(wù)器的名稱,它就會把請求轉(zhuǎn)發(fā)到對應(yīng)的服務(wù)器上。

三、Nginx實現(xiàn)動靜分離

為了加快網(wǎng)站的解析速度,可以把動態(tài)頁面和靜態(tài)頁面由不同的服務(wù)器來解析,加快解析速度。降低原來單個服務(wù)器的壓力。

準(zhǔn)備環(huán)境

3臺機(jī)器,一個做Nginx代理,一個http處理動態(tài),一個http處理靜態(tài),三臺機(jī)器都裝Nginx。
代理:192.168.124.10
http:192.168.124.11(動態(tài))192.168.124.12(靜態(tài))

1、配置nginx反向代理upstream(192.168.124.10)

upstream static {
        server 192.168.124.11:80 weight=1 max_fails=1 fail_timeout=60s;
        }
upstream php {
        server 192.168.124.12:80 weight=1 max_fails=1 fail_timeout=60s;
        }
     server {
        listen      80;
        server_name     localhost
        #動態(tài)資源加載
        location ~ \.(php|jsp)$ {
            proxy_pass http://phpserver;
            proxy_set_header Host $host:$server_port;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                }
        #靜態(tài)資源加載
        location ~ .*\.(html|gif|jpg|png|bmp|swf|css|js)$ {
            proxy_pass http://static;
            proxy_set_header Host $host:$server_port;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                }
        }

2、配置靜態(tài)資源(192.168.124.11)

# #vim /etc/nginx/nginx.conf
server {
        listen 80;
        server_name     localhost;

        location ~ \.(html|jpg|png|js|css|gif|bmp|jpeg) {
        root /home/www/nginx;
        }
}

# mkdir -p /home/www/nginx
# chmod 777 /home/www/
# vim /home/www/nginx/index.html   添加內(nèi)容

3、動態(tài)資源配置(192.168.124.12)

1、yum安裝php7.1
# rpm -Uvh https://mirror.webtatic.com/yum/el7/epel-release.rpm
# rpm -Uvh https://mirror.webtatic.com/yum/el7/webtatic-release.rpm
安裝依賴
# yum install php71w-xsl php71w php71w-ldap php71w-cli php71w-common php71w-devel php71w-gd php71w-pdo php71w-mysql php71w-mbstring php71w-bcmath php71w-mcrypt -y
# yum install -y php71w-fpm
啟動
# systemctl start php-fpm && systemctl enable php-fpm
2、編輯nginx配置文件
# vim /etc/nginx/nginx.conf
server {
        listen      80;
        server_name     localhost;
        location ~ \.php$ {
            root           /home/nginx/html;  #指定網(wǎng)站目錄
            fastcgi_pass   127.0.0.1:9000;    #指定訪問地址
            fastcgi_index  index.php;       #指定默認(rèn)文件
            fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name; #站點根目錄,取決于root配置項
            include        fastcgi_params;  #包含nginx常量定義
                }
        }
3、創(chuàng)建目錄
# mkdir -p /home/nginx/html
# chmod 777 /home/nginx/
# cat /home/nginx/html/index.php
<? Hello Warld!
?>

4、測試

1、訪問http://192.168.124.10/index.html會轉(zhuǎn)發(fā)到靜態(tài)服務(wù)器,通過location正則匹配來處理請求。
2、訪問http://192.168.124.10/index.php動態(tài)頁面時location匹配到./php結(jié)尾的文件會轉(zhuǎn)發(fā)到php服務(wù)器處理請求。

四、Nginx防盜鏈

兩個網(wǎng)站 A 和 B, A網(wǎng)站引用了B網(wǎng)站上的圖片,這種行為就叫做盜鏈。 防盜鏈,就是要防止A引用B的圖片。

1、Nginx防止網(wǎng)站資源被盜用模板

ngx_http_referer_module

2、防盜鏈配置

[root@nginx-server ~]# vim /etc/nginx/nginx.conf
# 日志格式添加"$http_referer"
log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                         '$status $body_bytes_sent "$http_referer" '
                         '"$http_user_agent" "$http_x_forwarded_for"';
# valid_referers 使用方式                         
Syntax:     valid_referers none | blocked | server_names | string ...;
Default:    —
Context: server, location

解釋:
none : 允許沒有http_referer的請求訪問資源
blocked : 允許不是http://開頭的,不帶協(xié)議的請求訪問資源
server_names : 只允許指定ip/域名來的請求訪問資源(白名單

2、配置實例

準(zhǔn)備兩臺機(jī)器,兩張圖片

第一臺,配置nginx配置文件,并上傳圖片

[root@nginx-server html]# vim /etc/nginx/conf.d/nginx.conf
server {
    listen       80;
    server_name  localhost;

    location / {
         root   /usr/share/nginx/html;
         index  index.html index.htm;

         valid_referers none blocked *.baby.com 10.0.105.202;
                if ($invalid_referer) {
                   return 403;
                }
        }
    location ~  .*\.(gif|jpg|png|jpeg)$ {
         root  /usr/share/nginx/html;

         valid_referers  baby.com 10.0.105.202;
                if ($invalid_referer) {
                   return 403;
                }
        }
}

重新加載nginx服務(wù)
[root@nginx-server ~]# nginx -s reload -c /etc/nginx/nginx.conf

第二臺機(jī)器客戶端

1、配置nginx訪問頁面
[root@nginx-server ~]# vim /home/www/nginx/index.html
<html>
<head>
    <meta charset="utf-8">
    <title>qf.com</title>
</head>
<body style="background-color:red;">
    <img src="http://10.0.105.202/test.jpg"/>
</body>
</html>

2、測試不帶http_refer:
[root@nginx-server ~]# curl -I "http://10.0.105.202/test1.png"
HTTP/1.1 200 OK
Server: nginx/1.16.0
...
Connection: keep-alive
ETag: "5d14a80f-39713"
Accept-Ranges: bytes

3、測試帶非法http_refer
[root@nginx-server ~]# curl -e http://www.baidu.com -I "http:/10.0.105.202/test.jpg"
HTTP/1.1 403 Forbidden
Server: nginx/1.16.0
...
Connection: keep-alive

4、測試帶合法的http_refer
[root@nginx-server nginx]# curl -e http://10.0.105.202 -I "http://10.0.105.202/test.jpg"
HTTP/1.1 200 OK
Server: nginx/1.16.0
...
Connection: keep-alive
ETag: "5d14b683-6d39"
Accept-Ranges: bytes

五、Nginx地址重寫rewrite

1、什么是Rewrite?

Rewrite對稱URL Rewrite,即URL重寫。就是把傳入Web的請求重定向到其他URL的過程。

2、Rewrite相關(guān)指令

Nginx Rewrite相關(guān)指令有if、rewrite、set、return
應(yīng)用環(huán)境:server、location

2.1 If 指令

支持如下條件判斷匹配符號:
~                        正則匹配(區(qū)分大小寫)
~*                       正則匹配(不區(qū)分大小寫)
!~                       正則不匹配(區(qū)分大小寫)
!~*                      正則不匹配(不區(qū)分大小寫)
-f 和 !-f                用來判斷是否存在文件
-d 和 !-d                用來判斷是否存在目錄
-e 和 !-e                用來判斷是否存在文件或目錄
-x 和 !-x                用來判斷文件是否可執(zhí)行

2.2 Rewrite flag
rewrite指令根據(jù)表達(dá)式來重定向URL,或者修改字符串??梢詰?yīng)用于server,location,if環(huán)境下每行rewrite指令最后跟一個flag標(biāo)記,支持的flag標(biāo)記有:

last 表示本條規(guī)則匹配后會重新發(fā)送請求
break 本條規(guī)則匹配完成后,終止匹配,不再匹配 后面的規(guī)則
redirect 返回302臨時重定向,瀏覽器地址會顯示跳轉(zhuǎn)后的URL地址
permanent 返回301永久重定向,瀏覽器地址會顯示跳轉(zhuǎn)后URL地址

2.3 Rewrite匹配參考實例

本地解析host文件
1、# http://www.test.com/a/hhh.html  ==> http://www.test.com/b/ggg.html
location /a {
        root    /html;
        index   hhh.html index.html;
        rewrite .* /b/gggg.html permanent;
        }
    location /b {
        root    /html;
        index   ggg.html index.htm;
        }

2、# http://www.test.com/2020/a/1.html ==> http://www.tset.com/2019/a/1,html
location /2020/a {
        root    /var/www/html;
        index   1.html index.hml;
        rewrite ^/2020/(.*)$ /2019/$1 permanent;
        }
     location /2019/a {
        root    /var/www/html;
        index   1.html index.htl;
        }

3、# http://www.llf.com/a/1.html ==> http://jd.com
location /a {
        root    /html;
        if ($host ~* test.com ) {
        rewrite .* http://jd.com permanent;
        }
        }

2.4 set指令

set指令用于定義一個變量,并且賦值
應(yīng)用環(huán)境:server、location、if

應(yīng)用實例:
# http://alice.testpm.com ==> http://www.testpm.com/alice
# http://jack.testpm.com ==> http://www.testpm.com/jack
首先做本地解析域名host文件,編輯配置文件:
# vim /etc/nginx/nginx.conf
server {
    listen       80;
    server_name  www.test.com;

    location / {
         root   /usr/share/nginx/html;
         index  index.html index.htm;
         if ( $host ~* ^www.test.com$) {
                break;
                }
         if ( $host ~* "^(.*)\.test\.com$" ) {
                set $user $1;
                rewrite .* http://www.test.com/$user permanent;
                }
        }
    location /jack {
         root /usr/share/nginx/html;
         index  index.html index.hml;
        }
    location /alice {
         root /usr/share/nginx/html;
         index index.html index.hml;
        }
}

2.5 return指令

return指令用于返回狀態(tài)碼給客戶端。可以應(yīng)用于server、location、If環(huán)境下。

應(yīng)用實例:
1、如果要訪問.sh結(jié)尾的文件則返回403操作拒絕錯誤
server {
    listen       80;
    server_name  www.test.cn;
    #access_log  /var/log/nginx/http_access.log  main;
    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
        }
    location ~* \.sh$ {
        return 403;
        }
}

2、80端口轉(zhuǎn)443端口
server {
    listen       80;
    server_name  www.test.cn;
    access_log  /var/log/nginx/http_access.log  main;
    return 301 https://www.test.cn$request_uri;
}

server {
    listen 443 ssl;
    server_name www.test.cn;
    access_log  /var/log/nginx/https_access.log  main;

    #ssl on;
    ssl_certificate   /etc/nginx/cert/2447549_www.test.cn.pem;
    ssl_certificate_key  /etc/nginx/cert/2447549_www.test.cn.key;
    ssl_session_timeout 5m;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers  ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP;
    ssl_prefer_server_ciphers on;

    location / {
        root  /usr/share/nginx/html;
        index index.html index.htm;
    }
}

[root@nginx-server ~]# curl -I http://www.testpm.cn
HTTP/1.1 301 Moved Permanently
Server: nginx/1.16.0
...
Connection: keep-alive
Location: https://www.test.cn/

3、查找順序和優(yōu)先級

1、帶有"="的精確匹配優(yōu)先 (完全匹配)
2、沒有修飾符的精確匹配
3、正則表達(dá)式按照他們在配置文件中定義的順序
4、帶有"^~"修飾符的,開頭匹配
5、帶有"~"或"~*"修飾符的,如果正則表達(dá)式與URL匹配
6、沒有修飾符的,如果指定字符串與URL開頭匹配

= 大于 ^~  大于 ~|~*|!~|!~* 大于 /

六、Nginx平滑升級

1、為什么要對Nginx進(jìn)行平滑升級

  1. 在不停掉老進(jìn)程的情況下,啟動新進(jìn)程
  2. 老進(jìn)程負(fù)責(zé)處理任然沒有處理完的請求,但不再接受處理請求
  3. 新進(jìn)程接受新請求
  4. 老進(jìn)程處理完所有請求,關(guān)閉所有連接,停止

用這種方式方便了所有的請求,一般有兩種情況下需要升級nginx。一種是確實要升級nginx的版本,另一種是要為nginx添加新的模板。

2、nginx平滑升級原理
多模式下的請求分配方式

nginx默認(rèn)工作是在多進(jìn)程模式下,即主進(jìn)程啟動后完成配置加載和端口綁定等動作。fock指定數(shù)量的工作進(jìn)程,這些進(jìn)程會持有監(jiān)聽端口的文件描述符(fd),并通過該描述符上添加監(jiān)聽事件來接受連接(accept)。

信號的接收和處理

Nginx主進(jìn)程在啟動完成后會進(jìn)入等待狀態(tài),負(fù)責(zé)響應(yīng)各類系統(tǒng)消耗,如sigchld、sighup、sigusr2等。

Nginx信號簡介

1、主進(jìn)程支持的信號
term,ini:立刻退出
quit:等待工作進(jìn)程結(jié)束后再退出
kill:強(qiáng)制終止進(jìn)程
hup:重新加載配置文件,使用新的配置啟動工作進(jìn)程并逐步關(guān)掉舊進(jìn)程。
usr1:重新打開日志文件
usr2:啟動新的主進(jìn)程,實現(xiàn)熱升級
winch:逐步關(guān)閉工作進(jìn)程

2、工作進(jìn)程支持的信號
term,ini:立刻退出
quit:等待工作進(jìn)程結(jié)束后再退出
usr1:重新打開日志文件

3、nginx平滑升級實戰(zhàn)

按照原來的編譯安裝nginx的方法進(jìn)行安裝,只需要到make,千萬不要make install,否則會覆蓋。

1、編譯安裝
[root@nginx-server ~]# yum install -y gcc gcc-c++ pcre-devel openssl-devel zlib-devel
[root@nginx-server ~]# tar xzf nginx-1.16.0.tar.gz -C /usr/local
[root@nginx-server ~]# cd /usr/local/nginx-1.16.0/
[root@nginx-server nginx-1.16.0]# ./configure --prefix=/usr/local/nginx --group=nginx --user=nginx --sbin-path=/usr/local/nginx/sbin/nginx --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --http-client-body-temp-path=/tmp/nginx/client_body --http-proxy-temp-path=/tmp/nginx/proxy --http-fastcgi-temp-path=/tmp/nginx/fastcgi --pid-path=/var/run/nginx.pid --lock-path=/var/lock/nginx --with-http_stub_status_module --with-http_ssl_module --with-http_gzip_static_module --with-pcre --with-http_realip_module --with-stream --with-http_image_filter_module
[root@nginx-server nginx-1.16.0]# make

2、備份原nginx二進(jìn)制文件和nginx配置文件
[root@nginx-server nginx-1.16.0]# mv /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx_$(date +%F)

3、復(fù)制新的nginx二進(jìn)制文件,進(jìn)入新的nginx源碼包
[root@nginx-server nginx-1.16.0]# cp /usr/local/nginx-1.16.0/objs/nginx /usr/local/nginx/sbin/

4、測試新版本的nginx是否正常
[root@nginx-server nginx-1.16.0]# /usr/local/nginx/sbin/nginx -t

5、給nginx發(fā)送平滑遷移信號
[root@nginx-server ~]# kill -USR2 `cat /var/run/nginx.pid`

6、查看nginx.pid,會出現(xiàn)一個nginx.pid.oldbin
[root@nginx-server ~]# ll /var/run/nginx.pid*
-rw-r--r-- 1 root root 5 Jul  1 11:29 /var/run/nginx.pid
-rw-r--r-- 1 root root 5 Jul  1 09:54 /var/run/nginx.pid.oldbin

7、從容關(guān)閉舊的Nginx進(jìn)程
[root@nginx-server ~]# kill -WINCH `cat /var/run/nginx.pid.oldbin`

8、此時不重載配置啟動舊的工作進(jìn)程
root@nginx-server ~]# kill -HUP `cat /var/run/nginx.pid.oldbin`

9、結(jié)束工作進(jìn)程,完成此次升級
[root@nginx-server ~]# kill -QUIT `cat /var/run/nginx.pid.oldbin`

10、驗證Nginx是否升級成功
[root@nginx-server ~]# /usr/local/nginx/sbin/nginx -V

七、Nginx流量控制

1、流量限制

可以用來限制用戶在給定時間內(nèi)HTTP請求的數(shù)量??梢杂米靼踩康模?/p>

  1. 減慢暴力破解的速率
  2. 將傳入請求的速率限制為真實用戶的典型值,并標(biāo)識目標(biāo)URL地址
  3. 抵御DDOS攻擊
  4. 保護(hù)上游應(yīng)用服務(wù)器不被同時太多用戶請求所擊垮

Nginx如何限流
使用漏桶算法,處理帶寬有限時的突發(fā)情況。

配置基本的限流
"流量限制"配置兩個主要的指令,limit_req_zone和limit_req.

limit_req_zone $binary_remote_addr zone=mylimit:10m rate=10r/s;  //每個IP地址被限制為每秒只能請求10次
        upstream myweb {
                server 10.0.124.196:80 weight=1 max_fails=1 fail_timeout=1;
                }
        server {
                listen 80;
                server_name localhost;

                location /login {
                        limit_req_zone=mylimit;
                        proxy_pass http://myweb;
                        proxy_set_header Host $host:$server_port;
                        proxy_set_header X-Real-IP $remote_addr;
                        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                        }
        }

10.0.124.196配置:

server {
        listen 80;
        server_name localhost;
        location /login {
                root    /usr/share/nginx/html;
                index   index.html index.html;
                }
}

limit_req_zone指令定義了流量限制相關(guān)的參數(shù),通常在HTTP塊中定義,使其可以在多個上下文使用。
limit_req指令將流量限制應(yīng)用在特定的location或者server塊。
2、處理突發(fā)
如果我們在100毫秒內(nèi)接收到2個請求,怎么辦?對于第二個請求,Nginx將給客戶端返回狀態(tài)碼503。我們希望緩沖任何超額的請求,然后及時地處理它們。我們更新下配置,在limit_req中使用burst參數(shù):

limit_req_zone $binary_remote_addr zone=mylimit:10m rate=10r/s;
        upstream myweb {
                server 10.0.105.196:80 weight=1 max_fails=1 fail_timeout=1;
                }
        server {
                listen 80;
                server_name localhost;

                location /login {
                        limit_req zone=mylimit burst=20;
                        proxy_pass http://myweb;
                        proxy_set_header Host $host:$server_port;
                        proxy_set_header X-Real-IP $remote_addr;
                        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                        }
        }

burst參數(shù)定義了超出了zone指定速率的情況下,客戶端還能發(fā)起多少請求。上一個請求100毫秒內(nèi)到達(dá)的請求將會被放入隊列,我們將隊列大小設(shè)置為20。

這意味著,如果從一個給定IP地址發(fā)送21個請求,Nginx會立即將第一個請求發(fā)送到上游服務(wù)器群,然后將余下20個請求放在隊列中。然后每100毫秒轉(zhuǎn)發(fā)一個排隊的請求,只有當(dāng)傳入請求使隊列中排隊的請求數(shù)超過20時,Nginx才會向客戶端返回503。

3、無延遲的排隊
配置burst參數(shù)將會使通訊更流暢,但是可能會不太實用,因為該配置會使站點看起來很慢。在上面的示例中,隊列中的第20個包需要等待2秒才能被轉(zhuǎn)發(fā),此時返回給客戶端的響應(yīng)可能不再有用。要解決這個情況,可以在burst參數(shù)后添加nodelay參數(shù):

limit_req_zone $binary_remote_addr zone=mylimit:10m rate=10r/s;
        upstream myweb {
                server 10.0.105.196:80 weight=1 max_fails=1 fail_timeout=1;
                }
        server {
                listen 80;
                server_name localhost;

                location /login {
                        limit_req zone=mylimit burst=20 nodelay;
                        proxy_pass http://myweb;
                        proxy_set_header Host $host:$server_port;
                        proxy_set_header X-Real-IP $remote_addr;
                        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                        }
        }

使用nodelay參數(shù),Nginx仍將根據(jù)burst參數(shù)分配隊列中的位置,并應(yīng)用已配置的速率限制,而不是清理隊列中等待轉(zhuǎn)發(fā)的請求。
例如:
隊列中有20個空位,從給定的IP地址發(fā)出的21個請求同時到達(dá)。Nginx會立即轉(zhuǎn)發(fā)這個21個請求,并且標(biāo)記隊列中占據(jù)的20個位置,然后每100毫秒釋放一個位置。如果是25個請求同時到達(dá),Nginx將會立即轉(zhuǎn)發(fā)其中的21個請求,標(biāo)記隊列中占據(jù)的20個位置,并且返回503狀態(tài)碼來拒絕剩下的4個請求。

注意:對于大部分部署,我們建議使用burst和nodelay參數(shù)來配置limit_req指令。

4、Nginx流量控制總結(jié)

以上已經(jīng)涵蓋了Nginx和Nginx Plus提供的“流量限制”的很多功能,包括為HTTP請求的不同loation設(shè)置請求速率,給“流量限制”配置burst和nodelay參數(shù)。還涵蓋了針對客戶端IP地址的白名單和黑名單應(yīng)用不同“流量限制”的高級配置,闡述了如何去日志記錄被拒絕和延時的請求。

八、Nginx訪問控制

1、nginx訪問控制模塊

  1. 基于IP的訪問控制:http_access_module
  2. 基于用戶的信任登錄:http_auth_basic_module

2、基于IP的訪問控制

# vim /etc/nginx/conf.d/access_mod.conf
server {
        listen 80;
        server_name localhost;
        location ~ ^/admin {
                root /home/www/html;
                index index.html index.hml;
                deny 192.168.1.8;
                allow all;
                #deny 192.168.1.8;
                }
}

需要注意: 如果先允許訪問,在定義拒絕訪問。那么拒絕訪問不生效。

指定location拒絕所有請求
如果你想拒絕某個指定URL地址的所有請求,而不是僅僅對其限速,只需要在location塊中配置deny all指令:

server {
        listen 80;
        server_name localhost;
        location /foo.html {
                root /home/www/html;
                deny all;
                }
}

3、基于用戶的信任登錄
將access_mod.conf為auth_mod.conf,內(nèi)容如下:

server {
    listen 80;
    server_name localhost;
    location ~ ^/admin {
        root /home/www/html;
        index index.html index.hml;
        auth_basic "Auth access test!";
        auth_basic_user_file /etc/nginx/auth.conf;
        }
}

auth_basic 不為off,開啟登錄驗證功能
auth_basic_user_file加載賬號密碼文件

建立口令文件

[root@192 ~]# yum install -y httpd-tools 

htpasswd 是開源 http 服務(wù)器 apache httpd 的一個命令工具,用于生成 http 基本認(rèn)證的密碼文件
[root@192 ~]# htpasswd -cm /etc/nginx/auth_conf user10
[root@192 ~]# htpasswd -m /etc/nginx/auth_conf user20
[root@192 ~]# cat /etc/nginx/auth_conf 
user10:$apr1$MOa9UVqF$RlYRMk7eprViEpNtDV0n40
user20:$apr1$biHJhW03$xboNUJgHME6yDd17gkQNb0

局限性

  1. 用戶信息依賴文件方式
  2. 操作系統(tǒng)管理機(jī)械,效率低下

解決辦法

  1. Nginx結(jié)合LUA實現(xiàn)高效驗證
  2. Nginx和LDAP打通,利用nginx-auth-ldap模塊
  3. Nginx只做中間代理,具體認(rèn)證交給應(yīng)用

九、Nginx變量

1、變量簡介

  • 所有的 Nginx變量在 Nginx 配置文件中引用時都須帶上 $ 前綴
  • 在 Nginx 配置中,變量只能存放一種類型的值,有且也只存在一種類型,那就是字符串類型
  • nginx可以使用變量簡化配置與提高配置的靈活性,所有的變量值都可以通過這種方式引用:$變量名

2、nginx變量的定義和使用
nginx變量分為兩種,自定義變量與內(nèi)置預(yù)定義變量。
2.1 自定義變量

可以在sever,http,location等標(biāo)簽中使用set命令(非唯一)聲明變量。
語法如下:set $變量名 變量值

注意:
1.nginx 中的變量必須都以$開頭
2.nginx 的配置文件中所有使用的變量都必須是聲明過的,否則 nginx 會無法啟動并打印相關(guān)異常日志

變量的可見性

  • nginx 變量的一個有趣的特性就是nginx中沒一個變量都是全局可見的,而他們又不是全局變量。
location a/ {
  return 200 $a
}

location b/ {
 set $a hello nginx
 return 200 $a
}


# 配置$foo=hello
server {
    listen 8080;
    server_name  localhost;
    
    location /test {
            set $foo hello;
            echo "foo: $foo";
    }
}

使用大括號插值

server {
    ...
    location /test-brace {
        set $first "hello ";
        echo "${first}world";
    }
}

輸出:
[root@localhost html]# nginx -s reload
[root@localhost html]# curl localhost/test-brace
hello world

3、變量作用域

set 指令(以及前面提到的 geo 指令)不僅有賦值的功能,它還有創(chuàng)建 Nginx 變量的副作用,即當(dāng)作為賦值對象的變量尚不存在時,它會自動創(chuàng)建該變量。

server {
    listen 8080;
    
    location /foo {
        echo "foo = [$foo]";
    }
    
    location /bar {
        set $foo 32;
        echo "foo = [$foo]";
    }
}

輸出:
[root@localhost html]# curl 'http://localhost/foo'
foo = []

[root@localhost html]# curl 'http://localhost/bar'
foo = [32]

內(nèi)部跳轉(zhuǎn)例子

server {
    listen 8080;

    location /foo {
        set $a hello;
        echo_exec /bar;    // echo_exec起到內(nèi)部跳轉(zhuǎn)的作用
    }

    location /bar {
        echo "a = [$a]";
    }
}

輸出:
[root@localhost html]# curl localhost/foo
a = [hello]

2.2 內(nèi)置預(yù)定義變量

內(nèi)置預(yù)定義變量即無需聲明就可以使用的變量,通常包括一個http請求或響應(yīng)中一部分內(nèi)容的值。
Nginx內(nèi)建變量最常見的用途是獲取關(guān)于請求或響應(yīng)的各種信息。

十、Nginx監(jiān)控

1、基礎(chǔ)監(jiān)控

  • 進(jìn)程監(jiān)控
  • 端口監(jiān)控

注意:這兩個必須加在Zabbix監(jiān)控,加觸發(fā)器有問題及時告警。

  • Nginx提供了ngx_http_stub_status_module、ngx_http_reqstat_module模塊,提供了基本的監(jiān)控功能

2、監(jiān)控的主要指標(biāo)
2.1 基本活躍指標(biāo)

Accepts(接受)、Handled(已處理)、Requests(請求數(shù))是一直在增加的計數(shù)器。Active(活躍)、Waiting(等待)、Reading(讀)、Writing(寫)隨著請求量而增減。

2.2 每秒請求數(shù) --QPS

1、按照固定時間間隔采樣請求數(shù)據(jù),計算出單位時間的請求量可以看到你的 web 服務(wù)器的請求情況。
2、通過持續(xù)的 QPS 監(jiān)控,可以立刻發(fā)現(xiàn)是否被惡意攻擊或?qū)Ψ?wù)的可用性進(jìn)行評估。
3、雖然當(dāng)問題發(fā)生時,通過 QPS 不能定位到確切問題的位置,但是他卻可以在第一時間提醒你環(huán)境可能出問題了。

2.3 服務(wù)器錯誤率

1、通過監(jiān)控固定時間間隔內(nèi)的錯誤代碼(4XX代碼表示客戶端錯誤,5XX代碼表示服務(wù)器端錯誤),可以了解到客戶端收到的結(jié)果是否是正確的錯誤率突然的飆升很可能是你的網(wǎng)站漏洞發(fā)出的信號.
2、如果你希望通過 access log 分析錯誤率,那么你需要配置 nginx 的日志模塊,讓 nginx 將響應(yīng)碼寫入訪問日志

2.4 請求處理時間

請求處理時間也可以被記錄在 access log 中,通過分析 access log,統(tǒng)計請求的平均響應(yīng)時間,通過持續(xù)觀察,可以發(fā)現(xiàn)上游服務(wù)器的問題。

3、指標(biāo)的收集

編譯時加入nginx的ngx_http_stub_status_module模塊可以實時監(jiān)控以下基本指標(biāo).

3.1 nginx stub status監(jiān)控模塊安裝

[root@localhost ~]# nginx -V   //查看是否安裝了這個模塊
如果沒有這個模塊,需要重新安裝
[root@localhost nginx-1.6.0]#  ./configure –with-http_stub_status_module

配置配置文件:

server {
        listen 80;
        server_name localhost;
        location /nginx-status {
                stub_status     on;
                access_log      on;
                allow   10.0.105.207;  #允許本地電腦訪問
                deny    all;
                }
}

3.2 nginx狀態(tài)查看

配置完成后在瀏覽器中輸入http://10.0.105.207/nginx-status 查看或者用 curl localhost/nginx_status
Active connections: 2 
server accepts handled requests
 26 26 48 
Reading: 0 Writing: 1 Waiting: 1 

3.3 Reqstat模塊監(jiān)控

  • 這個模塊計算定義的變量,根據(jù)變量值分別統(tǒng)計 nginx 的運行狀況。
  • 可以監(jiān)視的運行狀況有:連接數(shù)、請求數(shù)、各種響應(yīng)碼范圍的請求數(shù)、輸入輸出流量、rt、upstream訪問等。
  • 可以指定獲取所有監(jiān)控結(jié)果或者一部分監(jiān)控結(jié)果。
  • 利用變量添加自定義監(jiān)控狀態(tài)。總的監(jiān)控狀態(tài)最大個數(shù)為50個。
  • 回收過期的監(jiān)控數(shù)據(jù)。
  • 設(shè)置輸出格式
  • 跟蹤請求,不受內(nèi)部跳轉(zhuǎn)的影響
  • 不要使用與響應(yīng)相關(guān)的變量作為條件,比如"$status"
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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