Nginx 限流的天坑!!

简介: Nginx 限流的天坑!!

问题背景


大家看看这个页面,有没有发现什么问题?


1.png


主页:http://www.javastack.cn/


是的,页面 CSS 样式全丢失了,导致页面混乱。。


这个页面是我人为删除了样式(为了演示),真正出现问题是另外一个页面,最近栈长发现有个页面时不时就会出现样式错乱的问题,很诡异!!


于是这篇就记录下排查过程,和大家分享下解决方案,也许你会觉得这和 Nginx 有啥关系??我也万万想不到,这的确是因为 Nginx 限流引起的。。


开始排查


页面样式错乱,那肯定是检查样式文件呗。


样式文件位置:


2.png


页面中有很多这样的样式文件引入,比如:


<link type="text/css" rel="styleSheet" href="/css/style.css" />
<link type="text/css" rel="styleSheet" href="/css/page.css" />
<link type="text/css" rel="styleSheet" href="/css/plugin.css" />
...


这样写没问题呀,之前一直好好的,很神奇,怎么会时不时样式错乱,开始怀疑自己的认知了。


尝试解决1)


因为项目中使用到了 Spring Boot,而 CSS 文件是放在 /resources/static/css 目录下,我考虑加上 static 试下:


<link type="text/css" rel="styleSheet" th:href="/static/css/style.css" />
<link type="text/css" rel="styleSheet" th:href="/static/css/page.css" />
<link type="text/css" rel="styleSheet" th:href="/static/css/plugin.css" />
...


结果还是不行。


其实使用 Spring Boot,static 目录就是默认的资源目录之一,引用资源文件时并不需要加上 static,我感觉只是做了一次与自我认知对抗的无谓的尝试。


Spring Boot 这些基础的东西我就不介绍了,不会的可以关注公众号Java技术栈,回复:boot,看我整理的系列详细教程,实战源码也上传到了 Github 仓库:


https://github.com/javastacks/spring-boot-best-practice


尝试解决2)


因为项目中使用到了 Thymeleaf(模板引擎),考虑使用 Thymeleaf 的标签 th:href 进行引入试试:


<link type="text/css" rel="styleSheet" th:href="@{/css/style.css}" />
<link type="text/css" rel="styleSheet" th:href="@{/css/page.css}" />
<link type="text/css" rel="styleSheet" th:href="@{/css/plugin.css}" />
...


改了之后还是没什么用,然后用网页检查模式看页面生成的源码,发现 Thymeleaf 生成的 href 和之前的一样,看来问题并不是出在这里。


解决的转机


就是因为看了一下网页源码,然后我再顺便点了一下 Console 面板:


3.png


然后就发现了这个 503 错误:


503 Service Temporarily Unavailable


然后再点进去 Network 面板看看:



4.png

5.png


终于定位到问题了,样式文件加载失败!!!


这个 503 响应码明显是来自服务器端的错误。


注意到上面的 Network 面板没有,我只发起了一个网页刷新请求,浏览器后台却发起了一堆的请求列表,这里面就包括有 js、css 等静态资源的请求。


什么意思?


也就是说,虽然我只向浏览器发起了一个请求,实际上是向服务器发起了 N 个请求,这和页面上引用到的 css、js 文件数量有关系,这些静态资源的请求也会纳入一个新请求。


如果 Nginx 限流设置的是每秒 5 个请求:


limit_req_zone $binary_remote_addr zone=mylimit:10m rate=5r/s;

而页面上的 css、js 文件数量却达到了 8 个,如果在一秒之内加载完整个页面及附带的 8 个资源,那其他 4 个资源势必会被限流规则挡住,如果是 2 秒加载完就没问题(每秒 4、5 个)。


终于找到了页面时不是时样式错乱的原因了!!


解决方案


既然页面上引入的每个 css、js 文件也算一个请求,那就得调整限流规则了。


可以根据被请求的资源文件数量再作一个限流调整:


limit_req_zone $binary_remote_addr zone=mylimit:10m rate=20r/s;

