Nginx配置导致的503 Service Temporarily Unavailable问题
问题场景:
这两天由于公司人自己请求网站之后,导致网站服务器超负载,为了避免这种攻击我将 Nginx 配置了单个 IP 的并发限制,当天还没有问题,但是第二天早上网站访问量多的时候,浏览器出现页面 503 Service Temporarily Unavailable,然后我多次刷新,有时候刷新页面正常显示,有时候刷新页面出现样式未加载出来(样式错乱,因为加载 css 文件返回 503 状态)的情况,有时候刷新再次出现 503 Service Temporarily Unavailable。
问题分析:
503 Service Temporarily Unavailable 的意思是服务暂时不可用,结合我上次的配置,我猜测应该是小站并发高了之后导致单个 IP 超过了我所配置的单个 IP 所允许并发数量。
至于为什么全站的并发高了之后才出现 503 Service Temporarily Unavailable 呢,刚刚配置单个 IP 并发限制我访问页面是正常的。这个原因应该是全站的访问并发高了之后服务器负载高,服务器处理不过来,所以对于单个 IP 请求一个页面的时候还未处理完成,再次刷新或者跳转别的页面的时候又加入的新的多次请求(包括各种静态文件的请求),所以服务器存在的请求超出了单个 IP 并发配置的限制,而全站并发不高的时候意味着访问量少,服务器负载低,单个 IP 请求的并发也相对较少,则不容易出现返回 503 Service Temporarily Unavailable 的情况。
解决方案:
修改nginx单个 IP 并发限制的配置,将单个 IP 并发数限制提升到 20,这个数字取决于你访问一个页面最多需要走多少次**nginx**,一般看一次页面有多少次通过**nginx**的请求,包括 css 文件、图片文件、字体文件和 js 文件等等。
配置后重新 reload 配置,就再也没有出现过页面显示 503 Service Temporarily Unavailable 的情况,当然可能是负载突然下降了的原因,还需要进一步测试,暂时先这样处理。
本次将nginx.conf配置文件的server部分配置修改:
1 | // 单个IP并发数限制 |
Nginx 限制并发连接数与下载速度配置
ngx_http_limit_conn_module 模块用于限制每个定义密钥的连接数,特别是来自单个 IP 地址的连接数。而 ngx_http_core_module 则可以限制下载速度,这两个均是Nginx内置模块,不需要额外安装。
ngx_http_limit_conn_module 限制连接数
1 | #需要写在http段内 |
- $binary_remote_addr : nginx 变量,指的是客户端 IP
- zone : 域的名字,随便填写,这里设置的是 addr,后面会再次用到
- 10m : 设置共享内存我的理解是客户端的 IP 会被放入这个内存中,总共享内存不能超过 10M,不知道对不对。
- limit_conn addr 10 : 限制 addr 这个域的最大连接数为 10
但是在HTTP/2中每个并发请求被视为单独的连接,如果网站启用了HTTP/2上面的设置就没有作用了,可以继续改进一下。以下配置将限制每个客户端 IP 与服务器的连接数,同时限制与虚拟服务器的连接总数。
1 | #写在http段内 |
更多详细说明可参考Nginx官方文档:http://nginx.org/en/docs/http/ngx_http_limit_conn_module.html
ngx_http_core_module 限制下载速度
1 | #数据达到100M后再限制速度(注意:这里指的是单个连接达到100M) |
- limit_rate_after : 指的是请求的数据达到指定大小后才开始限速(这里设置的是 100M)
- limit_rate : 设置单个连接限速值,这里设置的是 10k/s,如果限制同一 IP 最大连接数为 10 的话,那么总的下载速度不能超过 100k/s
更多说明参考Nginx官方文档:http://nginx.org/en/docs/http/ngx_http_core_module.html#limit_rate
同时限制连接数和下载速度
将上面的配置整合一下,我们既要限制单 IP 的最大连接数,也需要限制下载速度。
1 | #写在http段内 |
上面配置的含义是限制单个 IP 最大连接数为 10 个,同时限制单个虚拟服务器的连接总数为 100 个。当请求的数据达到 100M 后(指单个连接达到 100M)限制连接速度为为 10k/s,如果产生了 10 个连接,最大速度不能超过 100k/s
写在最后
配置修改后建议用 nginx -t 先检查语法,确保没有问题,别忘记重载 Nginx 使其生效。