Nginx知识点整理

在此之前整理过Nginx的相关使用方法, 但是感觉不是很完整, 有兴趣可以去看看之前的整理: https://blog.csdn.net/ip_jl/article/category/8312911

现在抽时间重新整理一下Nginx从基础安装到日常开发的使用的全过程, 此次整理是较为完整的一次, 所以篇幅会较长, 无法一次性写完整, 只能持续更新...

//2019/01/12更新=========================>>>>

好了, 进入正题(从头至尾整理的都是Linux环境, 而非Windows环境), 说明一下, 此次整理可能不会有很多图文进行说明.

○ Nginx的安装和启动:

● 进入官网下载Nginx的稳定版本, http://nginx.org/en/download.html, 我这里选择1.14.2版本, 复制其下载链接: http://nginx.org/download/nginx-1.14.2.tar.gz

● 进入Linux环境, 使用wget命令下载Nginx对应版本: wget http://nginx.org/download/nginx-1.14.2.tar.gz

● 下载完成后, 使用命令解压tar包: tar -zxvf <tar包包名>

● 使用命令进行编译和安装, ./configure --prefix=<自定义安装的路径>; (ps: 期间可能会出现缺少某些依赖或者某些包, 则需要手动yum进行安装对应的依赖之后才能继续安装Nginx.) make && make install

● 安装完成后, 配置环境变量, 编辑/etc/profile文件, 在最下边加上以下两行配置

    ○ export NGINX_HOME=/opt/Milky-way/nginx/nginx_v1.14.2_install    //自定义变量名NGINX_HOME指定nginx的安装目录

    ○ export PATH=$PATH:$NGINX_HOME/sbin    //将变量追加进path路径中, 以后还可追加其他变量

● 刷新配置文件立即生效: source /etc/profile

● 命令启动Nginx, nginx

● 查看Nginx的启动状态, ps aux|grep nginx, 此时Nginx如果正常启动了的话, 应该可以看到如下信息:

至此, Nginx的安装顺利结束了.

○ Nginx的信号量和虚拟主机配置

这里介绍几个Nginx官网介绍的信号量, 有兴趣可以自行查看: https://www.nginx.com/resources/wiki/start/topics/tutorials/commandline/?highlight=commandline

TERM, INT Quick shutdown  //快速杀死进程(如: kill -int <进程号>)
QUIT Graceful shutdown  //平滑杀死进程(如: kill -quit <进程号>)
KILL Halts a stubborn process  //这个信号量我发现应该是新的(如: kill -kill <线程号>), 表面意思是'杀死顽固的进程', 自己试验了一下, 感觉还不如TERM / INT, 它并没有能杀死子线程, 只杀死了主线程
HUP

Configuration reload  //平滑重新加载配置文件(如: kill -hup <进程号>)

Start the new worker processes with a new configuration

Gracefully shutdown the old worker processes

USR1 Reopen the log files  //重新加载日志(如: kill -usr1 <进程号>)
USR2 Upgrade Executable on the fly  //平滑升级(如:  kill -usr2 <进程号>)
WINCH Gracefully shutdown the worker processes  //配置USER2来平滑关闭旧的进程(如: kill -winch <进程号>)

Nginx的配置文件是nginx.conf, 进入Nginx的安装目录的conf目录下, 打开nginx.conf文件, 里面大致有三个段, 分为是

worker_processes  1;  //全局区, 指定一个工作的子进程, 一般设置为cpu数*核数

events //配置Nginx的连接特性, 指定一个子进程能允许多少个连接
    worker_connections  1024;

http//配置http服务器

    server {  //配置虚拟主机
        listen       80;
        server_name  localhost;

        location / {  //定位特殊的路径并做处理
            root   html;
            index  index.html index.htm;
        }

        location / {
        }

    }

    server {  //配置虚拟主机
    }

}

 以上第二部分是信号量和虚拟主机的整理

○ 日志管理

在server段下有以下信息:

#access_log  logs/host.access.log  main;  //配置日志的存放路径跟名称, 并且以main的格式来展示

main格式:

#log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    #                  '$status $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';
main的格式可以自定义, 并且将日志设置在http段下或者server段下是自主可控的, 如果设置在server段下则代表该日志文件仅在该server端被访问时写日志.

● 利用定时任务完成日志定时切割

