最近接手一个连接短信的需求。这个需求本身并不难,直接按照服务商的要求请求具体的接口即可。一开始是使用传统的同步阻塞方式实现的。用户体验不好。发送短信需要等到服务提供者的接口返回内容后,再继续往下执行。因为最近在学习Swoole,Swoole中有一个“异步任务”,特别适合以下应用场景:需要执行耗时操作,主进程会被阻塞。用户无需等待返回结果。结合官网手册和Latent的基于swooleAPI的异步消息队列,最后简单封装了一个处理API的类,实现如下:服务端基于本地Tcp,监听9501端口。server=newSwoole\Server(self::HOST,self::PORT);$this->server->set(array("enable_coroutine"=>false,//关闭协程"worker_num"=>2,//开启进程数一般为cup核数的1-4倍"task_worker_num"=>2,//任务进程数'daemonize'=>true,//作为守护进程启动));//注册事件$this->server->on("connect",[$this,"onConnect"]);$this->server->on("receive",[$this,"onReceive"]);$this->server->on("close",[$this,"onClose"]);$this->server->on("任务",[$this,"onTask"]);$this->server->on("finish",[$this,"onFinish"]);//启用服务$this->server->start();}/***监听连接事件*@param$server*@param$fd*/publicfunctiononConnect($server,$fd){echo"连接成功".PHP_EOL;}/***监听客户端发送的消息*@param$server"服务器对象"*@param$fd"唯一ID"*@param$form_id*@param$data"客户端发送的数据"*/publicfunctiononReceive($server,$fd,$form_id,$data){//传递任务$server->task($data);$server->send($fd,"这是客户端发送给服务器的信息:{$data}");}/***监听异步任务事件*@param$server*@param$task_id*@param$worker_id*@param$data*@returnstring*/publicfunctiononTask($server,$task_id,$worker_id,$data){$data=json_decode($data,true);echo"开始执行异步任务".PHP_EOL;try{//开始执行任务$this->addLog(date('Y-m-dH:i:s')."开始执行任务".PHP_EOL);//通知worker(必须返回,否则不会调用onFinish)return$this->curl($data['url'],$data['data'],$data['type']);}赶上(异常$exception){//执行任务失败$this->addLog(date('Y-m-dH:i:s')."执行任务失败".PHP_EOL);}}/***监听结束事件*@param$server*@param$task_id*@param$data*/publicfunctiononFinish($server,$task_id,$data){$this->addLog(date("Y-m-dH:i:s")."异步任务执行完成".PHP_EOL);print_r("来自服务器的消息:{$data}");}/***监听关闭连接事件*@param$server*@param$fd*/publicfunctiononClose($server,$fd){echo"关闭TCP连接".PHP_EOL;}/***发起Get或Post请求*@paramstring$url请求地址*@paramarray$request_data请求参数*@paramstring$request_type请求类型*@paramarray$headers头信息*@parambool$is_ssl是ssl或者不是*@returnbool|string*/publicfunctioncurl($url='',$request_data=[],$request_type='get',$headers=[],$is_ssl=false){$curl=curl_init();//初始化//设置URLcurl_setopt($curl,CURLOPT_URL,$url);//不返回Response头信息curl_setopt($curl,CURLOPT_HEADER,0);//如果成功,只返回结果,不自动输出任何内容curl_setopt($curl,CURLOPT_RETURNTRANSFER,1);//设置请求参数curl_setopt($curl,CURLOPT_POSTFIELDS,http_build_query($request_data));//TRUE时,跟踪句柄的请求字符串curl_setopt($curl,CURLINFO_HEADER_OUT,true);//为Post类型添加如下处理if($request_type=='post'){//设置为POST方法curl_setopt($curl,CURLOPT_POST,1);//设置头部信息curl_setopt($curl,CURLOPT_HTTPHEADER,array('Content-Type:application/json','Content-Length:'.strlen(json_encode($request_data))));//设置请求参数curl_setopt($curl,CURLOPT_POSTFIELDS,json_encode($request_data));//当POST数据大于1024时强制执行curl_setopt($curl,CURLOPT_HTTPHEADER,array("Expect:"));}//判断是否绕过证书if($is_ssl){//绕过ssl验证curl_setopt($curl,CURLOPT_SSL_VERIFYPEER,false);curl_setopt($curl,CURLOPT_SSL_VERIFYHOST,false);}if(!empty($headers))curl_setopt($curl,CURLOPT_HTTPHEADER,$headers);//执行$result=curl_exec($curl);如果($result==FALSE)返回false;//关闭资源curl_close($curl);返回$结果;}/***写入日志*@param$content*/publicfunctionaddLog($content){$path=dirname(__FILE__)."/logs/";如果(!is_dir($path))mkdir($path,0777,true);$file_name=$path.date("Y_m_d")。“。日志”;如果(!file_exists($file_name)){touch($file_name);chown($file_name,"root");}$file_log=fopen($file_name,"a");fputs($file_log,$content);fclose($file_log);}}$server=newtaskServer();Client这里的client可以是cli脚本,也可以是对应controller中的特定方法,只要能连接到Swoole监听的Tcp即可connect('0.0.0.0',9501)){returnjson("连接失败。错误:{$client->errCode}\n");}$data=["url"=>"https://api.paasoo.com/json","data"=>["key"=>"key","secret"=>"secret","from"=>"sms","to"=>"mobile_phone","text"=>"test",],"type"=>"get"];$client->send(json_encode($data));返回json($client->recv());}}参考链接PHP使用Swoole基于swoole异步消息队列API实现实时异步任务队列
