一、什么是nginx

Nginx 是一个高性能的 Web 和反向代理服务器

二、Nginx有什么特点

  • 作为 Web 服务器:Nginx 使用更少的资源,支持更多的并发连接,体现更高的效率能够支持高达 50,000 个并发连接数的响应

  • 作为代理服务器:正向代理,反向代理(七层代理、四层代理、负载均衡)

  • 作为邮件代理服务器

三、Nginx高并发原理

nginx 采用的是多进程(单线程) + io多路复用(epoll)模型 实现高并发

3.1 多进程(单线程)

3.1.1 多线程工作模式

Nginx 在启动后,会有一个 master 进程和多个相互独立的 worker 进程。

master接收来自外界的信号,向各worker进程发送信号,每个进程都有可能来处理这个连接。

master 进程能监控 worker 进程的运行状态,当 worker 进程退出后(异常情况下),会自动启动新的 worker 进程。

注意:
worker 进程数,一般会设置成机器 cpu 核数。因为更多的worker 数,只会导致进程相互竞争 cpu,从而带来不必要的上下文切换。

3.1.2 多线程有什么好处?

不仅能提高并发率,而且进程之间相互独立,一个 worker 进程挂了不会影响到其他 worker 进程。

3.2 io多路复用

I/O多路复用 (单个线程,通过记录跟踪每个I/O流(sock)的状态,来同时管理多个I/O流 。)

I/O 多路复用(multiplexing) 这里面的 multiplexing 指的其实是在单个线程通过记录跟踪每一个Sock(I/O流)的状态来同时管理多个I/O流。发明它的原因,是尽量多的提高服务器的吞吐能力。在同一个线程里面, 通过拨开关的方式,来同时传输多个I/O流
在这里插入图片描述
一个请求到来了,nginx使用epoll接收请求的过程是怎样的?

ngnix会有很多连接进来, epoll会把他们都监视起来,然后像拨开关一样,谁有数据就拨向谁,然后调用相应的代码处理。

3.3 总结

每进来一个request,会有一个worker进程去处理。但不是全程的处理,处理到什么程度呢?处理到可能发生阻塞的地方,比如向上游(后端)服务器转发request,并等待请求返回。那么,这个处理
的worker不会这么一直等着,他会在发送完请求后,注册一个事件:“如果upstream返回了,告诉我一声,我再接着干”。于是他就休息去了。这就是异步。此时,如果再有request 进来,他就可以很快再按这种方式处理。这就是非阻塞和IO多路复用。而一旦上游服务器返回了,就会触发这个事件,worker才会来接手,这个request才会接着往下走。这就是异步回调

四、Nginx的安装

访问nginx官方网站:http://www.nginx.org

Nginx版本类型

Mainline version: 主线版,即开发版

Stable version:   最新稳定版,生产环境上建议使用的版本

Legacy versions:  遗留的老版本的稳定版

1、yum安装

1、yum安装
# yum -y install nginx
2、启动(启动前关闭firewalld,selinux内置防火墙)
# systemctl start nginx
3、开机自启nginx
# systemctl enable nginx

2、编译安装

1、环境准备

nginx可以官网下载

1、安装编译环境
yum -y install gcc gcc-c++

2、安装pcre软件包(使nginx支持http rewrite模块)
yum install -y pcre pcre-devel

3、安装 openssl-devel(使 nginx 支持 ssl)
yum install -y openssl openssl-devel 

4、安装zlib
yum install -y zlib zlib-devel gd gd-devel

5、创建用户 nginx
useradd -s /sbin/nologin nginx 

2、编译安装

1、下载并解压安装包
2、编译安装
./configure --prefix=/opt/nginx \
--user=nginx \
--group=nginx \
--with-pcre \
--with-http_ssl_module \
--with-http_v2_module \
--with-http_realip_module \
--with-http_addition_module \
--with-http_sub_module \
--with-http_dav_module \
--with-http_flv_module \
--with-http_mp4_module \
--with-http_gunzip_module \
--with-http_gzip_static_module \
--with-http_random_index_module \
--with-http_secure_link_module \
--with-http_stub_status_module \
--with-http_auth_request_module \
--with-http_image_filter_module \
--with-http_slice_module \
--with-mail \
--with-threads \
--with-file-aio \
--with-stream \
--with-mail_ssl_module \
--with-stream_ssl_module \
--http-client-body-temp-path=/opt/nginx/other/body \    
--http-fastcgi-temp-path=/opt/nginx/other/fastcgi \
--http-proxy-temp-path=/opt/nginx/other/proxy \        
--http-scgi-temp-path=/opt/nginx/other/scgi \          
--http-uwsgi-temp-path=/opt/nginx/other/uwsgi \  

make && make install

