Nginx系列之请求处理的11个阶段(下)

上篇博客介绍了PostRead阶段涉及的模块的作用,此篇博客将介绍剩余阶段所涉及的模块作用

Preaccess阶段的limit_conn和limit_req模块

限速(rate limiting)是NGINX中一个非常有用的特性,可以用它来限制在一段时间内的HTTP请求数量,或者连接数量,或者连接的速率。限速可以用于安全防护用途,例如限制密码撞库暴力破解等操作的频率,也可以通过把请求频率限制在一个正常范围来抵御DDoS攻击。不过更常见的使用是通过限制请求的数量来确保后端的upstream服务器不会在短时间内遭受到大量的流量访问从而导致服务异常。limit_conn指令可以设置每个给定键值的最大同时连接数,limit_rate指令对每个连接的速率进行限制。参数rate的单位是字节/秒,设置为0将关闭限速。如下图所示,设置的limit_conn是1,即并发连接数是1,另外,限制建立连接发送请求的速率是50字节/秒。将配置文件引入nginx.conf。开启两个terminal,第一个输入curl命令后,很缓慢的显示nginx的index.html的内容,同时在第二个terminal中执行curl命令,就会返回500的错误,因为配置文件中定义了limit_conn_status的值是500。

除了limit_conn和limit_rate的设置外,还定义了limit_conn_zone,这里的key是$binary_remote_addr, 即对每个发送请求的客户端IP进行限制,另外zone=addr:10m,zone的名称可以任意自定义,后面是建立连接时所需的共享内存大小设置,这里设置的是10m。为什么建立连接的时候需要设置共享内存呢?因为多个work进程的内存是共享的,这样当nginx启动多个work进程时,如果对一个客户端IP进行了限制,当不同的请求发送到不同的work进程时,也能按设置的值限制。

Nginx系列之请求处理的11个阶段(下)_第1张图片

 limit_req模块是基于算法来控制http请求的速率,如下图左边所示,上面水龙头类似于客户端发送的请求数量,这个数量无法控制,但是可以增加一个桶,可以通过控制桶往下流的速度来减少突发高峰流量对后端服务的冲击。如果请求太多,把桶都装满了,那么后续再发送过来的请求就会被丢弃掉。限制速率是有效应对突发激增流量的有效手段之一,如下图右边所示,有削峰填谷的效果。

Nginx系列之请求处理的11个阶段(下)_第2张图片

下图是limit_req设置的配置文件,当注释掉burst设置的配置后,开启limit_req zone=one的配置时,因为设置的速率rate=2r/m(每分钟不能大于2个请求,即在发送第一个请求后,必须间隔1分钟后再发送第二个请求,否则会返回错误) 。此时,连续发送两条curl命令给nginx,第二个请求就会返回503错误。如果开启burst=2的配置,注释掉location中最后一条配置,在发送第四次curl命令的时候返回503错误,因为第一次发送的请求被处理,第二次,第三次发送的请求存放到桶里,burst=2,第四次发送请求时,桶已经满了,所以会返回错误。

Nginx系列之请求处理的11个阶段(下)_第3张图片

另外,在上面的配置中还设置了nodelay,nodelay的作用是什么呢?上面的方法虽然使得请求的流量变得“均匀平滑”,但是,很大程度上增加了响应时间,排在队列越后面的请求,等待时间越长,过长的响应时间甚至可能会导致客户端认为请求异常或者直接导致请求超时。为了解决这种情况,可以在brust参数后面加上nodelay参数。加上nodelay参数后,nginx的处理方式和上面基本相同,唯一的区别在于:当nginx接受了第2到3共计2个请求之后,不会把它们放入队列中,而是直接将它们转发给upstream服务器,同时标记队列中的这2个插槽(slot)为已使用,然后把剩下的全部请求都503拒绝掉,接着每过1分钟再释放一个新的slot让新的请求进来。所以,配置nodelay后,在1分钟内前面连续发送的三个请求都会立即返回响应,不会出现延迟的效果,第四个请求返回503错误。

