nginx-知识点整理

一、Nginx Proxy代理

1、代理原理

(1)反向代理:需要有一个负载均衡设备(即反向代理服务器)来分发用户请求,将用户请求分发到后端正真提供服务的服务器上。服务器返回自己的服务到负载均衡设备,负载均衡设备将服务器的服务返回用户。
(2)正向代理:正向代理的过程隐藏了真实的请求客户端,服务器不知道真实的客户端是谁,客户端请求的服务都被代理服务器代替请求。我们常说的代理也就是正向代理,正向代理代理的是请求方,也就是客户端。

2、正向和反代的区别?

正向代理中代理的对象是客户端。
反向代理中代理的对象是服务端。

3、nginx Proxy 配置

代理模块:ngx_http_proxy_module
模拟:两台Nginx真实服务器

a、Nginx-1 启动网站(内容)
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服务器地址或域名,也就是http://192.168.124.20,成功访问Nginx-1服务器页面
d、观察Nginx-1服务器的日志
访问成功,记录了客户端的IP和代理服务器的IP。

二、Nginx负载均衡

1、upstream配置

这个配置是写一组被代理的服务器地址,然后配置负载均衡的算法。

upstream testapp { 
      server 10.0.105.199:8081;
      server 10.0.105.202:8081;
    }
 server {
        ....
        location / {         
           proxy_pass  http://testapp;  #请求转向 testapp 定义的服务器列表         
        } 
2、负载均衡算法

1、轮询(默认):每个请求按时间顺序逐一分配到不同的后端服务器;
2、ip_hash:每个请求按访问IP的hash结果分配,同一个IP客户端固定访问一个后端服务器。可以保证来自同一ip的请求被打到固定的机器上,可以解决session问题。
3、url_hash:按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器。
4、fair:此种算法可以依据页面大小和加载时间长短智能地进行负载均衡,也就是根据后端服务器的响应时间来分配请求,响应时间短的优先分配。Nginx本身是不支持 fair的,如果需要使用这种调度算法,必须下载Nginx的 upstream_fair模块。

配置实例
1、热备:如果有两台服务器,当一个服务器发生事故的时候,才启动第二台服务器给提供服务。

upstream myweb { 
      server 172.17.14.2:8080; 
      server 172.17.14.3:8080 backup;  #热备     
    }

2、轮询:nginx默认就是轮询其权重都默认1

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

3、加权轮询:根据配置的权重大小二分发给不用服务器数量的请求。

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

4、ip_hash:nginx会让相同的客户端IP请求相同的服务器。

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

5、Nginx负载均衡配置状参数

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:表示当前的server暂时不参与负载均衡
backup:预留的备份机器
max_fails:允许请求失败的次数,默认为1。当超过最大次数时,返回proxy_next_upstream 模块定义的错误。
fail_timeout:经历了max_fails失败后。暂停服务的时间单位秒。max_fails可以和fail_timeout一起使用。
3、Nginx会话保持

有以下几种实现方式:
1、ip_hash
使用源地址哈希算法,将同一客户端的请求总是发送同一个后端服务器。

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

ip_hash简单易用,但有如下的问题:
当后端服务器宕机后,session会丢失;
来自同一个局域网的客户端会被转发到同一个后端服务器,可能会导致负载失衡;

2、sticky_cookie_insert
使用这个模块会让来自同一个客户端的请求被传递到一组服务器的同一台服务器,与ip_hash不同之处是,它不是基于IP来判断客户端的,而是基于cookie来判断(需要引用第三方模块才能实现)
sticky模块语法:

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

expires:设置浏览器中保持cookie的时间
domain:定义cookie的域
path:为cookie定义路径

3、jvm_route方式

通过session_cookie这种方式实现session粘性,将特定会话附属到特定的tomcat上,从而解决session不同步问题,但是无法解决宕机后会话转移问题。如果cookie和url中并没有session,则这只是个简单的round-robin负载均衡。

jvm_route原理:
1.一开始请求过来,没有带session信息,jvm_round就会根据round robin的方法,发到一台Tomcat上面。
2.Tomcat添加上session信息,并返回给客户。
3.用户再次请求,jvm_route看到session中有后端服务器的名称,它就会把请求转发到对应的服务器上。

三、Nginx实现动静分离

为了加快网站的解析速度,可以把动态页面和静态页面由不同的服务器来解析,加快解析速度。降低原来单个服务器的压力。

准备环境

3台机器,一个做Nginx代理,一个http处理动态,一个http处理静态,三台机器都装Nginx。
代理:192.168.124.10
http:192.168.124.11(动态)192.168.124.12(静态)

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
        #动态资源加载
        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;
                }
        #静态资源加载
        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、配置静态资源(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   添加内容

3、动态资源配置(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;  #指定网站目录
            fastcgi_pass   127.0.0.1:9000;    #指定访问地址
            fastcgi_index  index.php;       #指定默认文件
            fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name; #站点根目录,取决于root配置项
            include        fastcgi_params;  #包含nginx常量定义
                }
        }