在实际工作中, 会有需要将每天的日志切割出来, 并存放在另外的地方, 这样做能便于管理这些日志和查看日志信息; 通常都会根据日期来切分不同的时间日志并存放于不同日期标识的文件夹中.

步骤:

① 新建一个shell文件runlog.sh, 内容为

#配置当前的日志存放路径
LOGPATH=/opt/Milky-Way/bin/nginx/logs/test.access.log

#配置备份日志的存放路径
BASEPATH=/opt/Milky-Way/data/$(date -d yesterday +%Y%m)

#创建存放日志的上层目录(如月份/日期)
mkdir -p $BASEPATH

#重命名备份日志的名称
BACKPATH=$BASEPATH/$(date -d yesterday +%d%H%M).access.log

#将当天的日志移至备份目录
mv $LOGPATH $BACKPATH

#新建一份空的日志
touch $LOGPATH

#重新加载日志
kill -usr1 `cat /opt/Milky-Way/bin/nginx/logs/nginx.pid`

② 命令设置定时任务 crontab -e, 内容为

*/1 * * * * sh /opt/Milky-Way/data/runlog.sh  //表示1分钟执行一次runlog.sh文件

③ 在Nginx的配置文件nginx.conf中指定日志生成的文件位置与上方的shell中的test.access.log日志文件对应

④ 启动Nginx, 访问Nginx之后, 每过一分钟查看备份路径下是否1分钟生成一个日志文件

我本地的结果如下:

//2019/01/13更新=========================>>>>

Location的定位

rule①  精准匹配优先于普通匹配

1) 第一种情况

        location = /index.htm {
            root   /opt/Milky-Way/data/html/;
            index  index.htm index.html;
        }   

        location /index.htm {
            root  /opt/Milky-Way/bin/nginx/html;
            index  index.html index.htm;
        }  

结论: 访问http://<ip>/index.htm的结果是精准匹配(=)优先, ps: 精准匹配无顺序的限制, 此时如果直接输入http://<ip>/, 由于配置文件中的精准匹配和普通匹配都无法匹配上, 只能由Nginx的最上层默认指定的安装路径下的html文件夹中的index.html来匹配.

2) 第二种情况

        location = /index.htm {
            root   /opt/Milky-Way/data/html/;
            index  index.htm index.html;
        }

        location = / {
            root   /opt/Milky-Way/data/html;
            index  index.htm index.html;
        }

        location /index.htm {
            root  /opt/Milky-Way/bin/nginx/html;
            index  index.html index.htm;
        }

结论: 访问http://<ip> /根目录时, 先精准匹配到location = / {...}, 返回的路径是http://<ip>/index.htm, 再次精准匹配到location = /index.htm {...}, 最后返回/opt/Milky-Way/data/html/路径下的index.htm页面

rule② 正则匹配优先于普通匹配

        location ~ images {  //正则表达式匹配(只要路径中含有images字样即被匹配)
            root   /opt/Milky-Way/;
            index  index.html;
        }

默认的index.html文件

<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<img src='images/nginxlogo.png' />  //手动加上去的
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

我在/opt/Milky-Way/images目录下有一张名为nginxlogo.png的图片, 结果说话:http://<ip>

再来, 将图片路径改为<img src='images/baidulogo.png' />

我在/opt/Milky-Way/newimages/images目录下放置一张名为baidulogo.png的图片, 验证多个正则都可以被匹配的情况

配置文件改为

        location ~ images {
            root   /opt/Milky-Way/;
            index  index.html;
        }

        location ~ images {
            root   /opt/Milky-Way/newimages/;
            index  index.html;
        }
结果是无法被访问到, 原因在于正则表达式是有顺序限制的, 一旦第一个正则表达式匹配上, 则不会再继续匹配下去, 而此时第一个正则匹配到的路径中我并没有放置baidulogo.png这张图片.

将配置改为


        location ~ images {
            root   /opt/Milky-Way/newimages;
            index  index.html;
        }

        location ~ images {
            root   /opt/Milky-Way/;
            index  index.html;
        }
结果说话:

最后, 再来测试一下该正则是否是检测路径中含有images字样即匹配

将配置文件改为

        location ~ images {
            root   /opt/Milky-Way/;
            index  index.html;
        }

图片路径改为<img src='newimages/baidulogo.png' />, 意味着如果匹配上, 我在/opt/Milky-Way/newimages目录下必须有一张名为baidulogo.png的图片才能被访问到.