Access阶段的access模块

access模块中可以使用satisfy指令来控制请求被允许还是通过,satisfy all表示只有access模块、auth_basic模块、auth_request模块以及其他模块全都对请求放行才能真的放行。satisfy any表示只要任意模块允许放行,则允许请求往下执行。具体的的判断逻辑如下图所示

Nginx系列之请求处理的11个阶段(下)_第4张图片

Access阶段的auth_basic和auth_request

ngx_http_auth_basic_module模块的作用是,当输入正确的用户密码才允许访问web内容。web上的一些内容不想被其他人知道,但是又想让部分人看到。nginx的http auth模块以及Apache http auth都是很好的解决方案。如下图所示配置,配置时需要指定存放用户名和密码的文件地址,即设置auth_basic_user_file.这里file里面存放的user和password经过了base64简单加密后存放。配置basi_auth后,在浏览器上访问nginx时,就会弹出输入用户名和密码的框,如果输入错误则不被允许访问nginx。生成存放密码文件的信息可借助工具,可以通过下载httpd-tools工具,工具命令格式"htpasswd –c file –b user pass",这条命令执行后就创建了用户名为usr,密码为pass的auth.pass文件。

Nginx系列之请求处理的11个阶段(下)_第5张图片Nginx系列之请求处理的11个阶段(下)_第6张图片

通过auth_basic只能做最简单的用户认证,例如像goaccess展示的日志报告一类的不敏感内容。实际项目中,如果是对后端服务进行认证,那么还需要接入专门的认证服务上进行认证。nginx中的auth_request模块就是用来将请求转发到专门的认证服务的。auth_request的工作原理是:收到请求后,生成子请求,通过反向代理技术把请求传递给上游服务,向上游服务转发请求后,若上游服务返回响应码2xx,则继续执行,若上游服务返回401或者403,则将响应返回给客户端。

如下图所示,再开启一个nginx服务,监听在8090端口,模拟认证服务器,当8090端口的nginx服务返回401时,执行"curl http://taoli.test.pub:8030/auth"也会返回401错误。需要注意一点:auth_request模块默认不会编译进nginx,所以需要通过--with-xx命令编译进去后,才能使用auth_request指令。

下左图,是用nginx模拟认证服务的配置,配置里面return的是401.

Nginx系列之请求处理的11个阶段(下)_第7张图片Nginx系列之请求处理的11个阶段(下)_第8张图片

除了认证功能外,在access阶段还可以在location中配置deny和allow来限制或者允许来自某个IP地址或者某一段IP地址的请求。例如上面右图的配置,这样可以设置IP地址的黑名单或者白名单了。deny和allow也属于access模块的指令。

上面介绍了access模块、auth_basic、auth_request三个模块,当配置文件中都有三个模块的命令时,执行顺序是如何的呢假设配置文件中有如下配置,当访问nginx服务时,不会弹出输入用户名、密码的dialog框,因为deny指令属于access模块,access模块在执行优先级上先于auth模块,因为配置了satisfy all,所以当deny指令拒绝请求后,则不再往下执行。如果配置satisfy any,则会弹出输入用户名、密码的弹框。

location /{
    satisfy all;
    auth_basic "auth";
    auth_basic_user_file auth.pass;
    deny all;
}

PreContent阶段的try-files和mirrors模块

try_files是nginx中http_core核心模块所带的指令,主要是替代一些rewrite的指令,提高解析效率。作用是按顺序检查文件是否存在,返回第一个找到的文件或文件夹(结尾加斜线表示为文件夹),如果所有的文件或文件夹都找不到,会进行一个内部重定向到最后一个参数。如下图所示:配置try_files后,nginx服务器会在配置的多个url中进行匹配,如果都匹配不上,那么可以通过@进行内部重定向,下面的配置文件中重定向到了@lasturl,所以返回了lasturl的信息。

Nginx系列之请求处理的11个阶段(下)_第9张图片