详细请看
https://zhuanlan.zhihu.com/p/128579141

五、Nginx配置文件结构

...              #全局块

events {         #events块
   ...
}

http      #http块
{
    ...   #http全局块
    server        #server块
    { 
        ...       #server全局块
        location [PATTERN]   #location块
        {
            ...
        }
        location [PATTERN] 
        {
            ...
        }
    }
    server
    {
      ...
    }
    ...     #http全局块
}

1、全局块:配置影响nginx全局的指令。一般有运行nginx服务器的用户组,nginx进程pid存放路径,日志存放路径,配置文件引入,允许生成worker process数等。

2、events块:配置影响nginx服务器或与用户的网络连接。有每个进程的最大连接数,选取哪种事件驱动模型处理连接请求,是否允许同时接受多个网路连接,开启多个网络连接序列化等。

3、http块:可以嵌套多个server,配置代理,缓存,日志定义等绝大多数功能和第三方模块的配置。如文件引入,mime-type定义,日志自定义,是否使用sendfile传输文件,连接超时时间,单连接请求数等。

4、server块:配置虚拟主机的相关参数,一个http中可以有多个server。

5、location块:配置请求的路由,以及各种页面的处理情况。location 是在 server 块中配置,根据不同的 URI 使用不同的配置,来处理不同的请求

举列:

########### 每个指令必须有分号结束。#################
#user administrator administrators;  #配置用户或者组,默认为nobody nobody。
#worker_processes 2;  #允许生成的进程数,默认为1
#pid /nginx/pid/nginx.pid;   #指定nginx进程运行文件存放地址
error_log log/error.log debug;  #制定日志路径,级别。这个设置可以放入全局块,http块,server块,级别以此为:debug|info|notice|warn|error|crit|alert|emerg
events {
    accept_mutex on;   #设置网路连接序列化,防止惊群现象发生,默认为on
    multi_accept on;  #设置一个进程是否同时接受多个网络连接,默认为off
    #use epoll;      #事件驱动模型,select|poll|kqueue|epoll|resig|/dev/poll|eventport
    worker_connections  1024;    #最大连接数,默认为512
}
http {
    include       mime.types;   #文件扩展名与文件类型映射表
    default_type  application/octet-stream; #默认文件类型,默认为text/plain
    #access_log off; #取消服务日志    
    log_format myFormat '$remote_addr–$remote_user [$time_local] $request $status $body_bytes_sent $http_referer $http_user_agent $http_x_forwarded_for'; #自定义格式
    access_log log/access.log myFormat;  #combined为日志格式的默认值
    sendfile on;   #允许sendfile方式传输文件,默认为off,可以在http块,server块,location块。
    sendfile_max_chunk 100k;  #每个进程每次调用传输数量不能大于设定的值,默认为0,即不设上限。
    keepalive_timeout 65;  #连接超时时间,默认为75s,可以在http,server,location块。
	keepalive_requests; #请求的最大数量,当最大请求数量达到时,连接被关闭。默认是100,QPS(每秒请求数)过高时,需要增大该值,避免过多TIME_WAIT的socket连接
    upstream mysvr {   
      server 127.0.0.1:7878;
      server 192.168.10.121:3333 backup;  #热备
    }
    error_page 404 https://www.baidu.com; #错误页
    server {
        keepalive_requests 120; #单连接请求上限次数。
        listen       4545;   #监听端口
        server_name  127.0.0.1;   #监听地址       
        location  ~*^.+$ {       #请求的url过滤,正则匹配,~为区分大小写,~*为不区分大小写。
           #root path;  #根目录
           #index vv.txt;  #设置默认页
           proxy_pass  http://mysvr;  #请求转向mysvr 定义的服务器列表
           deny 127.0.0.1;  #拒绝的ip
           allow 172.18.5.54; #允许的ip           
        } 
    }
}

六、nginx 虚拟机配置(server块)

什么是虚拟主机?
虚拟主机是一种特殊的软硬件技术,它可以将网络上的每一台计算机分成多个虚拟主机,每个虚拟主机可以独立对外提供www服务,这样就可以实现一台主机对外提供多个web服务,每个虚拟主机之间是独立的,互不影响。

nginx支持三种类型的虚拟主机配置。(通过配置文件中listen来实现)
1、基于域名的虚拟主机 (server_name指令可以设置基于域名的虚拟主机,根据请求头部的内容,一个ip的服务器可以配置多个域名)

	server {
        listen        80;
        server_name  web1.com;
        location /{
            root /tiger/html;
            index index.html index.htm;
                }
        }
    server {
        listen        80;
        server_name  web2.com;
        location /{
            root /1000phone/html;
            index index.html index.htm;
                }
        }

