一个nginx 回源限速的bug处理过程记录
一个生产环境,nginx占用cpu很高。
top - :: up day, :, users, load average: 13.26, 13.20, 13.20
Tasks: total, running, sleeping, stopped, zombie
Cpu(s): 21.3%us, 18.0%sy, 0.0%ni, 57.4%id, 0.0%wa, 0.0%hi, 3.3%si, 0.0%st
Mem: 257556M total, 254371M used, 3184M free, 400M buffers
Swap: 0M total, 0M used, 0M free, 200639M cached PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
root .9g .3g .2g R 1.3 :16.31 nginx
root .9g .5g .4g R 1.4 :16.87 nginx
root .9g .5g .4g R 1.4 :35.20 nginx
root .9g .6g .5g R 1.4 :12.50 nginx
root .9g .5g .4g R 1.4 :04.89 nginx
root .9g .7g .6g R 1.5 :46.03 nginx
root .9g .6g .5g R 1.4 :45.09 nginx
root .9g .7g .6g R 1.5 :42.75 nginx
top跟进去单个线程,发现是主线程很高:
top - :: up day, :, users, load average: 12.79, 12.84, 13.04
Tasks: total, running, sleeping, stopped, zombie
Cpu(s): 18.0%us, 21.5%sy, 0.1%ni, 54.6%id, 1.7%wa, 0.0%hi, 4.1%si, 0.0%st
Mem: 257556M total, 253504M used, 4052M free, 400M buffers
Swap: 0M total, 0M used, 0M free, 199627M cached PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
root .9g .4g .3g S 1.3 :24.72 nginx
root .9g .4g .3g S 1.3 :07.05 nginx
root .9g .4g .3g S 1.3 :06.36 nginx
root .9g .4g .3g S 1.3 :07.07 nginx
root .9g .4g .3g S 1.3 :06.18 nginx
root .9g .4g .3g S 1.3 :06.70 nginx
root .9g .4g .3g S 1.3 :03.87 nginx
root .9g .4g .3g S 1.3 :06.16 nginx
root .9g .4g .3g S 1.3 :06.51 nginx
root .9g .4g .3g S 1.3 :07.03 nginx
root .9g .4g .3g S 1.3 :07.10 nginx
gdb跟踪一下,发现大量的epoll_wait返回,中间没有任何系统调用:
epoll_wait(, {{EPOLLOUT, {u32=, u64=}}}, , ) =
epoll_wait(, {{EPOLLOUT, {u32=, u64=}}}, , ) =
epoll_wait(, {{EPOLLOUT, {u32=, u64=}}}, , ) =
epoll_wait(, {{EPOLLOUT, {u32=, u64=}}}, , ) =
epoll_wait(, {{EPOLLOUT, {u32=, u64=}}}, , ) =
epoll_wait(, {{EPOLLOUT, {u32=, u64=}}}, , ) =
epoll_wait(, {{EPOLLOUT, {u32=, u64=}}}, , ) =
epoll_wait(, {{EPOLLOUT, {u32=, u64=}}}, , ) =
查看堆栈,
epoll_wait在返回有active的fd的时候,我们并没有去调用recv或者recvfrom,走查代码:
if ((revents & EPOLLOUT) && wev->active) {
if (c->fd == - || wev->instance != instance) {
/*
* the stale event from a file descriptor
* that was just closed in this iteration
*/
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, ,
"epoll: stale event %p", c);
continue;
}
wev->ready = ;
if (flags & NGX_POST_EVENTS) {
ngx_post_event(wev, &ngx_posted_events);
} else {
wev->handler(wev);
}
}
发现 wev->active 有时候不为1,但是在epoll_wait返回的时候,大多数情况是1,为什么没有recv呢?
查看 wev->handler,在 ngx_http_upstream_process_non_buffered_request 中,有这么一个分支判断:
if(downstream->write->delayed)
{
ngx_log_error(NGX_LOG_DEBUG, upstream->log, ,
"[no_buffering_limite_rate] downstream->write->delayed return here. remove upstream read event"); ngx_del_event(upstream->read, NGX_READ_EVENT, );
return;
}
在做了限速的情况下,只删除了 upstream->read 事件,没有删除 upstream->write 事件。
而我们epoll_wait返回的是 EPOLLOUT 事件。
在这种情况下,wev->handler(wev); 由于处理非常快,
delta = ngx_current_msec;
(void) ngx_process_events(cycle, timer, flags);
delta = ngx_current_msec - delta;
这样delta几乎为0,使得下次循环的时候扫描的timer为红黑树的最小值,且这个值都没有超时。
timer = ngx_event_find_timer();
所以我们也看到epoll_wai的超时值大多数时间非常小。
最后,这个问题在满足限速情况下,将NGX_WRITE_EVENT 从epoll中删除,等到了限速不满足的时候,再加入这个event。
一个nginx 回源限速的bug处理过程记录的更多相关文章
- nginx回源使用localhost产生问题
最近测试ngx_http_slice模块,回源的时候填的localhost结果老是超时,还以为是slice模块有问题,后来无意间改成127.0.0.1后就没有问题了 真是见鬼了 #user root; ...
- 年年出妖事,一例由JSON解析导致的"薛定谔BUG"排查过程记录
前言 做开发这么多年,也碰到无数的bug了.不过再复杂的bug,只要仔细去研读代码,加上debug,总能找到原因. 但是最近公司内碰到的这一个bug,这个bug初看很简单,但是非常妖孽,在一段时间内我 ...
- 解决工作中遇到的一个"打开,保存"文件框的bug的过程
工作中遇到的这个问题还是很有意思的.其中嵌套了很多奇葩性的问题. (转载请指明出于breaksoftware的csdn博客) 我们来看下故事的发生过程,QA同学发现我们存在如下的bug 看到如此多的串 ...
- Red Hat5下源码安装mysql5.6过程记录
1.安装cmake包 [root@edu soft]# tar -xzf cmake-.tar.Z [root@edu soft]# cd cmake- [root@edu cmake-]# ./co ...
- CDN 的缓存与回源机制解析
CDN的缓存与回源机制解析 CDN (Content Delivery Network,即内容分发网络)指的是一组分布在各个地区的服务器.这些服务器存储着数据的副本,因此服务器可以根据哪些服务器与用户 ...
- 找bug的过程
关于昨天程序出差我找bug的过程记录 昨天才程序 https://www.cnblogs.com/pythonywy/p/11006273.html ├── xxxx │ ├── src.py │ └ ...
- Dubbo加权轮询负载均衡的源码和Bug,了解一下?
本文是对于Dubbo负载均衡策略之一的加权随机算法的详细分析.从2.6.4版本聊起,该版本在某些情况下存在着比较严重的性能问题.由问题入手,层层深入,了解该算法在Dubbo中的演变过程,读懂它的前世今 ...
- 面试题(造火箭必备技能):请举例一个最有成就感的性能bug
当前,绝大部分招聘都有性能要求或者把其作为加分项(会性能优先),哪怕你不是面试的性能,面试的时候可能会问性能,所以大家才会有"面试造火箭,进去拧螺丝"的共鸣.至于企业为什么重视性能 ...
- nginx做下载限速
nginx做下载限速-szszszsz-ChinaUnix博客 nginx做下载限速 2009-12-25 14:34:57 分类: 系统运维 nginx做下载服务器,在性能上满足需求.自带limit ...
随机推荐
- FCC JS基础算法题(11):Seek and Destroy (摧毁数组)
题目描述: 实现一个摧毁(destroyer)函数,第一个参数是待摧毁的数组,其余的参数是待摧毁的值. 我们可以使用arguments来进行参数的遍历. function destroyer(arr) ...
- Ros Kinetic 配置 OpenCV2和CV_bridge (Python, C++)
本篇介绍如何在Ros-kinetic环境下运用opencv2进行开发的配置,系统平台为64位Ubuntu16.04. 需要系统环境: 1.Ros kinetic版本,一般自带cv_bridge, 若没 ...
- linux 内存使用情况详解
一:首先是先登录 二:查看当前目录 命令:df -h 三:查看具体文件夹占用情况 命令:du --max-depth=1 -h /data/ 或者:为了快算显示,同时也只是想查看目录整体占用大小 命 ...
- Maven用途
1.使用Maven编译项目,命令是:“mvncompile” 在命令行中,进入pom.xml所在目录,输入命令即可. 2.使用Maven清理项目,命令是:“mvnclean” 3.使用Maven测试项 ...
- PTA——乘2后不变
PTA 7-49 Have Fun with Numbers #include<stdio.h> #include<string.h> #define N 21 int mai ...
- BZOJ 2277 Poi2011 Strongbox
题目大意:一个集合A,包含了0~n-1这n个数.另有一个集合B,满足: 1.B是A的子集. 2.如果a.b均在B中,则(a+b)%n也在B中(a=b亦可) 给出k个数ai,前k-1个不在B中,第k个在 ...
- Hello2 分析
一.打开GreetingServlet.java文件以查看它 hello2应用程序是一个web模块,hello2应用程序的行为几乎与hello1应用程序相同,但是它是使用Java Servlet技术实 ...
- CNN+BLSTM+CTC的验证码识别从训练到部署
项目地址:https://github.com/kerlomz/captcha_trainer 1. 前言 本项目适用于Python3.6,GPU>=NVIDIA GTX1050Ti,原mast ...
- dos2unix 批量转化文件
在windows和linux双平台下开发,同时也用git作为同步工具,但前期没有注意,导致很多文件使用windows下的换行符CRLF 参考资料了解dos2unix可以转化格式. 但有个问题,虽然可以 ...
- Lock的lockInterruptibly()方法
lockInterruptibly()方法能够中断等待获取锁的线程.当两个线程同时通过lock.lockInterruptibly()获取某个锁时,假若此时线程A获取到了锁,而线程B只有等待,那么对线 ...