问题描述

昨天下午优化了物流推送的代码,快下班的时候收到了告警短信,显示消费队列堆积。遂登录zabbix观察服务器资源情况,发现cpu飙升。
file

问题处理

刚开始以为是代码原因。是否由于来源非tb,进程(循环消费3000条)在秒级的时间单位类销毁创建。600个消费者是否在不停的创建销毁,cpu肯定会飙升。观察当天日志目录,未生成因来源问题的日志。故可以排除此项。尝试屏蔽了几处直接过滤的判断,让一个进程走更长的时间,这样进程就不会不停的销毁创建了。但是多次尝试,发现还是这样?。无奈,为了脚本能正常运行,不至于消费过慢,联系运维版本回退。

再次查找

再次开始查找原因,发现cpu飙升是从16:30左右开始的。查找聊天记录,优化升级14:40就已经完成了。就算消费一条消息要0.5秒,3000条也应该在30分钟内完成。如果代码有问题,15:10分之前就应该出现问题。而不是运行这么久,更加坚信了问题不再消费者脚本。在聊天记录中发现,16:30进行了一个操作,把日志统一放到了nas中。难道是因为写日志文件引起的问题。原来有两台消费服务器,日志各自放在服务器本地。将日志统一放到nas后,两台服务器900个消费进程同时写一个文件。问题可能在文件锁

查看写日志代码

file_put_contents($logFile, $content,FILE_APPEND); #FILE_APPEND 追加写入

file

此处未加锁,但是FILE_APPEND保证文件内容不会覆盖,所有日志都追加了只是会有顺序错乱的可能性。
而LOCK_EX就是解决这个问题的(FILE_APPENF|LOCK_EX)。

问题有可能出在FILE_APPEND,模拟测试代码如下
test.php


for ($i=0;$i<30000;$i++) {
    file_put_contents('test.log',$i."\n",FILE_APPEND); 
}

test.sh

#!/bin/bash
exec_path=pwd

while true
do
    for i in {1..100}
    do
        exec_command="ps -ef | grep '$exec_path/test.php $i\$' | grep -v grep | wc -l"
        count=$(eval $exec_command)
        current_cpu=0
        let "current_cpu=i % 8"
        if [ $count -lt "1" ];then
            php $exec_path/test.php $i > /dev/null &
        fi
    done

#   sleep 1
done

file

file

极耗cpu,故由此推断是由此引起。

top 查看cpu说明

  1. load average 0.00 0.00 0.00 分别是1分钟 5分钟 15分钟的负载情况
    load average数据是每隔5秒钟检查一次活跃的进程数,然后按特定算法计算出的数值。如果这个数除以逻辑CPU的数量,结果高于5的时候就表明系统在超负荷运转了。
  2. Task 现有921个进程,运行中2,休眠919,stoped状态0,zombie状态(僵尸)0
  3. Cpu(s) cpu状态
    5.4 us — 用户空间占用CPU的百分比。
    3.1 sy — 内核空间占用CPU的百分比。
    0.0 ni — 改变过优先级的进程占用CPU的百分比
    81.5 id — 空闲CPU百分比
    9.2 wa — IO等待占用CPU的百分比
    0.0 hi — 硬中断(Hardware IRQ)占用CPU的百分比
    0.8 si — 软中断(Software Interrupts)占用CPU的百分比
  4. KiB Mem 内存状态
    24518724 total — 物理内存总量(23.4GB)
    3071660 free — 空闲内存总量(2.9GB)
    3977420 used — 使用中的内存总量(3.7GB)
    17469644 buff/cache — 缓存的内存量 (16.7GB)
  5. KiB Swap swap交换分区
    33550332 total — 交换区总量(32G)
    33362684 free — 空闲交换区总量(31.8G)
    187648 used — 使用的交换区总量(183M)
    19915268 cached — 缓冲的交换区总量(19G)
  6. 输入命令大写P以cpu排序,输入命令大写M以内存排序
  7. mac 输入命令o 再输入排序字段

file

Scroll to Top