一次生产事故让我学会了 Nginx 限速

业余杂谈 herman 265浏览
公告:“业余草”微信公众号提供免费CSDN下载服务(只下Java资源),关注业余草微信公众号,添加作者微信:xttblog,发送下载链接帮助你免费下载!
本博客日IP超过1800,PV 2600 左右,急需赞助商。
极客时间所有课程通过我的二维码购买后返现24元微信红包,请加博主新的微信号:xttblog,之前的微信号好友位已满,备注:返现
所有面试题(java、前端、数据库、springboot等)一网打尽,请关注文末小程序
视频教程免费领

前方的路都是坑,只有你踩过,你才知道,经验就是钱。别问公司里,同样敲的代码,为啥别人比你工资高,因为别人踩的坑比你多。

最近,我们生产服务器就出了一次故障。这个故障本来是一个小问题,但是迫于我们没有运维,就只能我们硬着头皮去自己研究摸索。最终发现了问题并解决了它,它就是一个简单的 Nginx 限速问题。

WIFi 限速

事情经过是这样的,一次,我们生产上服务器大半夜的发出了报警信息。CPU、磁盘、带宽都报警,奇了怪了,最近没有活动啊,为什么大晚上的,服务器异常呢?

服务器带宽爆了

于是,赶紧爬起来,分析 Nginx 的日志信息,发现有人在进行多线程高并发的下载。这是黑客找到了我们的一个缺点,用多线程下载的方式把我们服务器搞垮了。这得赶紧解决,要不然明天又要喝茶。

- [31/May/2018:00:01:03 -0700]  - xxx.ip.addr.xxx  GET /download/xttblog.zip HTTP/1.1 - 192.168.100.15:8188 ups_resp_time: 0.010 request_time: 0.011
- [31/May/2018:00:01:03 -0700]  - xxx.ip.addr.xxx  GET /download/xttblog.zip HTTP/1.1 - 192.168.100.16:8188 ups_resp_time: 0.006 request_time: 0.006
- [31/May/2018:00:01:03 -0700]  - xxx.ip.addr.xxx  GET /download/xttblog.zip HTTP/1.1 - 192.168.100.15:8188 ups_resp_time: 0.013 request_time: 0.013
- [31/May/2018:00:01:03 -0700]  - xxx.ip.addr.xxx  GET /download/xttblog.zip HTTP/1.1 - 192.168.100.17:8188 ups_resp_time: 0.003 request_time: 0.003
- [31/May/2018:00:01:03 -0700]  - xxx.ip.addr.xxx  GET /download/xttblog.zip HTTP/1.1 - 192.168.100.18:8188 ups_resp_time: 0.004 request_time: 0.004
- [31/May/2018:00:01:03 -0700]  - xxx.ip.addr.xxx  GET /download/xttblog.zip HTTP/1.1 - 192.168.100.15:8188 ups_resp_time: 0.012 request_time: 0.013
- [31/May/2018:00:01:03 -0700]  - xxx.ip.addr.xxx  GET /download/xttblog.zip HTTP/1.1 - 192.168.100.18:8188 ups_resp_time: 0.005 request_time: 0.005
- [31/May/2018:00:01:03 -0700]  - xxx.ip.addr.xxx  GET /download/xttblog.zip HTTP/1.1 - 192.168.100.16:8188 ups_resp_time: 0.011 request_time: 0.011
- [31/May/2018:00:01:03 -0700]  - xxx.ip.addr.xxx  GET /download/xttblog.zip HTTP/1.1 - 192.168.100.15:8188 ups_resp_time: 0.447 request_time: 0.759

强大如 CSDN 都在下载时提示禁止使用迅雷进行下载。还有群里一个网友分享的 dl.xabc.io 网站,在并发下载时都会出现故障宕机。

后来我想起来了,必须对下载限速,并且限制多线程下载。有些公司面试中,可能就会问到,如何限制多线程下载?

其实就是服务端根本就不要提供 Content-Length 值。试想一下,如果多线程下载工具得不到文件总大小值,如何分配去分配每个线程需要下载的量呢?不得已,只能通过单线程下载了。

Nginx 中有一个 ngx_http_core_module 模块,该模块中有一个 limit_rate 指令。我们根据它就可以限速,并且配合 ngx_http_limit_conn_module 模块中的 limit_conn 指令可以限制线程数。

http {
    limit_zone xttblog $binary_remote_addr 10m;
    ...
    server {
        ...
        location /download/ {
            ...
            limit_rate 100k; #限制速度 
            limit_rate_after 1m;
            limit_conn xttblog 2; #限制线程
            ...
        }
    }
}

指令 limit_rate 表示设置最高下载速度;指令 limit_rate_after 从下载到你指定的文件大小之后开始限速。但是这个设置是限制的是每一个连接的下载速度,所以如果一个用户打开了多个连接下载,那么它的下载速度就能达到单个连接的限速乘以连接数。

所以,limit_zone 指令定义一个叫“xttblog”的记录区,总容量为 10M,以变量 $binary_remote_addr 作为会话的判断基准(即一个地址一个会话)。限制 /download/ 目录下,一个会话只能进行一个连接。简单点,就是限制 /download/ 目录下,一个 IP 只能发起 2 个连接,多过 2 个,一律 503。

迅雷下载被限制

配置完后,重启 Nginx,迅雷下载不超过 1M,被限制。

360 浏览器下载被限制

360 浏览器下载不超过 1M。

谷歌浏览器下载被限制

谷歌浏览器下载也不超过 1M。其他的我就不在截图了,都被限制了。然后,结果你们都知道了,服务器带宽等都恢复正常。

只有你又当爹又当妈的时候,你才知道这些知识的重要性!

业余草公众号

最后,欢迎关注我的个人微信公众号:业余草(yyucao)!可加QQ1群:135430763(2000人群已满),QQ2群:454796847(已满),QQ3群:187424846(已满)。QQ群进群密码:xttblog,想加微信群的朋友,之前的微信号好友已满,请加博主新的微信号:xttblog,备注:“xttblog”,添加博主微信拉你进群。备注错误不会同意好友申请。再次感谢您的关注!后续有精彩内容会第一时间发给您!原创文章投稿请发送至532009913@qq.com邮箱。商务合作可添加助理微信进行沟通!

本文原文出处:业余草: » 一次生产事故让我学会了 Nginx 限速