但这样可能又会影响所有的页面,包括接口,因为每个页面的资源文件数量是不同的,纯接口又是没有页面跳转的,也就不大可能会引用静态资源文件。


我的想法是可以保持之前的所有限流,对 css、js 等静态资源的访问就取消限流。


保持所有限流:


location / {
    limit_req zone=mylimit;
    proxy_pass http://javastack.cn;
}


静态资源不限流:


location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
    proxy_pass http://javastack.cn;
}


修改之后,重新加载 Nginx 配置,反复测试,页面显示正常了。


总结


这个坑其实和 Nginx 本身并没有关系,但却和 Nginx 息息相关,通过这个问题,也让我感觉到很多技术我们只知道简单的用,或者只知其一,不知其二,就比如说我上一个遇到的 Nginx 的坑:


Nginx 转发时的一个坑,运维居然让我背锅!!


这些细节的坑我怎么能想到呢?我不可能把 Nginx 文档全部熟读一遍。。这些问题也只有碰到了才会去尝试解决,不找理由,说白了,还是我掌握的不够深,不够全面吧!


但现实也很残酷,不可能全部技术都学得精深,时间精力也不允许,技术更新也快,但有一点,遇到问题了,我们要学会总结经验,避免下次再犯,这样也是一个知识的积累过程。


相关文章
|
1月前
|
存储 安全 应用服务中间件
解密Nginx限流机制:有效应对DDoS攻击与高并发流量
解密Nginx限流机制:有效应对DDoS攻击与高并发流量
52 0
|
11月前
|
存储 数据采集 算法
Nginx 限流算法大揭秘
Nginx 有多种限流算法....
190 0
Nginx 限流算法大揭秘
|
7月前
|
算法 NoSQL Java
分布式接口幂等性、分布式限流(Guava 、nginx和lua限流)
接口幂等性就是用户对于同一操作发起的一次请求或者多次请求的结果是一致的,不会因为多次点击而产生了副作用。举个最简单的例子,那就是支付,用户购买商品后支付,支付扣款成功,但是返回结果的时候网络异常,此时钱已经扣了,用户再次点击按钮,此时会进行第二次扣款,返回结果成功,用户查询余额返发现多扣钱了,流水记录也变成了两条,这就没有保证接口的幂等性。
|
8月前
|
存储 缓存 算法
Nginx限流和黑名单配置
Nginx限流和黑名单配置
368 0
|
11月前
|
Java 应用服务中间件 nginx
nginx限流配置理解与学习
nginx限流配置理解与学习
139 0
|
存储 算法 中间件
nginx限流方案
nginx限流方案
297 0
|
存储 缓存 算法
|
存储 算法 应用服务中间件
长这么大才读懂高并发核心编程,限流原理与实战,Nginx漏桶限流
使用Nginx可通过配置的方式完成接入层的限流,其ngx_http_limit_req_module模块所提供的limit_req_zone和limit_req两个指令使用漏桶算法进行限流。其中,limit_req_zone指令用于定义一个限流的具体规则(或者计数内存区),limit_req指令应用前者定义的规则完成限流动作。
|
存储 缓存 算法
Nginx 安装配置 | 图床搭建 | Nginx 限流 三大弹
Nginx(“engine x”)是一款是由俄罗斯的程序设计师Igor Sysoev所开发高性能的 Web和 反向代理 服务器,也是一个 IMAP/POP3/SMTP 代理服务器。 在高连接并发的情况下,Nginx是Apache服务器不错的替代品。
263 0
Nginx 安装配置 | 图床搭建 | Nginx 限流 三大弹
|
Web App开发 缓存 网络协议
nginx 限流模块和fail2ban搭配使用
ngnix的限流模块主要有三个: limit_conn 限制某个ip的tcp连接数目或者限制某个server(网站)整体的连接数目 limit_rate 现在每个请求的数据大小 limit_req 限制某个ip的请求次数 其中效果最明显的是第三个limit_req,但是宝塔面板中的流量限制只有前面两项的配置,所以之前一直流量限制没什么用。
377 0
nginx 限流模块和fail2ban搭配使用