3、创建目录
# 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会转发到静态服务器,通过location正则匹配来处理请求。
2、访问http://192.168.124.10/index.php动态页面时location匹配到./php结尾的文件会转发到php服务器处理请求。

四、Nginx防盗链

两个网站 A 和 B, A网站引用了B网站上的图片,这种行为就叫做盗链。 防盗链,就是要防止A引用B的图片。

1、Nginx防止网站资源被盗用模板

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://开头的,不带协议的请求访问资源
server_names : 只允许指定ip/域名来的请求访问资源(白名单

2、配置实例

准备两台机器,两张图片

第一台,配置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服务
[root@nginx-server ~]# nginx -s reload -c /etc/nginx/nginx.conf

第二台机器客户端

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相关指令

Nginx Rewrite相关指令有if、rewrite、set、return
应用环境:server、location

2.1 If 指令

支持如下条件判断匹配符号:
~                        正则匹配(区分大小写)
~*                       正则匹配(不区分大小写)
!~                       正则不匹配(区分大小写)
!~*                      正则不匹配(不区分大小写)
-f 和 !-f                用来判断是否存在文件
-d 和 !-d                用来判断是否存在目录
-e 和 !-e                用来判断是否存在文件或目录
-x 和 !-x                用来判断文件是否可执行

2.2 Rewrite flag
rewrite指令根据表达式来重定向URL,或者修改字符串。可以应用于server,location,if环境下每行rewrite指令最后跟一个flag标记,支持的flag标记有:

last 表示本条规则匹配后会重新发送请求
break 本条规则匹配完成后,终止匹配,不再匹配 后面的规则
redirect 返回302临时重定向,浏览器地址会显示跳转后的URL地址
permanent 返回301永久重定向,浏览器地址会显示跳转后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指令用于定义一个变量,并且赋值
应用环境:server、location、if

应用实例:
# 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指令用于返回状态码给客户端。可以应用于server、location、If环境下。

应用实例:
1、如果要访问.sh结尾的文件则返回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端口转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、查找顺序和优先级

1、带有"="的精确匹配优先 (完全匹配)
2、没有修饰符的精确匹配
3、正则表达式按照他们在配置文件中定义的顺序
4、带有"^~"修饰符的,开头匹配
5、带有"~"或"~*"修饰符的,如果正则表达式与URL匹配
6、没有修饰符的,如果指定字符串与URL开头匹配

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

六、Nginx平滑升级

1、为什么要对Nginx进行平滑升级

  1. 在不停掉老进程的情况下,启动新进程
  2. 老进程负责处理任然没有处理完的请求,但不再接受处理请求
  3. 新进程接受新请求
  4. 老进程处理完所有请求,关闭所有连接,停止

用这种方式方便了所有的请求,一般有两种情况下需要升级nginx。一种是确实要升级nginx的版本,另一种是要为nginx添加新的模板。

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

nginx默认工作是在多进程模式下,即主进程启动后完成配置加载和端口绑定等动作。fock指定数量的工作进程,这些进程会持有监听端口的文件描述符(fd),并通过该描述符上添加监听事件来接受连接(accept)。

信号的接收和处理

Nginx主进程在启动完成后会进入等待状态,负责响应各类系统消耗,如sigchld、sighup、sigusr2等。

Nginx信号简介

1、主进程支持的信号
term,ini:立刻退出
quit:等待工作进程结束后再退出
kill:强制终止进程
hup:重新加载配置文件,使用新的配置启动工作进程并逐步关掉旧进程。
usr1:重新打开日志文件
usr2:启动新的主进程,实现热升级
winch:逐步关闭工作进程

2、工作进程支持的信号
term,ini:立刻退出
quit:等待工作进程结束后再退出
usr1:重新打开日志文件

3、nginx平滑升级实战

按照原来的编译安装nginx的方法进行安装,只需要到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二进制文件和nginx配置文件
[root@nginx-server nginx-1.16.0]# mv /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx_$(date +%F)

3、复制新的nginx二进制文件,进入新的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发送平滑迁移信号
[root@nginx-server ~]# kill -USR2 `cat /var/run/nginx.pid`

6、查看nginx.pid,会出现一个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、从容关闭旧的Nginx进程
[root@nginx-server ~]# kill -WINCH `cat /var/run/nginx.pid.oldbin`

8、此时不重载配置启动旧的工作进程
root@nginx-server ~]# kill -HUP `cat /var/run/nginx.pid.oldbin`