2、基于ip的虚拟主机, (一个主机绑定多个ip地址)

server {
	listen 192.168.95.134:80;
	server_name www.nginx01.com;
	location / {
		root html;
		index index.html index.htm;
	}
}

server {
	listen 192.168.95.100:80;
	server_name www.nginx02.com;
	location / {
		root /root/html;
		index index.html index.htm;
	}
}

3、基于端口的虚拟主机 (端口来区分虚拟主机——应用:公司内部网站,外部网站的管理后台)

server {
	listen 80;
	server_name www.01.com;
	location / {
		root html;
		index index.html index.htm;
	}
}

server {
	listen 8080;
	server_name www.02.com;
	location / {
		root /root/html;
		index index.html index.htm;
	}
}

测试访问:

在/etc/hosts 进行域名解析

浏览器输入:http://01.com/
浏览器输入:http://02.com:8080

七、location块详解

  • location 是在 server 块中配置,根据不同的 URI 使用不同的配置,来处理不同的请求。
  • location 是有顺序的,会被第一个匹配的location 处理。

7.1 location 前缀含义

=    表示精确匹配,优先级也是最高的 
^~   表示uri以某个常规字符串开头,理解为匹配url路径即可 
~    表示区分大小写的正则匹配  
~*   表示不区分大小写的正则匹配
!~   表示区分大小写不匹配的正则
!~*  表示不区分大小写不匹配的正则
/    通用匹配,任何请求都会匹配到
@    内部服务跳转

优先级:(高到低)
精准匹配( = )
前缀匹配(^~)
正则匹配( ~ )
通用匹配( / )

7.2 root 、alias 指令区别

location /img/ {
    alias /var/www/image/;
}
#若按照上述配置的话,则访问/img/目录里面的文件时,ningx会自动去/var/www/image/目录找文件
location /img/ {
    root /var/www/image;
}
#若按照这种配置的话,则访问/img/目录下的文件时,nginx会去/var/www/image/img/目录下找文件。] 
  • alias 是一个目录别名的定义,

  • root 则是最上层目录的定义。

  • 还有一个重要的区别是alias后面必须要用“/”结束,否则会找不到文件的,而root则可有可无。

八、Proxy 代理

8.1 正向代理、反向代理

  • 正向代理:正向代理的过程隐藏了真实的请求客户端,服务器不知道真实的客户端是谁,客户端请求的服务都被代理服务器代替请求。eg:vpn
  • 反向代理:反向代理的过程隐藏了真实的服务器,客户不知道真正提供服务的人是谁,客户端请求的服务都被代理服务器处理。eg:访问www.baidu.com是正向代理的过程、负载均衡

8.2 nginx Proxy 配置

1、代理模块
ngx_http_proxy_module

配置文件

代理
Syntax: 	proxy_pass URL;				   #代理的后端服务器URL
Default: 	—
Context: 	location, if in location, limit_except

缓冲区
Syntax:     proxy_buffering on | off;
Default:    proxy_buffering on;			   #缓冲开关
Context: 	http, server, location
proxy_buffering开启的情况下,nignx会把后端返回的内容先放到缓冲区当中,然后再返回给客户端
(边收边传,不是全部接收完再传给客户端)。

Syntax:   	proxy_buffer_size size;
Default: 	proxy_buffer_size 4k|8k;	   #缓冲区大小
Context: 	http, server, location

Syntax: 	proxy_buffers number size;
Default: 	proxy_buffers 8 4k|8k;		   #缓冲区数量
Context: 	http, server, location

Syntax:    	proxy_busy_buffers_size size;
Default: 	proxy_busy_buffers_size 8k|16k;#忙碌的缓冲区大小控制同时传递给客户端的buffer数量
Context: 	http, server, location

头信息
Syntax: 	proxy_set_header field value;
Default: 	proxy_set_header Host $proxy_host;		#设置真实客户端地址
            proxy_set_header Connection close;
Context: 	http, server, location

超时
Syntax: 	proxy_connect_timeout time;
Default: 	proxy_connect_timeout 60s;				#链接超时
Context: 	http, server, location

Syntax: 	proxy_read_timeout time;
Default: 	proxy_read_timeout 60s;
Context: 	http, server, location

Syntax: 	proxy_send_timeout time; #nginx进程向fastcgi进程发送request的整个过程的超时时间
Default: 	proxy_send_timeout 60s;
Context: 	http, server, location

#buffer 工作原理
1. 所有的proxy buffer参数是作用到每一个请求的。每一个请求会安按照参数的配置获得自己的buffer。proxy buffer不是global而是per request的。

2. proxy_buffering 是为了开启response buffering of the proxied server,开启后proxy_buffers和proxy_busy_buffers_size参数才会起作用。

