昨晚和一位读者朋友讨论了一个问题:在一台多核 CPU 的 Web 服务器上,存在负载不均衡问题,其中 CPU0 的负载明显高于其它 CPUx,进一步调查表明 PHP-FPM 的嫌疑很大。话说以前我曾经记录过软中断导致过类似的问题,但是本例中可以排除嫌疑。
让我们在一台四核服务器上采样分析一下数据确认看看是否存在负载不均衡问题:
shell> mpstat -P ALL 1 10

CPU    %usr   %nice    %sys %iowait    %irq   %soft ... %idle
all   17.57    0.03    1.78    0.00    0.35    0.23 ... 80.04
 0   43.17    0.00    4.12    0.00    1.41    1.00 ... 50.30
 1    9.80    0.00    0.81    0.00    0.00    0.00 ... 89.39
 2    9.31    0.00    1.20    0.00    0.00    0.00 ... 89.49
 3    7.94    0.10    0.80    0.00    0.00    0.00 ... 91.16

如上命令的含义是每秒运行一次 mpstat,一共采样 10 次取平均值,可以明显看出 CPU0 的空闲 idle 明显小于其它 CPUx,而且大部分都消耗在了用户态 usr 上面。
再让我们通过 pidstat 来确认一下是不是 PHP-FPM 导致的 CPU0 负载问题:
shell> pidstat | grep php-fpm | awk '{print $(NF-1)}' | sort | uniq -c

157 0
34 1
34 2
32 3

可见分配给 CPU0 的 PHP-FPM 进程比其他三个 CPUx 总和还要多。为什么大部分进程被分配给了 CPU0?我模模糊糊有一些印象是因为操作系统偏爱使用 CPU0,但我暂时也没找到实质的线索可以佐证,如果有人知道,麻烦告诉我。
问题总要解决,既然 PHP-FPM 没有类似 Nginx 那样 CPU 亲缘性(affinity)绑定的指令,那么我们可以使用 taskset 绑定 PHP-FPM 进程到固定的 CPUx 来解决问题:
#!/bin/bash

CPUs=$(grep -c processor /proc/cpuinfo)
PIDs=$(ps aux | grep "php-fpm[:] pool" | awk '{print $2}')

let i=0
for PID in $PIDs; do
   CPU=$(echo "$i % $CPUs" | bc)
   let i++

taskset -pc $CPU $PID
done

如上脚本运行后,让我们再来看看各个 CPU 负载分配情况如何:
shell> mpstat -P ALL 1 10

CPU    %usr   %nice    %sys %iowait    %irq   %soft ...  %idle
all   15.73    0.03    1.61    0.00    0.20    0.23 ...  82.20
 0   16.28    0.10    1.62    0.10    0.81    0.91 ...  80.18
 1   16.16    0.10    1.51    0.00    0.00    0.10 ...  82.13
 2   14.46    0.10    1.71    0.00    0.00    0.00 ...  83.73
 3   15.95    0.00    1.71    0.00    0.00    0.00 ...  82.35

终于平均了,不过需要提醒的是,一旦 PHP-FPM 处理的请求数超过 max_requests 的设置,那么对应的进程将自动重启,先前的 taskset 设置也将失效,所以为了一直有效,我们需要把 taskset 脚本添加到 CRON 配置中去,例如每分钟自动设置一遍!
本文把 PHP-FPM 进程平均分配给了 0,1,2,3 四个 CPU,实际操作的时候可以更灵活一些,比如前文我们提过,操作系统总是偏爱使用 CPU0,如果 CPU0 的负载已经很高了的话,那么我们不妨把 PHP-FPM 进程平均分配给 1,2,3 三个 CPU。

原文链接