9、结束工作进程,完成此次升级
[root@nginx-server ~]# kill -QUIT `cat /var/run/nginx.pid.oldbin`

10、验证Nginx是否升级成功
[root@nginx-server ~]# /usr/local/nginx/sbin/nginx -V

七、Nginx流量控制

1、流量限制

可以用来限制用户在给定时间内HTTP请求的数量。可以用作安全目的:

  1. 减慢暴力破解的速率
  2. 将传入请求的速率限制为真实用户的典型值,并标识目标URL地址
  3. 抵御DDOS攻击
  4. 保护上游应用服务器不被同时太多用户请求所击垮

Nginx如何限流
使用漏桶算法,处理带宽有限时的突发情况。

配置基本的限流
"流量限制"配置两个主要的指令,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指令定义了流量限制相关的参数,通常在HTTP块中定义,使其可以在多个上下文使用。
limit_req指令将流量限制应用在特定的location或者server块。
2、处理突发
如果我们在100毫秒内接收到2个请求,怎么办?对于第二个请求,Nginx将给客户端返回状态码503。我们希望缓冲任何超额的请求,然后及时地处理它们。我们更新下配置,在limit_req中使用burst参数:

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参数定义了超出了zone指定速率的情况下,客户端还能发起多少请求。上一个请求100毫秒内到达的请求将会被放入队列,我们将队列大小设置为20。

这意味着,如果从一个给定IP地址发送21个请求,Nginx会立即将第一个请求发送到上游服务器群,然后将余下20个请求放在队列中。然后每100毫秒转发一个排队的请求,只有当传入请求使队列中排队的请求数超过20时,Nginx才会向客户端返回503。

3、无延迟的排队
配置burst参数将会使通讯更流畅,但是可能会不太实用,因为该配置会使站点看起来很慢。在上面的示例中,队列中的第20个包需要等待2秒才能被转发,此时返回给客户端的响应可能不再有用。要解决这个情况,可以在burst参数后添加nodelay参数:

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参数,Nginx仍将根据burst参数分配队列中的位置,并应用已配置的速率限制,而不是清理队列中等待转发的请求。
例如:
队列中有20个空位,从给定的IP地址发出的21个请求同时到达。Nginx会立即转发这个21个请求,并且标记队列中占据的20个位置,然后每100毫秒释放一个位置。如果是25个请求同时到达,Nginx将会立即转发其中的21个请求,标记队列中占据的20个位置,并且返回503状态码来拒绝剩下的4个请求。

注意:对于大部分部署,我们建议使用burst和nodelay参数来配置limit_req指令。

4、Nginx流量控制总结

以上已经涵盖了Nginx和Nginx Plus提供的“流量限制”的很多功能,包括为HTTP请求的不同loation设置请求速率,给“流量限制”配置burst和nodelay参数。还涵盖了针对客户端IP地址的白名单和黑名单应用不同“流量限制”的高级配置,阐述了如何去日志记录被拒绝和延时的请求。

