websocket开启大约几天后,fd达到9000左右,进程会挂掉

用swoole搭建了一个websocket服务器,在Linux上开机启动,在运行大约1天后,客户端建立链接请求数据明显变慢很多,杀死这个进程后,重新启动就会正常很快(tp5框架),代码如下,求解

<?php
namespace app\Console;

use think\console\Command;
use think\console\Input;
use think\console\Output;
class WebSocket extends Command
{
    protected $server;
    // 命令行配置函数
    protected $timer=array();

    protected function configure()
    {
        // setName 设置命令行名称
        // setDescription 设置命令行描述
        $this->setName('websocket:start')->setDescription('Start Web Socket Server!');
    }

    // 设置命令返回信息
    protected function execute(Input $input, Output $output)
    {
        $this->server = new \Swoole\WebSocket\Server('0.0.0.0', 9501);

        // 设置 server 运行前各项参数
        // 调试的时候把守护进程关闭,部署到生产环境时再把注释取消
        // $this->server->set([composer require topthink/think-swoole
        //     'daemonize' => true,
        // ]);
    $this->server->set(array(
            'worker_num' => 6
         ));


        // 设置回调函数
        $this->server->on('Open', [$this, 'onOpen']);
        $this->server->on('Message', [$this, 'onMessage']);
        $this->server->on('Close', [$this, 'onClose']);
        $this->server->user = [];
        $this->server->start();
    }

    public function onOpen(\Swoole\WebSocket\Server $server, \Swoole\Http\Request $request)
    {
        echo "server: handshake success with fd{$request->fd}\n";
    }

    // 收到数据时回调函数
    public function onMessage(\Swoole\WebSocket\Server $server, \Swoole\WebSocket\Frame $frame)
    {
        echo "receive from {$frame->fd}:{$frame->data},opcode:{$frame->opcode},fin:{$frame->finish}\n";
        if($frame->data){
            //首次直接返回数据
            $data=$this->getMany($frame->data);
       if($server->exist($frame->fd)){
           $server->push($frame->fd, json_encode($data));
       }
            if(array_key_exists($frame->fd,$this->timer)){
                swoole_timer_clear($this->timer[$frame->fd]);
                unset($this->timer[$frame->fd]);
            }
            //后续定时推送
            $time_id=swoole_timer_tick(1000,function() use($server,$frame) {
                //获取需要推送消息的fd列表
                if($server->exist($frame->fd)){
                    $list=$frame->data;
                    $data=$this->getMany($list);
                    $server->push($frame->fd, json_encode($data));
                }
            });
            $this->timer[$frame->fd]=$time_id;
        }else{
            $this->onClose($server,$frame->fd);
        }

    }
    // 连接关闭时回调函数
    public function onClose($server, $fd)
    {
        echo "client {$fd} closed\n";
    }

}
2018-04-17 15:26
0
1

探索者 - one框架 -- 极简的基于swoole常驻内存框架

赞同来自: swoole-鱼

是不是有9000个 swoole_timer_tick 的原因

2018-04-24 08:56
1

只饮半盏

赞同来自: swoole-鱼

不太确定,我后面考虑到可能是这个问题,在关闭链接的时候,用fd找到对应的timeid将它清除,报错了,后面就没清楚了,打开了守护进程就没事了,不知道swoole中这个定时器的清除机制是怎样的

2018-04-24 15:44
1

大苏打的苏打水

赞同来自: swoole-鱼

你的业务逻辑不对吧,这样做肯定出问题

2018-05-01 14:32
1

hanhyu - 为了生活才敲代码

赞同来自: swoole-鱼

建议你把定时器放在onWorkerStart回调中固定一个进程使用。。。

2018-05-02 11:08
1

swooler - 90  后IT男

赞同来自: swoole-鱼

swoole 学习交流的朋友可以加群一起交流 646724664加群链接

2018-09-15 14:21

要回复问题请先登录注册