结果说话:

小结: 

location的路径定位顺序是, 第一步匹配精准路径, 如果一旦匹配上, 立刻返回, 此时也是有顺序限制的; 第二步, 当没有匹配上精准路径时, 则匹配正则, 一旦匹配上, 则立刻返回; 第三步, 当都没有匹配上, 则匹配普通路径, 匹配普通路径时, 如果有多个符合, 则按照最长路径符合进行匹配; 最后, 当普通路径都没有匹配上, 则匹配Nginx的上层默认路径, 也就是安装路径下的html文件夹.

//2019/01/13 18点更新=========================>>>>

 rewrite重写

 需要用到的命令:

● if (条件) {...}

● set $<变量名称> <变量值>

● return <返回的状态码>

● break;  //跳出当前的rewrite

if条件的格式有:

○ '='  //判断是否相等

○ '~'  或者 '~*'  //正则匹配, 前者区分大小写, 后者不区分大小写

○ -f -d -e  //判断是否为文件, 是否为目录, 是否存在

配置文件:

1) 判断请求ip是否等于192.168.5.1

if ($remote_addr = 192.168.5.1) {
                return 403;

2) 判断浏览器的头信息是否包含AppleWebKit(ps: 需要使用break, 否则进入死循环. )

if ($http_user_agent ~ AppleWebKit) {
                rewrite ^.*$ /denyIEbrowser.html;
                break;
}

3) 判断该文件名是否存在

 if (!-e $document_root$fastcgi_script_name) {
                rewrite ^.*$ /404.html break;  //造成死循环的原因是rewrite并不能改变路径的文件指向, 相当于还是指向请求时的文件, 那么Nginx再次解析时还会进入该循环, 造成死循环
}

4) 设置变量isie

            if ($http_user_agent ~* trident) {
                set $isie 1;
            }   

            if ($fastcgi_script_name = denyIEbrowser.html) {
                set $isie 0;
            }   

            if ($isie = 1) {
                rewrite ^.*$ /denyIEbrowser.html break;
            }

至于 $document_root$fastcgi_script_name的由来, 可以进入Nginx的安装目录下的conf目录中的fastcgi.conf文件中查找, 具体如下可供使用:

fastcgi_param  SCRIPT_FILENAME    $document_root$fastcgi_script_name;  //代表当前文件的路径(包含文件名称)
fastcgi_param  QUERY_STRING       $query_string;
fastcgi_param  REQUEST_METHOD     $request_method;
fastcgi_param  CONTENT_TYPE       $content_type;
fastcgi_param  CONTENT_LENGTH     $content_length;

fastcgi_param  SCRIPT_NAME        $fastcgi_script_name;
fastcgi_param  REQUEST_URI        $request_uri;
fastcgi_param  DOCUMENT_URI       $document_uri;
fastcgi_param  DOCUMENT_ROOT      $document_root;
fastcgi_param  SERVER_PROTOCOL    $server_protocol;
fastcgi_param  REQUEST_SCHEME     $scheme;
fastcgi_param  HTTPS              $https if_not_empty;

fastcgi_param  GATEWAY_INTERFACE  CGI/1.1;
fastcgi_param  SERVER_SOFTWARE    nginx/$nginx_version;

fastcgi_param  REMOTE_ADDR        $remote_addr;
fastcgi_param  REMOTE_PORT        $remote_port;
fastcgi_param  SERVER_ADDR        $server_addr;
fastcgi_param  SERVER_PORT        $server_port;
fastcgi_param  SERVER_NAME        $server_name;

rewrite部分小结完成===>

//2019/01/13  23点更新=========================>>>>

反向代理 / 负载均衡

使用Nginx就不能不提到反向代理(proxy) 和负载均衡(upstream)

反向代理(proxy)

需要两台服务器, 一台运行Nginx, 另一台运行Tomcat(此时我使用docker启动Tomcat容器)

在Tomcat容器中的webapps目录下放置一个testProxy目录, 该目录下有个testProxy.html文件

在Nginx的配置文件中进行如下配置:

        location ~* /testProxy.html {
            proxy_pass http://192.168.5.134:8899;  //此处的ip:port是Tomcat所在的服务器及端口
        }