记录一个多核CPU负载不均衡问题(动态绑定进程到指定cpu:taskset -pc $CPU $PID)的更多相关文章

  1. 有趣的taskset命令,使进程再指定CPU上运行

    前言 taskset命令,用于进程的CPU调优,可以把某进程,指定再某CPU内工作. 如还不明白,可以参考此文 http://www.361way.com/linux-context-switch/5 ...

  2. cpu负载的探讨 (转)

    文章出处:http://blog.chinaunix.net/uid-12693781-id-368837.html 摘要:确定cpu的负载的定义,帮助管理员设置cpu负载阀值,推测可能的导致cpu负 ...

  3. cpu负载的探讨

    原链接:http://blog.chinaunix.net/uid-12693781-id-368837.html 摘要:确定cpu的负载的定义,帮助管理员设置cpu负载阀值,推测可能的导致cpu负载 ...

  4. eCos系统CPU负载测量

    原文:http://ecos.sourceware.org/docs-latest/ref/services-cpuload.html 译文:http://blog.csdn.net/zoomdy/a ...

  5. 如何获取多核、多cpu系统中指定cpu的序列号

    如何获取多核.多cpu系统中指定cpu的序列号作者:SkyJacker(转贴请保持完整并注明作者和出处)http://www.cnpack.orgCnPack IV  QQ Group: 130970 ...

  6. Process和Thread在指定CPU运行

    最近帮朋友写了一个多线程程序,他那边一运行多线程就出错,我这边却没有任何问题,找了好久才找到解决方法,原来是CPU的问题,有朋友遇到同样的问题,可以一起参考 //进程与指定cpu绑定 SetProce ...

  7. linux上限制用户进程数、cpu占用率、内存使用率

    限制进程CPU占用率的问题,给出了一个shell脚本代码如下: renice +10 `ps aux | awk '{ if ($3 > 0.8 && id -u $1 > ...

  8. LINUX内核CPU负载均衡机制【转】

    转自:http://oenhan.com/cpu-load-balance 还是神奇的进程调度问题引发的,参看Linux进程组调度机制分析,组调度机制是看清楚了,发现在重启过程中,很多内核调用栈阻塞在 ...

  9. 一个快速检测系统CPU负载的小程序

    原理说明 在对服务器进行维护时,有时也遇到由于系统 CPU(利用率)负载过高导致业务中断的情况.服务器上可能运行多个进程,查看单个进程的 CPU 都是正常的,但是整个系统的 CPU 负载可能是异常的. ...

随机推荐

  1. ruby中rsa加签解签方法

    # coding:utf-8require 'openssl'require 'base64'# rsa签名,文本内容和私钥路径def rsa_sign(data,private_key_path) ...

  2. HTML 事件属性_03

    全局事件属性 HTML 4 的新特性之一是可以使 HTML 事件触发浏览器中的行为,比方说当用户点击某个 HTML 元素时启动一段 JavaScript. 如果你想学习更多关于事件属性,请访问 Jav ...

  3. TCP/UDP的接收包方式

    UDP udp不是流式的,每次接收一个包,长度不超过(65535-28,总包长65535字节,包头28字节).所以UDP方式下不需要填写任何参数直接调用 $client->recv() 即可.注 ...

  4. iOS NSNotification的使用

    如果在一个类中想要执行另一个类中的方法可以使用通知 1.创建一个通知对象:使用notificationWithName:object: 或者 notificationWithName:object:u ...

  5. ubuntu 下rar解压工具安装方法

    1.压缩功能安装 sudo apt-get install rar卸载 sudo apt-get remove rar2.解压功能安装 sudo apt-get install unrar卸载 sud ...

  6. winform下自绘提示框风格窗体

    昨天分享了一个环形滚动条控件,今天分享一个提示框风格的窗体.代码如下: /// <summary> /// 继承自Form,但将FormBorderStyle设置为None /// < ...

  7. nodejs http 请求延时的处理方法(防止程序崩溃)

    有时候因为接口没开,或者其他原因,导致http.request 请求延时,一直耗费资源不说,还会导致程序报错崩溃,延时处理其实也是一种错误处理. 直接上代码: var APIGET = functio ...

  8. MVC 自定义IModelBinder实现json参数转Dictionary<string, string>

    IModelBinder的学习不算深入,现在用它来实现一个json转Dictionary<string, string> 一.原始json转Dictionary<string, st ...

  9. sublime ctags

    安装 ctags: 下载ctags,复制exe到系统目录或者sublime text的目录中 sublime: 安装ctags插件 使用: 快捷键 Command Key Binding Alt Bi ...

  10. ssh IP打通,hadoop启动失败

    ssh ip 无密码打通,hadoop启动失败 报错为:host'主机名' can't be established. 纠结了接近一个多小时 之后必须ssh 主机名 , yes一下,发现hadoop能 ...