将生产环境的流量拷贝到预上线环境或测试环境,可以带来一些好处,比如:用真实有效的流量请求进行测试验证;可以用来排查线上问题等。Nginx中的mirrors模块就提供了流量复制的功能,mirrors的工作原理是处理请求时,生成子请求发送到其他服务,对子请求的返回值不做处理。下面是一段mirror的配置文件信息。

server {
    server_name taoli.test.pub;
	listen 8009;
	error_log logs/error.log debug;
	location / {
	mirror /mirror;
	#复制子请求到/mirror路径的服务上

	mirror_request_body off;
	#不复制request_body,因为是实验演示,所以这里设置的是off.
	}
	location = /mirror {
	internal;
	proxy_pass http://127.0.0.1:10020$request_uri;
	@#这里可以启动另外一个nginx服务,作为反向代理服务
	proxy_pass_request_body off;
	proxy_set_header Content-Length "";
	proxy_set_header X-Original-URI $request_uri;
	}
}

上面的配置内容可include到nginx1服务上,nginx2服务启动作为模拟的反向代理服务,监听在10020端口。此时用curl命令访问nginx1的服务,查看nginx2的access.log信息,可以看到同样打印了请求的信息,说明请求被复制发送到了nginx2服务上。结果如下所示:

Nginx系列之请求处理的11个阶段(下)_第10张图片

Content阶段的static模块

static模块对于访问nginx服务url不添加最后的反斜杠,默认会返回301重定向,重定向后的域名具体会被改写成什么呢?这里涉及两个指令absolute_redirect,当值为on时,假设访问“curl http://localhost:8088/first”,重定向的Location是"/first/",当值设置为off时,重定向的Location是"http://localhost:8080/first/"。当开启server_name_in_redirect时,重定向的Location是"http://server_name:ListenPort/first/",实验结果如下所示:

Nginx系列之请求处理的11个阶段(下)_第11张图片

当Nginx作为静态资源服务器,在访问某个Url时,还会伴随生成三个环境变量。通过读取环境变量,可以获取到访问的url中的文件路径。

$request_filename       # 访问某url时,访问的真实文件路径
$document_root          # 访问某url时,访问的目录路径
$realpath_root          # 访问某url时,访问的目录路径,和document_root的区别是,如果该目录是个软链接,$realpath_root会显示软链接的真实路径,而$document_root显示的是软链接的路径

Content节点的index、autoindex模块以及concat模块

index file...;  # 默认 index index.html 表示访问一个目录默认访问其内的index.html,可以配置的上下文包括http、location、server。
autoindex on|off;   #默认off,作用是当url以/结尾(即访问目录时)显示目录结构。auto_index_format html|xml|json|jsonp,显示目录结构时使用的格式。如果即配置了index又配置了autoindex,执行顺序是什么呢?因为index模块先于autoindex模块执行,所以,如果这个目录有index.html,则显示index.html,而不是显示目录结构。如果没有index.html,则会显示目录结构。

concat模块的作用是当页面需要访问多个小文件时,把内容合并到一次http响应中返回,从而提升性能。例如访问"https://g.alicdn.cn/??one/first.js,second/second.css/,thrid/third.js"。固定格式是https://xxx??后面跟需要访问的小文件,多个文件间用逗号隔开。另外,nginx默认不会编译进这个模块,需要--with编译进去。concat默认是关闭状态,如果要开启,需要设置成on。concat的部分配置项说明如下
concat on|off;      # 默认 off;可配置的上下文有http、server、location 
concat_types text/css application/x-javascript  # 合并的文件类型
concat_max_files 10     # 最大合并文件数

Nginx系列之请求处理的11个阶段(下)_第12张图片

Log阶段的Log模块

Log模块默认开启,且不能被禁用,安装nginx后,在默认的配置文件中就有关于log的配置,如下所示,log_format定义日志记录的内容,acees_log后面定义log存放的位置,采用的格式等。

Nginx系列之请求处理的11个阶段(下)_第13张图片

以上就是Nginx处理请求的11个阶段涉及的常用模块使用的介绍。

你可能感兴趣的:(微服务,nginx,处理请求11个阶段)