页面请求: http://192.168.5.130/testProxy/testProxy.html, 响应回来的正是部署在Tomcat的webapps/testProxy目录下的页面内容, 查看Tomcat的日志情况如下(为了更显而易见我狂刷了n次哈): ps: 我也不清楚为什么时间对不上系统的时间, Nginx服务器的时间是正常的, Tomcat的时间不正常.

好了, 反向代理(所谓的动静分离)就是这么实现的.

负载均衡(upstream)

当后端有多台服务器时, 则能够形成负载均衡, 但是proxy_pass在一个location中不允许写多个, 所以必须引入upstream, 将多台服务器绑定在一起, 并起个组名, 将proxy_pass指向该组名.

官方文档upstream模块: http://nginx.org/en/docs/http/ngx_http_upstream_module.html

Nginx的配置文件:

upstream servers {  //将两个端口的服务器绑定在一起, 也可以设置两台不同的服务器
        server 192.168.5.130:8081 weight=7 max_fails=3 fail_timeout=10s;
        server 192.168.5.130:8082 weight=3 max_fails=3 fail_timeout=10s;
    }

○ weight: 权重, 权重值越大则分配的请求越多

○ max_fails: 最大请求失败数, 一旦请求超过3次则不再请求该服务器

○ fail_timeout: 超时时间, 一旦超过超时时间则不再请求该服务器

    server {  //虚拟服务器端口8081
        listen 8081;
        server_name localhost;
        access_log logs/8081-access.log  main;  //日志8082

        location ~* /image {
                root /opt/Milky-Way/images;
                index index.html;
        }
    }

    server {  //虚拟服务器端口8082
        listen 8082;
        server_name localhost;

        access_log logs/8082-access.log  main;  //日志8082

        location ~*  /image {
                root /opt/Milky-Way/newimages;
                index index.html;
        }
    }

 server {  //默认的80请求端口
        listen       80;
        server_name  localhost;

        location ~* /image {

                proxy_set_header X-Forwarded-For $remote_addr;  //设置携带客户端的头信息
                proxy_pass http://servers;
                root /opt/Milky-Way;
                index index.html;
        }

我在/opt/Milky-Way/images/image目录和/opt/Milky-Way/newimages/image目录下分别放置名为nginxlogo.png的图片

测试: 访问http://192.168.5.130/image/nginxlogo.png, 查看日志打印信息, 请求10次, 8081和8082分别响应7次(权重为7)和3次(权重为3)

8081log:

8082log:

//2019/01/15 更新=========================>>>>

压缩(gzip)和缓存(expires)

gzip压缩 

gzip的Nginx官方文档: http://nginx.org/en/docs/http/ngx_http_gzip_module.html

上下文位置是http, server, location, if in location

配置的常用参数:

○ gzip on|off  //是否开启gzip

○ gzip_buffers 32 4K | 16 8K  //缓冲(压缩在内存中有几块, 每块多大)

○ gizp_comp_level <1-9>  //推荐6(级别越高, 压缩力度越大, 文件越小, 耗费cpu资源越多)

○ gzip_disable <正则表达式>  //正则匹配uri, 匹配上的uri不进行压缩

○ gzip_min_length <文件大小(字节单位)>  //开始压缩的最小长度

○ gzip_http_version  //开始压缩的http协议版本(目前基本上都是http1.1协议了)

○ gzip_proxied  //设置请求者的代理服务器该如何缓存内容

○ gzip_types text/plain application/xml  //默认是text/html, 对指定文件使用压缩

设置指定文件类型, 可以进入安装目录的conf目录下的mime.types文件:

○ gzip_vary on|off   //是否开启gzip的传输标志 

ps: 太小的文件或者二进制文件不需要使用压缩, 文件太小或者由于二进制的压缩比太小而导致不划算(压缩时会耗费cpu) 

配置文件: 根据个人需求编写压缩条件即可

        gzip on; 
        gzip_buffers 32 4K; 
        gzip_comp_level 6;
        gzip_min_length 4000;

expires缓存 

为了提高网站的性能, 一般希望将一些图片等静态资源缓存在用户的浏览器上(可能几天之类的...), 这样的话就可以避免用户每次都访问都来回请求服务器造成服务器端的压力增大, 资源浪费.

expires的用法, 配置在location域 / if域内

expires  30s;  //30秒过期

expires  30m;  //30分钟过期

expires  30h;  //30小时过期

expires  30d;  //30天过期

配置文件中加入

location ~* image {
                root /opt/Milky-Way;
        }

正常情况下服务器的响应头应该如下:

 

在Nginx的配置文件中加上:
        location ~* image {
                expires 1d;  //过期时间设置为1天
                root /opt/Milky-Way;
        } 

此时的响应头变成如下:

 

//此时服务器的时间跟本地系统时间存在时区间隔 

ps: 服务器的日期要与当前时间一致, 否则缓存可能无效; 304状态码的请求也是一种缓存手段, 在于服务器响应的内容etag标签和last_modified_since是否发生改变, 不变的情况下, 浏览器只会返回304状态码, 浏览器就会直接调用本地缓存, 这个过程与expires的区别在于304状态码也是一种请求服务器的过程, 只不过传输的信息量较少, 而expires在过期时间内是不会请求服务器的.

//2019/01/19 更新=========================>>>>

Nginx的模块

● Nginx的核心功能模块

官网地址: http://nginx.org/en/docs/ngx_core_module.html

在nginx.conf的原始配置中, 就是这个区域

● 标准的Http功能模块的集合

官网: ngx_http_*  //官网中所有ngx_http_开头的都属于http模块, 对应nginx.conf的原始配置位置:

● Nginx的安装目录结构

○ conf目录  //nginx所有的配置的目录, 最为重要的目录

    1) nginx.conf  //主配置文件

    2) fastcgi.conf  //参数配置文件, 用于和动态程序配合

    3) mime.types  //枚举类型文件