3. 无论proxy_buffering是否开启,proxy_buffer_size(main buffer)都是工作的,proxy_buffer_size所设置的buffer_size的作用是用来存储upstream端response的header。

4. 在proxy_buffering 开启的情况下,Nginx将会尽可能的读取所有的upstream端传输的数据到buffer,直到proxy_buffers设置的所有buffer们 被写满或者数据被读取完(EOF)。此时nginx开始向客户端传输数据,会同时传输这一整串buffer们。同时如果response的内容很大的 话,Nginx会接收并把他们写入到temp_file里去。大小由proxy_max_temp_file_size控制。如果busy的buffer 传输完了会从temp_file里面接着读数据,直到传输完毕。

5. 一旦proxy_buffers设置的buffer被写入,直到buffer里面的数据被完整的传输完(传输到客户端),这个buffer将会一直处 在busy状态,我们不能对这个buffer进行任何别的操作。所有处在busy状态的buffer size加起来不能超过proxy_busy_buffers_size,所以proxy_busy_buffers_size是用来控制同时传输到客户 端的buffer数量的。
2、配置文件添加 proxy 配置
location{
......
proxy_pass :真实服务器
proxy_redirect :如果真实服务器使用的是的真实IP:非默认端口。则改成IP:默认端口。
proxy_set_header:重新定义或者添加发往后端服务器的请求头
proxy_set_header X-Real-IP :启用客户端真实地址(否则日志中显示的是代理在访问网站)
proxy_set_header X-Forwarded-For:记录代理地址

proxy_connect_timeout::后端服务器连接的超时时间发起三次握手等候响应超时时间
proxy_send_timeout:后端服务器数据回传时间就是在规定时间之内后端服务器必须传完所有的数据
proxy_read_timeout :nginx接收upstream(上游/真实) server数据超时, 默认60s, 如果连续的60s内没有收到1个字节, 连接关闭。像长连接

proxy_buffering on;开启缓存
proxy_buffer_size:proxy_buffer_size只是响应头的缓冲区
proxy_buffers 4 128k; 内容缓冲区域大小
proxy_busy_buffers_size 256k; 从proxy_buffers划出一部分缓冲区来专门向客户端传送数据的地方
proxy_max_temp_file_size 256k;超大的响应头存储成文件。

......
}

8.3 Nginx负载均衡

1、upstream 配置

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