八、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,内容如下:

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 服务器 apache httpd 的一个命令工具,用于生成 http 基本认证的密码文件
[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. 操作系统管理机械,效率低下

解决办法

  1. Nginx结合LUA实现高效验证
  2. Nginx和LDAP打通,利用nginx-auth-ldap模块
  3. Nginx只做中间代理,具体认证交给应用

九、Nginx变量

1、变量简介

  • 所有的 Nginx变量在 Nginx 配置文件中引用时都须带上 $ 前缀
  • 在 Nginx 配置中,变量只能存放一种类型的值,有且也只存在一种类型,那就是字符串类型
  • nginx可以使用变量简化配置与提高配置的灵活性,所有的变量值都可以通过这种方式引用:$变量名

2、nginx变量的定义和使用
nginx变量分为两种,自定义变量与内置预定义变量。
2.1 自定义变量

可以在sever,http,location等标签中使用set命令(非唯一)声明变量。
语法如下:set $变量名 变量值

注意:
1.nginx 中的变量必须都以$开头
2.nginx 的配置文件中所有使用的变量都必须是声明过的,否则 nginx 会无法启动并打印相关异常日志

变量的可见性

  • 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 指令)不仅有赋值的功能,它还有创建 Nginx 变量的副作用,即当作为赋值对象的变量尚不存在时,它会自动创建该变量。

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]

内部跳转例子

server {
    listen 8080;

    location /foo {
        set $a hello;
        echo_exec /bar;    // echo_exec起到内部跳转的作用
    }

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

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

2.2 内置预定义变量

内置预定义变量即无需声明就可以使用的变量,通常包括一个http请求或响应中一部分内容的值。
Nginx内建变量最常见的用途是获取关于请求或响应的各种信息。

十、Nginx监控

1、基础监控

  • 进程监控
  • 端口监控

注意:这两个必须加在Zabbix监控,加触发器有问题及时告警。

  • Nginx提供了ngx_http_stub_status_module、ngx_http_reqstat_module模块,提供了基本的监控功能

2、监控的主要指标
2.1 基本活跃指标

Accepts(接受)、Handled(已处理)、Requests(请求数)是一直在增加的计数器。Active(活跃)、Waiting(等待)、Reading(读)、Writing(写)随着请求量而增减。

2.2 每秒请求数 --QPS

1、按照固定时间间隔采样请求数据,计算出单位时间的请求量可以看到你的 web 服务器的请求情况。
2、通过持续的 QPS 监控,可以立刻发现是否被恶意攻击或对服务的可用性进行评估。
3、虽然当问题发生时,通过 QPS 不能定位到确切问题的位置,但是他却可以在第一时间提醒你环境可能出问题了。

2.3 服务器错误率

1、通过监控固定时间间隔内的错误代码(4XX代码表示客户端错误,5XX代码表示服务器端错误),可以了解到客户端收到的结果是否是正确的错误率突然的飙升很可能是你的网站漏洞发出的信号.
2、如果你希望通过 access log 分析错误率,那么你需要配置 nginx 的日志模块,让 nginx 将响应码写入访问日志

2.4 请求处理时间

请求处理时间也可以被记录在 access log 中,通过分析 access log,统计请求的平均响应时间,通过持续观察,可以发现上游服务器的问题。

3、指标的收集

编译时加入nginx的ngx_http_stub_status_module模块可以实时监控以下基本指标.

3.1 nginx stub status监控模块安装

[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状态查看

配置完成后在浏览器中输入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模块监控

  • 这个模块计算定义的变量,根据变量值分别统计 nginx 的运行状况。
  • 可以监视的运行状况有:连接数、请求数、各种响应码范围的请求数、输入输出流量、rt、upstream访问等。
  • 可以指定获取所有监控结果或者一部分监控结果。
  • 利用变量添加自定义监控状态。总的监控状态最大个数为50个。
  • 回收过期的监控数据。
  • 设置输出格式
  • 跟踪请求,不受内部跳转的影响
  • 不要使用与响应相关的变量作为条件,比如"$status"
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342