○ html目录  //nginx的默认站点目录

○ logs目录  //nginx的默认日志目录

○ sbin目录  //nginx的命令目录

○ *_temp目录  //临时文件

● nginx.conf配置文件

 

虚拟主机

● 概念: 在Nginx中就是一个server{...}, 里面需要配置监听的端口 / 域名 / location{...}等

● 类型: 

    ○ 基于域名的虚拟主机

配置

server {
        listen       80;
        server_name  www.test1.com;
        location / {
            root   html/test1;
            index  index.html index.htm;
        }
    }
    server {
        listen       80;
        server_name  www.test2.com;
        location / {
            root   html/test2;
            index  index.html index.htm;
        }
    }
小结:

● 此时客户端通过tcp发出请求转成http被nginx识别, 先识别端口, 再识别域名; 当使用ip进行访问时, 默认使用第一个虚拟主机, 因为此时无法通过域名来识别了

● 在定义index中无法找到文件时时, 默认返回403; 可以通过autoindex来控制是否开启列表显示, 如下配置:

server {
        listen       80;
        server_name  www.test1.com;
        autoindex on;
        location / {
            root   html/test1;
            index  index.html1 index.htm1;
        }
    }
    server {
        listen       80;
        server_name  www.test2.com;
        autoindex on;  //on表示打开
        location / {
            root   html/test2;
            index  index.html1 index.htm1;
        }
    }

此时访问http://<ip> , 返回index目录下的文件列表, 如下图:

    ○ 基于端口的虚拟主机

在每个server中设置不同的端口即可实现根据端口来区别虚拟主机

    ○ 基于ip的虚拟主机

为了方便测试, 可以使用命令配置一个网卡多个ip

ifconfig <网卡名称>:<标志(从0-255)> <自定义ip>/24 up

如: ifconfig ens33:0 192.168.5.200/24 up

或者

ip addr add <自定义ip>/24 dev <网卡名称> label <网卡名称>:<标志(0-255)>

如: ip addr add 192.168.5.201/24 dev ens33 label ens33:1

 //2019/01/19 17点更新=========================>>>>

主配置文件的优化

① 引入子配置文件

 一般来讲, 主配置文件不需要轻易经常改动它, 所以一般采用引入子配置文件的方式.