upstream myweb { 
      server 172.17.14.2:8080;
      server 172.17.14.3:8080;
    }
 server {
        ....
        location / {         
           proxy_pass  http://myweb;  #请求转向 myweb 定义的服务器列表         
        } 
upstream mysvr { 
      server  http://172.17.14.2:8080;
      server  http://172.17.14.3:8080;
    }
 server {
        ....
        location  / {         
           proxy_pass  mysvr;  #请求转向myweb 定义的服务器列表         
        } 
2、负载均衡算法

upstream 支持4种负载均衡调度算法:

A、轮询(默认):每个请求按时间顺序逐一分配到不同的后端服务器;

B、ip_hash:每个请求按访问IP的hash结果分配,同一个IP客户端固定访问一个后端服务器。可以保证来自同一ip的请求被打到固定的机器上,可以解决session问题。

C、url_hash:按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器。后台服务器为缓存的时候效率。

D、fair:这是比上面两个更加智能的负载均衡算法。此种算法可以依据页面大小和加载时间长短智能地进行负载均衡,也就是根据后端服务器的响应时间来分配请求,响应时间短的优先分配。Nginx本身是不支持 fair的,如果需要使用这种调度算法,必须下载Nginx的 upstream_fair模块。

3、配置实例

1、热备:如果你有2台服务器,当一台服务器发生事故时,才启用第二台服务器给提供服务。服务器处理请求的顺序:AAAAAA突然A挂啦,BBBBBBBBBBBBBB…

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

2、加权轮询:跟据配置的权重的大小而分发给不同服务器不同数量的请求。如果不设置,则默认为1。下面服务器的请求顺序为:ABBABBABBABBABB…

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

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

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

4、nginx负载均衡配置状态参数

  • down,表示当前的server暂时不参与负载均衡。
  • backup,预留的备份机器。当其他所有的非backup机器出现故障或者忙的时候,才会请求backup机器,因此这台机器的压力最轻。
  • max_fails,允许请求失败的次数,默认为1。当超过最大次数时,返回proxy_next_upstream 模块定义的错误。
  • fail_timeout,在经历了max_fails次失败后,暂停服务的时间。max_fails可以和fail_timeout一起使用。
 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;    
    }
4、Nginx配置 七层/四层 负载均衡

在nginx做负载均衡,负载多个服务,部分服务是需要7层的,部分服务是需要4层的,也就是说7层和4层配置在同一个配置文件中。

worker_processes  8;

events {
        worker_connections  1024;
}
#7层http负载
http {
        include       mime.types;
        default_type  application/octet-stream;
        sendfile        on;
        keepalive_timeout  65;
        gzip  on;

        #app
        upstream  app.com {
                ip_hash;
                server 172.17.14.2:8080;
                server 172.17.14.3:8080;
        }

        server {
                listen       80;
                server_name  app;
                charset utf-8;
                location / {
                        proxy_pass http://plugin.com;
                        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;
                }
                error_page   500 502 503 504  /50x.html;
                location = /50x.html {
                        root   html;
                }
        }
}

nginx在1.9.0的时候,增加了一个 stream 模块,用来实现四层协议(网络层和传输层)的转发、代理、负载均衡等。stream模块的用法跟http的用法类似,允许我们配置一组TCP或者UDP等协议的监听,然后通过proxy_pass来转发我们的请求,通过upstream添加多个后端服务,实现负载均衡。

#4层tcp负载 
stream {
			upstream myweb {
                hash $remote_addr consistent;
                server 172.17.14.2:8080;
                server 172.17.14.3:8080;
        }
        server {
            listen 82;
            proxy_connect_timeout 10s;
            proxy_timeout 30s;
            proxy_pass myweb;
        }
}

九、nginx 实现动静分离

为了加快网站的解析速度,可以把动态页面和静态页面由不同的服务器来解析,加快解析速度。降低原来单个服务器的压力。 在动静分离的tomcat的时候比较明显,因为tomcat解析静态很慢,其实这些原理的话都很好理解,简单来说,就是使用正则表达式匹配过滤,然后交个不同的服务器。
1、代理配置

准备一个nginx代理 两个http 分别处理动态和静态。

  location / {
            root   /var/www/html/upload;
            index  index.php index.htm;
        }

  location ~ .*\.(html|gif|jpg|png|bmp|swf|jpeg)$ {
                proxy_pass http://172.17.14.3:80;
        }
  location ~ \.php$ {
                proxy_pass http://172.17.14.2:80;
        }

2、本地配置

  #服务器1
  location ~ .*\.(html|gif|jpg|png|bmp|swf|jpeg)$ {
            root   /var/www/html/static;
            index  index.html;
        }
  #服务器2
  location ~ \.php$ {
            root   /var/www/html/move;
            index  index.php;
        }

十、nginx 防盗链问题

nginx 防止网站资源被盗用模块

ngx_http_referer_module

如何区分哪些是不正常的用户?

​ HTTP Referer是Header的一部分,当浏览器向Web服务器发送请求的时候,一般会带上Referer,告诉服务器我是从哪个页面链接过来的,服务器借此可以获得一些信息用于处理,例如防止未经允许的网站盗链图片、文件等。因此HTTP Referer头信息是可以通过程序来伪装生成的,所以通过Referer信息防盗链并非100%可靠,但是,它能够限制大部分的盗链情况。

防盗链配置:

# 日志格式添加"$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_refer的请求访问资源;
  • blocked : 允许不是http://开头的,不带协议的请求访问资源;
  • server_names : 只允许指定ip/域名来的请求访问资源(白名单);
[root@localhost ~]# vim /etc/nginx/conf.d/nginx.conf
        location ~ .*\.(gif|jpg|png|jpeg)$ {
                root  /usr/share/nginx/html;                  
                valid_referers none blocked qf.com 192.168.19.135;
                if ($invalid_referer) {
                    return 403;
                }
         }

修改配置文件后需要重新加载
[root@localhost ~]# nginx -s reload -c /etc/nginx/nginx.conf

十一、地址重写 rewrite

11.1 什么是Rewrite

​ Rewrite对称URL Rewrite,即URL重写,就是把传入Web的请求重定向到其他URL的过程。

  • URL Rewrite最常见的应用是URL伪静态化,是将动态页面显示为静态页面方式的一种技术。比如http://www.123.com/news/index.php?id=123 使用URLRewrite 转换后可以显示为 http://www.123.com/news/123.html对于追求完美主义的网站设计师,就算是网页的地址也希望看起来尽量简洁明快。理论上,搜索引擎更喜欢静态页面形式的网页,搜索引擎对静态页面的评分一般要高于动态页面。所以,UrlRewrite可以让我们网站的网页更容易被搜索引擎所收录。

  • 从安全角度上讲,如果在URL中暴露太多的参数,无疑会造成一定量的信息泄漏,可能会被一些黑客利用,对你的系统造成一定的破坏,所以静态化的URL地址可以给我们带来更高的安全性。

  • 实现网站地址跳转,例如用户访问360buy.com,将其跳转到jd.com。例如当用户访问tianyun.com的80端口时,将其跳转到443端口。

11.2 Rewrite 相关指令

1、if 语句
  • 应用环境
server,location
  • 语法
if (condition) {}
if 可以支持如下条件判断匹配符号
~ 					正则匹配 (区分大小写)
~* 				    正则匹配 (不区分大小写)
!~                  正则不匹配 (区分大小写)
!~*		            正则不匹配  (不区分大小写)
-f 和!-f 		    用来判断是否存在文件
-d 和!-d 		    用来判断是否存在目录
-e 和!-e 		    用来判断是否存在文件或目录
-x 和!-x 		    用来判断文件是否可执行

在匹配过程中可以引用一些Nginx的全局变量
$args				请求中的参数;
$document_root	    针对当前请求的根路径设置值;
$host				请求信息中的"Host",如果请求中没有Host行,则等于设置的服务器名;
$limit_rate			对连接速率的限制;
$request_method		请求的方法,比如"GET""POST";
$remote_addr		客户端地址;
$remote_port		客户端端口号;
$remote_user		客户端用户名,认证用;
$request_filename   当前请求的文件路径名(带网站的主目录/usr/local/nginx/html/images /a.jpg)
$request_uri		当前请求的文件路径名(不带网站的主目录/images/a.jpg)
$query_string$args相同;
$scheme				用的协议,比如http或者是https
$server_protocol	请求的协议版本,"HTTP/1.0""HTTP/1.1";
$server_addr 		服务器地址,如果没有用listen指明服务器地址,使用这个变量将发起一次系统调用以取得地址(造成资源浪费);
$server_name		请求到达的服务器名;
$document_uri$uri一样,URI地址;
$server_port 		请求到达的服务器端口号;
2、Rewrite flag

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

last 			    相当于Apache里的[L]标记,表示完成rewrite
break 				本条规则匹配完成后,终止匹配,不再匹配后面的规则
redirect 			返回302临时重定向,浏览器地址会显示跳转后的URL地址
permanent 		    返回301永久重定向,浏览器地址会显示跳转后URL地址

redirect 和 permanent区别则是返回的不同方式的重定向,对于客户端来说一般状态下是没有区别的。而对于搜索引擎,相对来说301的重定向更加友好,如果我们把一个地址采用301跳转方式跳转的话,搜索引擎会把老地址的相关信息带到新地址,同时在搜索引擎索引库中彻底废弃掉原先的老地址。使用302重定向时,搜索引擎(特别是google)有时会查看跳转前后哪个网址更直观,然后决定显示哪个,如果它觉的跳转前的URL更好的话,也许地址栏不会更改,那么很有可能出现URL劫持的现像。在做URI重写时,有时会发现URI中含有相关参数,如果需要将这些参数保存下来,并且在重写过程中重新引用,可以用到 () 和 $N 的方式来解决。

3、Rewrite匹配参考示例
示例1:
# http://www.tianyun.com/a/1.html ==> http://www.tianyun.com/b/2.html
location /a {
    rewrite .* /b/2.html permanent;
    #return 301 /b/2.html;
}

例2:
# http://www.tianyun.com/2019/a/1.html ==> http://www.tianyun.com/2018/a/1.html
location /2019 {
     rewrite ^/2019/(.*)$ /2018/$1 permanent;
}
例3:
# http://www.qf.com/a/1.html ==> http://jd.com
if ( $host ~* qf.com ) {
	rewrite .*	http://jd.com permanent;
}

例4:
# http://www.qf.com/a/1.html ==> http://jd.com/b/2.html
if ( $host ~* qf.com ) {
	rewrite  .*	 http://jd.com$request_uri permanent;
}

例5: 在访问目录后添加/  (如果目录后已有/,则不加/)
# http://www.tianyun.com/test/
# $1: /a/b
# $2: c
# http://$host$1$2/
if (-d $request_filename) {
    rewrite ^(.*)([^/])$ http://$host$1$2/ permanent;
}

例6:
# http://www.tianyun.com/login/tianyun.html ==>  http://www.tianyun.com/reg/login.php?user=tianyun

location /login {
           rewrite ^/login/(.*)\.html$ /reg/login.php?user=$1;
        }

例7:
#http://www.tianyun.com/qf/11-22-33/1.html  ==>  http://www.tianyun.com/qf/11/22/33/1.html
location /qf {
            rewrite ^/qf/([0-9]+)-([0-9]+)-([0-9]+)(.*)$ /qf/$1/$2/$3$4 permanent;
        }

4、set 指令

set 指令是用于定义一个变量,并且赋值

  • 应用环境:
server,location,if
  • 应用示例
例8:
#http://alice.tianyun.com ==> http://www.tianyun.com/alice
#http://jack.tianyun.com ==> http://www.tianyun.com/jack

[root@localhost html]# mkdir jack alice
[root@localhost html]# echo jack.... > jack/index.html
[root@localhost html]# echo alice... > alice/index.html

a. DNS实现泛解析
*   		IN      A			    网站IP

b. nginx Rewrite
if ($host ~* "^www.tianyun.com$" ) {
      break;
  }

if ($host ~* "^(.*)\.tianyun\.com$" ) {
      set $user $1;
      rewrite .* http://www.tianyun.com/$user permanent;
  }
.5、return 指令

return 指令用于返回状态码给客户端

  • 应用环境:
server,location,if
  • 应用示例:
例9:如果访问的.sh结尾的文件则返回403操作拒绝错误
location ~* \.sh$ {
	return 403;
	#return 301 http://www.tianyun.com;
}

例10:80 ======> 443
server {
        listen      80;
        server_name  www.tianyun.com tianyun.com;
        return     301  https://www.tianyun.com$request_uri;
        }
server {
        listen      443 ssl;
        server_name  www.tianyun.com;
        ssl  on;
        ssl_certificate      /usr/local/nginx/conf/cert.pem;
        ssl_certificate_key  /usr/local/nginx/conf/cert.key;
        location / {
            root html;
            index index.html index.php;
        }
    }

[root@localhost html]# curl -I http://www.tianyun.com
HTTP/1.1 301 Moved Permanently
Server: nginx/1.10.1
Date: Tue, 26 Jul 2016 15:07:50 GMT
Content-Type: text/html
Content-Length: 185
Connection: keep-alive
Location: https://www.tianyun.com/

十二、Nginx日志

12.1 nginx 日志介绍

nginx 有一个非常灵活的日志记录模式,每个级别的配置可以有各自独立的访问日志, 所需日志模块 ngx_http_log_module 的支持,日志格式通过 log_format 命令来定义,日志对于统计和排错是非常有利的。

下面总结了 nginx 日志相关的配置 包括 access_loglog_formatopen_log_file_cachelog_not_foundlog_subrequestrewrite_logerror_log

12.2 access_log 指令

访问日志主要记录客户端的请求。客户端向 Nginx 服务器发起的每一次请求都记录在这里。

客户端IP,浏览器信息,referer,请求处理时间,请求URL等都可以在访问日志中得到。当然具体要记录哪些信息,你可以通过log_format指令定义。

语法:

# 设置访问日志
access_log path [format [buffer=size] [gzip[=level]] [flush=time] [if=condition]];
# 关闭访问日志
access_log off; 
  • path 指定日志的存放位置。
  • format 指定日志的格式。默认使用预定义的combined
  • buffer 用来指定日志写入时的缓存大小。默认是64k。
  • gzip 日志写入前先进行压缩。压缩率可以指定,从1到9数值越大压缩比越高,同时压缩的速度也越慢。默认是1。
  • flush 设置缓存的有效时间。如果超过flush指定的时间,缓存中的内容将被清空。
  • if 条件判断。如果指定的条件计算为0或空字符串,那么该请求不会写入日志。

作用域:

可以应用access_log指令的作用域分别有httpserverlocationlimit_except。也就是说,在这几个作用域外使用该指令,Nginx会报错。

基本用法:

access_log /var/logs/nginx-access.log

该例子指定日志的写入路径为/var/logs/nginx-access.log,日志格式使用默认的combined

access_log /var/logs/nginx-access.log buffer=32k gzip flush=1m

该例子指定日志的写入路径为/var/logs/nginx-access.log,日志格式使用默认的combined,指定日志的缓存大小为 32k,日志写入前启用 gzip 进行压缩,压缩比使用默认值 1,缓存数据有效时间为1分钟。

12.3 log_format 指令

Nginx 预定义了名为 combined 日志格式,如果没有明确指定日志格式默认使用该格式:

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

如果不想使用Nginx预定义的格式,可以通过log_format指令来自定义。

语法

log_format name [escape=default|json] string ...;
  • name 格式名称。在 access_log 指令中引用。
  • escape 设置变量中的字符编码方式是json还是default,默认是default
  • string 要定义的日志格式内容。该参数可以有多个。参数中可以使用Nginx变量。

log_format 指令中常用的一些变量:

变量含义
$bytes_sent发送给客户端的总字节数
$body_bytes_sent发送给客户端的字节数,不包括响应头的大小
$connection连接序列号
$connection_requests当前通过连接发出的请求数量
$msec日志写入时间,单位为秒,精度是毫秒
$pipe如果请求是通过http流水线发送,则其值为"p",否则为“."
$request_length请求长度(包括请求行,请求头和请求体)
$request_time请求处理时长,单位为秒,精度为毫秒,从读入客户端的第一个字节开始,直到把最后一个字符发送张客户端进行日志写入为止
$status响应状态码
$time_iso8601标准格式的本地时间,形如“2017-05-24T18:31:27+08:00”
$time_local通用日志格式下的本地时间,如"24/May/2017:18:31:27 +0800"
$http_referer请求的referer地址。
$http_user_agent客户端浏览器信息。
$remote_addr客户端IP
$http_x_forwarded_for当前端有代理服务器时,设置web节点记录客户端地址的配置,此参数生效的前提是代理服务器也要进行相关的x_forwarded_for设置。
$request完整的原始请求行,如 “GET / HTTP/1.1”
$remote_user客户端用户名称,针对启用了用户认证的请求
$request_uri完整的请求地址,如 “https://qf.com/”

自定义日志格式的使用:

access_log /var/logs/nginx-access.log main

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

使用log_format指令定义了一个main的格式,并在access_log指令中引用了它。假如客户端有发起请求:https://qf.com/,我们看一下我截取的一个请求的日志记录:

192.168.95.134 - - [20/Feb/2019:12:12:14 +0800] "GET / HTTP/1.1" 200 190 "-" "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Mobile Safari/537.36" "-"

我们看到最终的日志记录中$remote_user$http_referer$http_x_forwarded_for都对应了一个-,这是因为这几个变量为空。

12.4 error_log 指令

错误日志在Nginx中是通过error_log指令实现的。该指令记录服务器和请求处理过程中的错误信息。

语法

配置错误日志文件的路径和日志级别。

error_log file [level];
Default:	
error_log logs/error.log error;

file 参数指定日志的写入位置。

level 参数指定日志的级别。level可以是debug, info, notice, warn, error, crit, alert,emerg中的任意值。可以看到其取值范围是按紧急程度从低到高排列的。只有日志的错误级别等于或高于level指定的值才会写入错误日志中。默认值是error

基本用法

error_log /var/logs/nginx/nginx-error.log

配置段:mainhttp, mail, stream, server, location作用域。

例子中指定了错误日志的路径为:/var/logs/nginx/nginx-error.log,日志级别使用默认的 error

12.5 open_log_file_cache 指令

每一条日志记录的写入都是先打开文件再写入记录,然后关闭日志文件。如果你的日志文件路径中使用了变量,如 access_log /var/logs/$host/nginx-access.log,为提高性能,可以使用open_log_file_cache指令设置日志文件描述符的缓存。

语法

open_log_file_cache max=N [inactive=time] [min_uses=N] [valid=time];

默认值: 
open_log_file_cache off;
  • max 设置缓存中最多容纳的文件描述符数量,如果被占满,采用LRU算法将描述符关闭。
  • inactive 设置缓存存活时间,默认是10s。
  • min_usesinactive时间段内,日志文件最少使用几次,该日志文件描述符记入缓存,默认是1次。
  • valid:设置多久对日志文件名进行检查,看是否发生变化,默认是60s。
  • off:不使用缓存。默认为off。

基本用法

open_log_file_cache max=1000 inactive=20s valid=1m min_uses=2;

配置段:httpserverlocation作用域中。

例子中,设置缓存最多缓存1000个日志文件描述符,20s内如果缓存中的日志文件描述符至少被被访问2次,才不会被缓存关闭。每隔1分钟检查缓存中的文件描述符的文件名是否还存在。

12.6 log_not_found 指令

是否在error_log中记录不存在的错误。默认是

基本语法:

log_not_found on | off;
默认值: 
log_not_found on;

配置段: http, server, location作用域。

12.7 log_subrequest 指令

是否在access_log中记录子请求的访问日志。默认不记录

基本语法:

log_subrequest on | off;

默认值: 
log_subrequest off;

配置段: http, server, location作用域。

12.8 rewrite_log 指令

ngx_http_rewrite_module模块提供的。用来记录重写日志的。对于调试重写规则建议开启,启用时将在error log中记录notice级别的重写日志。
基本语法:

rewrite_log on | off;

默认值: 
rewrite_log off;

配置段: http, server, location, if作用域。

12.9 nginx 日志配置总结

Nginx中通过access_logerror_log指令配置访问日志和错误日志,通过log_format我们可以自定义日志格式。如果日志文件路径中使用了变量,我们可以通过open_log_file_cache 指令来设置缓存,提升性能。其他的根据自己的使用场景定义。

十三、错误页面配置

只需要在server中增加以下配置即可:

error_page  404 403 500 502 503 504  /404.html;
location = /404.html {
    root   /usr/local/nginx/html;
}

404 403...为错误类型,/404.html  为这种类型错误对应跳转页面

十四、流量控制

十五、访问控制

十六、nginx监控

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