SendBufferToWorker fail

bijingjieshen

程序启动如下所示:

$ sudo php start.php start
Workerman start in DEBUG mode
----------------------- WORKERMAN -----------------------------
Workerman version:3.3.9          PHP version:5.3.3
------------------------ WORKERS -------------------------------
user          worker                  listen                          processes status
root          YourAppBusinessWorker   none                             1          
root          JDwuliu-YourAppGateway  json://192.168.1.105:8185        1          
root          JDwuliu-HttpGateway     http://192.168.1.105:8184        1          
root          Register                text://192.168.1.105:1242        1          
root          JDwuliu-WebGateway      websocket://192.168.1.105:8188   1          
----------------------------------------------------------------
Press Ctrl-C to quit. Start success.

在成功启动几个小时后,cpu会增长到90%多,然后日志开始报错:

2017-09-12 10:53:32 pid:72082 SendBufferToWorker fail. The connections between Gateway and BusinessWorker are not ready. See http://wiki.workerman.net/Error3 for detail,

导致JDwuliu-HttpGateway这个进程不会接收数据,但是JDwuliu-YourAppGateway和JDwuliu-WebGateway 。请问这是什么原因呢???

3372 11 0
11个回答

walkor

哪个进程占用cpu 90%?

  • 暂无评论
bijingjieshen

pid memory listening worker_name connections total_request send_fail throw_exception
16758 4.25M none YourAppBusinessWorker 4 673 0 0
16759 2.75M json://192.168.1.105:8185 JDwuliu-YourAppGateway 2 1 0 0
16760 2.75M http://192.168.1.105:8184 JDwuliu-HttpGateway 2 3 0 0
16761 2.5M text://192.168.1.105:1242 Register 4 2440 0 0
16762 2.75M websocket://192.168.1.105:8188 JDwuliu-WebGateway 3 24930 0 0

pid为16758 这个进程

  • 暂无评论
walkor

应该是你们服务器没装event扩展导致的。
在线数超过1000需要是要装event扩展的。
另外还要根据workerman手册优化linux内核。

  • 暂无评论
bijingjieshen

安装了libevent,也优化了内核参数,但是cpu还是会蹦到90%,业务代码如下(websocket协议)

//查询所有车辆id
$cars_id = $db1->select('car_id')->from('carinfo')->query();

foreach($cars_id as $car_id)
{
    $gps_data = $db1->select('gps_lon,gps_lat')->from($car_id.'_LOCATIONINFO')->orderByDESC(array('u_id'))->limit(1)->query();
    $gps_data = $car_id;
    //查询车辆类型
    $type = $db1->select('type')->from('carinfo')->where("car_id = '{$car_id}'")->query();
    $gps_data = $type;
    $ret = insert_lesson($query_data, "data", $gps_data);
}

//正在运行中
$trans_car_data = $db1->query("select count(*) from carinfo where status = '0'");

//停止
$idle_car_data = $db1->query("select count(*) from carinfo where status = '1'");

//正在运行中
$hitch_car_data = $db1->query("select count(*) from carinfo where hitch = '1'");

//车辆状态统计
$car_status = array("trans_car" => $trans_car_data,
    "hitch_car" => $hitch_car_data,
    "idle_car" => $idle_car_data);

$all_cars_data = array("resData" => array
("result" => 0,
    "msg" => "查询成功",
    "data" => $query_data,
    "status" => $car_status));

Gateway::sendToClient($client_id, json_encode($all_cars_data));

$timer_id = Timer::add(3, function()use($client_id, $db1)
{.......}

做了个定时器定时器中的内容就和上面的代码一样,目的就是每三秒发送实时车辆数据给web端。我通过explain查看了执行计划只有count(*)这个是全表扫描,而且整个表也就30行左右的数据。到底是哪占用了这么高的cpu呢?

  • 暂无评论
walkor

定时器什么时候添加的,onMessage时候添加的?
你的情况有可能是不停的添加定时器导致的。
预期是3秒运行一次,结果没处理好不停的添加定时器,每秒运行成千上万次,也会导致cpu 很高

  • 暂无评论
bijingjieshen

是在onMessage的时候添加的。是一个websocket接口,我的目的前端创建了一个websocket,然后访问过这个接口,我就每三秒回一次最新的数据给web端,不需要它再次请求,它只要接收就好了。当web页面跳转的时候,websocket就断了。目标是创建一次定时器,然后自动销毁。难道不是这样吗?

  • 暂无评论
bijingjieshen

而且我通过tcpdump抓包,确实是每三秒发送一次数据

  • 暂无评论
walkor

用命令
strace -ttp cpu高的进程pid
看下进程在干嘛吧。
一般来说都是业务代码问题

  • 暂无评论
bijingjieshen

找到问题了,按照你的方法用strace 命令跟踪了一下pid,发现即使把web端页面关了,之前加的定时器还在跑,所以做了如下修改

$_SESSION = Timer::add(2, function()use($client_id, $db1, $car_id, $redis1)

    public static function onClose($client_id) {

       if(isset($_SESSION))
       {
           Timer::del($_SESSION);
       }
}

在断开的时候把定时器给销毁了。我原以为在websocket断开的时候定时器会自动销毁,所以才导致了上面的问题,谢谢@walkor 大神

  • 暂无评论
walkor

好的,看来还是无限加定时器的问题导致

  • 暂无评论
bijingjieshen

是的是的,非常感谢!!!

  • 暂无评论
年代过于久远,无法发表回答
🔝