在主配置文件的http{...}域内引入include subConf/*.conf;  //代表引入当前目录的subConf文件夹下的所有.conf文件

② 别名

别名的好处:

○ 简单讲可以区分有没有加"www"

○ 当服务器有多台时, 为了能有效监控具体是哪一台宕机, 给不同的server配置不同的别名, 而对外仍是统一的域名.

做法:

在server域中配置server_name时, 空格隔开, 并写上需要的别名即可.

③ 状态

 在server域中配置stub_status on;  //开启状态信息

④ 日志

日志的级别: debug | info | notice | warm | error| alert | emerg

日志配置的位置: http域 / server域 / location域

● 错误日志 

日志的配置格式: error_log <错误日志存放位置> <错误日志级别>

日志的默认值: error_log logs/error.log error

ps: 在做web服务器时不要将日志的级别配置成比info级别(包含info)还低, 那样会带来极大的I/O消耗

● 访问日志

顾名思义, 访问网站时就会记录起来的日志信息(包括内容, 地址, 大小...)

日志格式:

日志格式配置的位置: http域

默认:

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

自定义日志格式:  根据需要自行组合配置日志格式

$remote_addr  //记录访问网站的客户端地址

$http_x_forwarded_for  //用于当前端有代理服务器时, 可以记录初始客户访问时的地址, 需要结合代理服务器上也有相关的x_forwarded_for的设置

$remote_user  //远程客户端用户名称

$time_local  //记录访问的时间和时区

$request  //用户http的请求信息

$status  //记录http请求返回的状态码

$body_bytes_sent  //服务器响应的body字节数

$http_referer  //记录请求来自哪里, 如判断该流量是否是由推广网站推广而来的流量; 可以根据referer进行防盗链的设置

$http_user_agent  //记录客户端的访问信息, 如来自浏览器 / 手机...

日志的配置格式: 

access_log <日志存放位置> <日志格式>, 如: access_log logs/access_log main

● 日志的轮询切割

采用的方式: cron+script

配置脚本cut_nginx_log.sh, 内容为:

cd /application/nginx/logs    //进入logs文件夹
mv access.log access_$(date +%F -d '-1day').log    //重命名日志文件
/application/nginx/sbin/nginx -s reload    //重新加载配置文件, 会生成一个新的access.log文件

定时任务:

使用命令设置定时任务: crontab -e

设置定时任务: 00 00 * * * sh /application/nginx/scripts/cut_nginx_log.sh  //每周每月每天晚上00点00分执行cut_nginx_log.sh脚本

 //2019/01/20  19点更新=========================>>>>

location & rewrite的应用

● location 

可以根据用户请求的uri来执行不同的操作,  简单理解, location域就是相当于if(){...}else{...}的判断, 满足则执行.

○ location的匹配规则有 '=' | '~' | '~*' | '^~' | '@' 

'='  //精准匹配

'~'  //字符串匹配(区别大小写)

'~*'  //字符串匹配(不区别大小写)

'^~'  //校验字符串后不再进行正则表达式的校验

ps: 经过测试, 该符号的校验需要跟无符号校验相比才能体现优势, 如果是跟同样有符号标志进行校验相比的话还是会按照顺序谁先被校验到就匹配谁.

'@'  //内部转发, 很少用, 官方文档如下 

ps: 以上校验均可以用"!"进行取反操作; 另外还可以不使用以上等符号, 直接写路径进行匹配, 不过级别较低.

○ 对应匹配位置

请求的uri 完整的url地址
/ http://xxx/
/index.html http://xxx/  |  http://xxx/index.html
/documents/document.html http://xxx/documents/document.html
/images/zz.gif http://xxx/images/zz.gif

○ 总而言之, 虽然上面提到了有符号校验跟无符号校验相比较才会占优势, 但是大体上平时用到的还是以下面这个表格的优先级来考虑

优先级从高到低 说明
location = xxx {...} 精准匹配最高优先级
location ^~ /xxx/ {...}

匹配常规字符串, 一旦匹配上则不再校验后面的正则

location ~* \.(gif|jpg|png)$ 正则匹配
location /xxx/ {...} 匹配常规字符串, 有正则则优先正则(即使正则的顺序在后也优先), 这个就是上面提到的无符号的路径校验
location / {...} 默认的匹配(最后的无奈之举...)

● rewrite 

○ 伪静态

rewrite主要功能就是实现url地址的改写, nginx的rewrite功能需要pcre软件的支持, 通过perl兼容正则表达式语法进行规则匹配.

简单讲就是实现将用户的访问路径跳转至其他url, 并且显示在地址栏上

○ rewrite语法

rewrite <要被替代的url, 可以用正则来匹配, 此处的正则不是上面location提到的正则, 而是perl正则, 是开发人员开发时常用到的> <要跳转的url> <标志>

适合的域: server域 / location域 / if{...}

○ 重定向标志permanent & redirect

永久重定向(permanent): 返回状态码301

临时重定向(redirect): 返回状态码302

○ permanent & redirect区别

301(permanent)永久重定向后, 当nginx服务器关闭后, 再次请求原先的地址时, 还会按照重定向后的地址转发过去;  //最常用

302(redirect)临时重定向后, 当nginx服务器关闭后, 再次请求原先的地址时, 还是直接请求服务器, 而此时的服务器已经关闭, 所以无法请求成功

○ 其他两个标志(last & break)

当一个location里面出现了多个rewrite规则时, last标志和break标志就发挥作用了

last: 本条规则匹配完成后, 使用rewrite的url重新自己请求一次服务器

break: 本条规则匹配完成后, 直接跳转到该url

经测试, 我自己对这两个标志的小结是: 

last相当没有通过rewrite, 直接就请求了该url效果; break相当于通过了rewrite, 请求该url的效果; 但两种方式用户本身是无感知的.

 配置文件如下:

curl测试结果:

浏览器访问结果:

○ rewrite的用途

1) 可以调整用户的url, 使之更规范

2) 伪装成静态地址, 体验更好

3) 网站更换新域名后常用的一种跳转方式

4) 根据特殊情况进行url跳转

Nginx的访问认证 

利用Nginx提供的权限验证功能对网站进行权限的验证, 需要使用工具生成一个密钥文件, 存储用户名和密码.

配置文件:

location / {
                auth_basic "limits of authority ! ! !";
                auth_basic_user_file /application/nginx/conf/htpasswd;
                root html;
                index index.html;
        }

使用工具httpd-tools的htpasswd命令来生成密钥文件

命令安装httpd-tools工具: yum install httpd-tools -y

命令生成密钥文件: htpasswd -cb <文件路径, 如上/application/nginx/conf/htpasswd> <自定义用户名> <自定义密码>

浏览器输入http://ip:port访问, 如下图:

//2019/01/21  更新=========================>>>>

记录下出现403的可能原因

● 没有首页文件

● 没有读取某文件的权限

● 没有首页配置文件(配置autoindex on  //配置展示列表功能, 可供下载(不安全))

Nginx的常见问题

1. 多个相同的server_name中虚拟主机的读取优先级

当出现多个虚拟主机的server_name都相同时(此时监听的端口号也相同), nginx此时会根据先读取到的虚拟主机就一直是优先使用它, 比如, 此时我系统中有多个xxx.conf文件, 分别命名为server1.conf, server2.conf, server3.conf, 那么nginx一定会先读取server1.conf, 并且一直是使用它的虚拟主机来作为nginx本次启动的相对应的监听对象

2. 多个location匹配的优先级

=      进行普通字符精确匹配, 也就是完全匹配(优先级最高)

^~    表示普通字符匹配, 使用前缀匹配(优先级次之)

~  或者  ~*  表示执行一个正则匹配(~表示区分大小写, ~*表示不区分大小写)

完全匹配和前缀匹配一旦匹配上就立即结束匹配, 而正则匹配即使匹配上了还会继续往下匹配, 直到找到最合适的匹配为止

3. try_files的使用

try_files的作用是按顺序检查文件是否存在

将try_files写在location域中, 当请求匹配到该location时, try_files首先检查路径的文件是否存在, 存在则返回给客户端, 不存在则按照指定规则处理(类似于重定向处理).

使用方式:

        location / {
                root /opt/app/code/cache;  //指定文件路径
                try_files $uri @java_page;  //$uri表示在指定的文件路径下查找, 如果没有则跳转至@java_page的location中
        }

        location @java_page {  //内部跳转的location
                proxy_pass http://127.0.0.1:8906;
        }

4. root和alias的区别

访问路径: http://<ip>:<端口>/testRoot/image/cat.png

root:

        location /testRoot/image/ {
                root /local_path/images/pic/;
        }

实际访问路径变成: http://<ip>:<端口>/local_path/images/pic/testRoot/image/cat.png
alias:

        location /testRoot/image/ {
                alias /local_path/images/pic/;
        }

实际访问路径变成: http://<ip>:<端口>/local_path/images/pic/cat.png

5. 获取用户真实ip信息

针对经过很多层代理或中转的情况, 容易出现真是ip地址无法获取.

$remote_addr无法获取, $x_forwarded_for容易被篡改

解决方法: 跟第一级代理约定一个变量专门传递$remote_addr信息, set <变量名> = $remote_addr

6. 常见错误码

介绍几个Nginx的错误码

① 413 Request Entity Too Large  //上传文件大小限制 client_max_body_size(默认1m)

② 502 Bad Gateway  //后端服务无响应, 可能动态服务器关闭或宕机

③ 504 Gateway Time-out   //后端服务执行超时

//2019/01/26  更新=========================>>>>

Nginx的性能优化

● 需要考虑的方面

    ○ 当前系统的结构如何

        * 观察指标(日志检测)

        * 压力测试

    ○ 了解业务模式

        * 接口业务类型

        * 系统层次化结构

    ○ 性能与安全

        * 设计防火墙的严密程度

● 压测工具ab

用于系统没有真正进入实际业务之前的准备工作

    ○ ab接口压力测试工具

        * 安装: yum install httpd-tools

        * 使用: ab -n <请求总数> -c <并发级别> <要测试的域名地址>        //-k 是否开启长连接

    ○ 压测

        ab -n 2000 -c 2 http://<ip>:<端口>/<访问路径>, 结果如下:

可见, Nginx处理静态请求的效率还是非常高的 

● 系统与Nginx的性能优化

    ○ 网络

    ○ 系统

        * 文件句柄

Linux上一切皆文件, 而文件句柄就是一个索引, 每当发起一个请求, 对Linux来说就是一个句柄

        * 设置方式

当请求与执行的操作越来越多时, 句柄也随之增加, 那么对系统就会带来损耗, 系统默认是有对句柄进行限制的, 因为系统的资源是有限的.

            ※ 系统全局性修改(进入/etc/security/limits.conf)

            ※ 用户局部性修改(进入/etc/security/limits.conf)

            ※ 进程局部性修改(进入nginx.conf)

    ○ 硬件

        * CPU的亲和(进入/proc/cpuinfo)

把对于在不同worker上工作的进程绑定到不同的CPU块, 这样可以减少不同进程在不同CPU块之间进行切换的损耗

使用命令查看当前系统的CPU个数和每个CPU的核数

CPU个数: cat /proc/cpuinfo |grep "physical id" |sort |uniq|wc -l

单个CPU核数: cat /proc/cpuinfo |grep "cpu cores"|uniq

CPU总核数: CPU个数*单个CPU核数

配置参数worker_cpu_affinity auto;    //自动做cpu块与worker控制的进程之间的绑定 

    ○ 服务

    ○ 程序

    ○ 数据库 / 底层服务

附上一份比较通用的配置:

//2019/02/19  更新=========================>>>>

Nginx架构总结

☞ 需要考虑的方面

    ● 了解需求

        ○ Nginx所能扮演的角色

            ※ 静态资源服务

            ※ 代理服务

            ※ 动静分离

        ○ 静态资源服务的功能设计

            ※ 类型分类(不同类型文件匹配不同的规则)

            ※ 浏览器端的缓存设置(不同场景的缓存时间设置不同)

            ※ 防盗链(防止资源被随意盗用)

            ※ 流量的限制(防止服务端的流量被瞬间占用完)

            ※ 静态资源的压缩(选择适当的压缩比率能够将服务端的性能最大化利用并且减少流量的消耗)

        ○ 代理服务

            ※ 根据需求选定具体的协议类型

            ※ 正向、反向代理

            ※ 反向代理 ==> 负载均衡(不同的哈希策略、超时重连的时间)

            ※ 缓存设置(缓存内容的时间长短设置、缓存内容的类型、缓存内容的存放目录)

            ※ 头信息的处理(获取用户的头信息,包括自定义和必带的头信息)

    ● 设计评估

        ○ 硬件(CPU、内存和硬盘的性能,根据角色的不同有所侧重,如只做代理服务则要求CPU和内存的性能高些;做静态资源存储则要求硬盘性能高些)

        ○ 系统(用户权限、日志目录的存放位置)

        ○ 关联服务

    ● 配置的注意事项

        ○ 合理配置(配置的作用域不同,影响范围不同)

        ○ 了解原理(HTTP协议、状态,操作系统等)

        ○ 关注日志(分析日志)

暂完!

猜你喜欢

转载自blog.csdn.net/ip_JL/article/details/86361088