一个生产环境,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); 由于处理非常快,

ngx_process_events_and_timers(ngx_cycle_t *cycle)函数在下面这个逻辑:
    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。

最新文章

  1. WebGIS中等值线前端生成绘制简析
  2. 学习maven的使用,看到一篇很实用的入门教程(菜鸟级入门)
  3. ImageView显示网络图片
  4. sonar-gerrit-plugin-2.2.0 安装
  5. Android中解决图像解码导致的OOM问题
  6. JavaScript初学者应注意的七个细节
  7. POJ 1948 Triangular Pastures【二维01背包】
  8. 24小时学通Linux内核之内存管理方式
  9. Storm概念介绍
  10. mod_wsgi + pymssql通路SQL Server座
  11. scala 读取文件遇到encode问题(Mac -> remote Linux)
  12. 总结:PyQt5自定义信号源
  13. The Lisp Curse /Lisp魔咒
  14. 数组a和&a区别
  15. LinkedList源码解析(JDK1.8)
  16. navicat里导入和导出.sql文件
  17. 阿里云 轻量应用服务器(LAMP) 使用日志记录
  18. spring cloud 微服务日志跟踪 sleuth logback elk 整合
  19. Hibernate入门1 - Hibernate概述及第一个小例子
  20. Linux内核第八节 20135332武西垚

热门文章

  1. sed语法
  2. ffmpeg 视频 转 gif
  3. 框架tensorflow1
  4. [LeetCode&Python] Problem 202. Happy Number
  5. PyCharm:ModuleNotFoundError: No module named 'selenium'
  6. mvn package出现No compiler is provided in this environment. Perhaps you are running on a JRE rather than a JDK
  7. Arch Linux 的休眠设置
  8. cookie和session的关联关系
  9. zabbix安装、部署、lnmp(一)
  10. Guava 3: 集合Collections