php는 프로그램을 실행하는데, 이 작업은 몇 밀리초 안에 완료되거나 오랜 시간이 걸릴 수 있습니다.
예를 들어 사용자가 주문을 하는 경우 일부 타사 서비스를 호출하여 이메일, 문자 메시지, 푸시 알림 등을 보내는 경우 프런트 엔드가 계속 대기할 수 있습니다.
때때로 우리는 시간이 많이 걸리는 스크립트가 실행되는 한 이러한 스크립트의 반환 결과에 신경 쓰지 않습니다. 이때 비동기적으로 실행해야 합니다.
우리 모두 알고 있듯이 PHP는 멀티스레딩을 직접 지원하지 않습니다. 우리는 타협적인 방식으로 이를 할 수 있습니다. 여기서 가장 중요한 것은 fsockopen
입니다. fsockopen
。
通过fsockopen发送请求并忽略返回结果,程序可以马上返回。
示例代码:
$fp = fsockopen("www.example.com", 80, $errno, $errstr, 30); if (!$fp) { echo "$errstr ($errno)<br />\n"; } else { $out = "GET /backend.php HTTP/1.1\r\n"; $out .= "Host: www.example.com\r\n"; $out .= "Connection: Close\r\n\r\n"; fwrite($fp, $out); /*忽略执行结果 while (!feof($fp)) { echo fgets($fp, 128); }*/ fclose($fp); }
需要注意的是我们需要手动拼出header头信息。通过打开注释部分,可以查看请求返回结果,但这时候又变成同步的了,因为程序会等待返回结果才结束。
实际测试的时候发现,不忽略执行结果,调试的时候每次都会成功发送sock请求;但忽略执行结果,经常看到没有成功发送sock请求。查看nginx日志,发现很多状态码为499的请求。
后来找到了原因:
fwrite
之后马上执行fclose
샘플 코드:
# 忽略客户端中断 fastcgi_ignore_client_abort on;
실제 테스트에서 실행 결과를 무시하지 않으면 디버깅할 때마다 sock 요청이 성공적으로 전송되지만 실행 결과를 무시하면 sock 요청이 자주 전송되는 것으로 나타났습니다. 성공적으로 전송되지 않았습니다. nginx 로그를 확인하고 상태 코드가 499인 요청을 많이 찾으세요.
나중에 이유를 찾았습니다:
fwrite
직후에 fclose
를 실행합니다. nginx 499가 직접 반환되며 요청은 처리를 위해 PHP로 전달되지 않습니다. 클라이언트가 적극적으로 연결을 요청하면 NGINX는 요청을 업스트림 서비스(FastCGI PHP 프로세스)로 프록시하지 않습니다. 이때 요청은 액세스 로그에 499로 기록됩니다. 솔루션:
#🎜🎜#usleep(20000);
<?php /** * 工具类 * */ class FsockService { public static function post($url, $param){ $host = parse_url($url, PHP_URL_HOST); $port = 80; $errno = ''; $errstr = ''; $timeout = 30; $data = http_build_query($param); // create connect $fp = fsockopen($host, $port, $errno, $errstr, $timeout); if(!$fp){ return false; } // send request $out = "POST ${url} HTTP/1.1\r\n"; $out .= "Host:${host}\r\n"; $out .= "Content-type:application/x-www-form-urlencoded\r\n"; $out .= "Content-length:".strlen($data)."\r\n"; $out .= "Connection:close\r\n\r\n"; $out .= "${data}"; fwrite($fp, $out); //忽略执行结果;否则等待返回结果 // if(APP_DEBUG === true){ if(false){ $ret = ''; while (!feof($fp)) { $ret .= fgets($fp, 128); } } usleep(20000); //fwrite之后马上执行fclose,nginx会直接返回499 fclose($fp); } public static function get($url, $param){ $host = parse_url($url, PHP_URL_HOST); $port = 80; $errno = ''; $errstr = ''; $timeout = 30; $url = $url.'?'.http_build_query($param); // create connect $fp = fsockopen($host, $port, $errno, $errstr, $timeout); if(!$fp){ return false; } // send request $out = "GET ${url} HTTP/1.1\r\n"; $out .= "Host:${host}\r\n"; $out .= "Connection:close\r\n\r\n"; fwrite($fp, $out); //忽略执行结果;否则等待返回结果 // if(APP_DEBUG === true){ if(false){ $ret = ''; while (!feof($fp)) { $ret .= fgets($fp, 128); } } usleep(20000); //fwrite之后马上执行fclose,nginx会直接返回499 fclose($fp); } } ?>
위 내용은 PHP에서 fsockopen을 사용하여 비동기 요청 구현(코드 예)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!