正常情况下,PHP执行的都是同步请求,代码自上而下依次执行,但有些场景如发送邮件、执行耗时任务等操作时就不适用于同步请求,只能使用异步处理请求。
场景要求:
客户端调用服务器a.php接口,需要执行一个长达10s-20s不等的耗资源操作,假如客户端响应请求时间为5秒(请求响应超时时间),5s以上无回复即断开连接。
解决设想:
客户端调用a.php之后,a.php执行异步多线程操作调用b.php,a.php调用成功后即刻反馈给客户端回执,b.php自动执行耗资源操作。
方案:
利用fsockopen()方法解决PHP异步请求
1.封装异步请求函数asyncRequest(),代码如下:
/** ????* php异步请求 ????* @param $host string 主机地址 ????* @param $path string 路径 ????* @param $param array 请求参数 ????* @return string ????*/ ???private static function asyncRequest($host, $path, $param = array()){ ???????$query = isset($param) ? http_build_query($param) : ‘‘; ???????Bd_Log::debug($query); ???????$port = 80; ???????$errno = 0; ???????$errstr = ‘‘; ???????$timeout = 30; //连接超时时间(S) ???????$fp = @fsockopen($host, $port, $errno, $errstr, $timeout); ???????//$fp = stream_socket_client("tcp://".$host.":".$port, $errno, $errstr, $timeout); ???????if (!$fp) { ???????????Bd_Log::debug(‘连接失败‘); ???????????return ‘连接失败‘; ???????} ???????if ($errno || !$fp) { ???????????Bd_Log::debug($errstr); ???????????return $errstr; ???????} ???????stream_set_blocking($fp,0); //非阻塞 ???????stream_set_timeout($fp, 1);//响应超时时间(S) ???????$out ?= "POST " . $path . " HTTP/1.1\r\n"; ???????$out .= "host:" . $host . "\r\n"; ???????$out .= "content-length:" . strlen($query) . "\r\n"; ???????$out .= "content-type:application/x-www-form-urlencoded\r\n"; ???????$out .= "connection:close\r\n\r\n"; ???????$out .= $query; ???????$result = @fputs($fp, $out); ???????@fclose($fp); ???????return $result; ???}
实例:
正常接口a.php,如下
???/** ????* 正常接口a.php ????* @param $host string 主机地址 ????* @param $path string 路径 ????* @param $param array 请求参数 ???*/ public function a(){ ??????$param = array( ??????????‘XXX‘ => $XXX, ???????); ???????$asyncData = $this->asyncRequest( $host, $path ,$param); ???????echo‘a.php success‘ ????? }
耗时接口b.php,如下
???/** ????* 耗时接口b.php,依次输出三种结果 ???*/ ???public function b(){ ??? ? set_time_limit(0); ???????ignore_user_abort(true);//设置与客户机断开是否会终止执行 ???????fastcgi_finish_request();//提高请求的处理速度 ???????sleep(‘30‘); ???????echo "耗时30秒"; ???????sleep(‘20‘); ???????echo "耗时20秒"; ???????sleep(‘10‘); ???????echo "耗时10秒"; ???}
上述实例即为简单的测试接口部分代码,根据自己需求做修改即可;
PHP异步请求之fsockopen()方法详解
原文地址:https://www.cnblogs.com/wenzheshen/p/10213480.html