循环创建定时器,是否会进行排队等待阻塞?

caption

N个群进行发消息,视频,图片,文字。视频图片文字之间有个五秒的延迟,一开始用的sleep,导致时间间隔压根不对,现在用定时器去操作,又遇到了定时器阻塞问题。

循环读取群,批量往群内去发送视频图片文字。请问这种情况用workman怎么写,如果是原生php之间用sleep去写了。但workman里面用sleep又导致了其他的业务阻塞。已经用了AsyncTcpConnection

我的业务比较复杂。

15分钟读取机器人id,根据机器人id读取他的群,循环发送这些群。
现在的写法如下:

    public function sendRobotAllGroup($wxId,$group=[]){

        foreach ($group as $k=>$v){
            if(!$v['wechatgroup_code']){
                Db::name('wechatgroup')->where('id',$v['id'])->update(['status'=>6]);
                continue;
            }
            $send = new Send();
            $send->setGroupId($v['id']);
            //获取内容
            $content = $send->index();

            if($k==0){
                $space = 1;
            }else{
                $space = $k*4;
            }
            //发送
            Timer::add($space, array($this, 'sendByWxId'), [$wxId, $v['wechatgroup_code'] ,$content], false);
      //      $this->sendByWxId($wxId,$v['wechatgroup_code'],$content);

            unset($content);
            unset($send);
        }
    }

    public function sendBysWxId($fromId,$toId,$content){
        $vedio      = $content['vedio']; //视频
        $pic_urls   = $content['pic_urls'];   //图片
        $text       = $content['content'];        //文案
        $i = 0;
        $curr = 0;  //当前位置  0 视频 1 图片 2文案
        $v_count = count($vedio);
        $p_count = count($pic_urls);
        $t_count = count($text);

        $timer_id = Timer::add(5, function()use(&$timer_id ,&$fromId, &$toId, &$vedio,&$pic_urls, &$text,&$v_count,&$p_count,&$t_count, &$i ,&$curr)
        {
            if($curr == 0){
                if($i == $v_count){
                    $i = 0;
                    $curr = 1;
                }else{
                    $this->sendVideo($fromId, $toId, $vedio[$i]);
                }
            }
            if ($curr == 1){
                if($i == $p_count){
                    $i = 0;
                    $curr = 2;
                }else{
                    $this->sendImage($fromId, $toId, $pic_urls[$i]);
                }
            }
            if ($curr == 2){
                if($i == $t_count){
                    $i = 0;
                }else{
                    $this->sendText($fromId, $toId, $text[$i]);
                }
            }
            $i++;
            if($i >= $t_count && $curr ==2){
                Timer::del($timer_id);
            }
        });

    }

现在应该是遇到定时器阻塞,循环创建的定时器,如果前面一个定时器还没有跑完,那下面的定时器是不是不会执行?都要等着他执行万,别告诉我再来一个 AsyncTcpConnection 。我已经做了客户端定时15分钟发起发送请求,然后AsyncTcpConnection到服务端来处理发送了。

sendText , sendImage ,sendVideo都是curl http接口
请大神指点下。

阅读 1247
2个回答

barley

我的本机环境和服务器都是windows,我在测试的过程中发现定时器在一个进程里应该是串行的,如果你上一个定时器里的逻辑比较复杂,后面的定时器会等它执行完再执行;我现在也在为这个事找解决方法,我的是在时间的越往后,我的执行越来越慢,得找大神问去了

  • caption 2020-03-20

    目前只能按 blogdaren 说的,把curl那些等待放到其他服务器操作去了,定时器里面curl调用远程接口,请求不等待。传递参数执行的间隔,远程服务用sleep去等待

blogdaren

1、sleep是系统调用,系统调用会导致进程挂起,所以不要用sleep.
2、单个进程内业务都是串行执行的、而且上一个定时器内的业务要是规定时间内没执行完则会等执行完了才会继续执行下一个定时器内的业务,如此反复......
3、sendText , sendImage ,sendVideo都是curl http接口 这些属于典型的繁重网络IO,我认为还是惯用的异步方案,将这些任务放到独立的进程组或机器上来异步处理;另你客户端15分钟的定时器发起请求和异步处理任务之间有什么必然关系呢?

  • 暂无评论