Using fsockopen in PHP to implement asynchronous requests (code example)

藏色散人
Release: 2023-04-08 09:40:02
forward
2748 people have browsed it

Using fsockopen in PHP to implement asynchronous requests (code example)

php executes a program. It may be completed in a few milliseconds, or it may take a long time.

For example, in the event of a user placing an order, if some third-party services are called to send emails, text messages, push notifications, etc., the front end may be kept waiting.

Sometimes, we don’t care about the return results of these time-consuming scripts, as long as they are executed. At this time, you need to execute it asynchronously.

As we all know, PHP does not directly support multi-threading. We can do it in a compromised way. The main thing here is fsockopen.

Send the request through fsockopen and ignore the return result, the program can return immediately.

Sample code:

$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);
}
Copy after login

It should be noted that we need to manually spell out the header information. By opening the comment section, you can view the request return result, but this time it becomes synchronous again, because the program will wait for the return result before ending.

During the actual test, it was found that if the execution result is not ignored, the sock request will be sent successfully every time during debugging; but if the execution result is ignored, the sock request is often not sent successfully. Check the nginx log and find many requests with status code 499.

Later I found the reason:

fwrite is executed immediately after fclose, nginx will directly return 499, and will not The request is forwarded to php for processing.

When the client requests a connection through the active port, NGINX will not proxy the request to the upstream service (FastCGI PHP process). At this time, the request will be recorded as 499 in the access log.

Solution:

1) Add configuration to nginx.conf

# 忽略客户端中断
fastcgi_ignore_client_abort on;
Copy after login

2) Use usleep after fwrite The function sleeps for 20 milliseconds:

usleep(20000);
Copy after login

Later, the test found no failure.

Attached is the complete code:

<?php
/**
 * 工具类
 * */
class FsockService {
    
    public static function post($url, $param){
        $host = parse_url($url, PHP_URL_HOST);
        $port = 80;
        $errno = &#39;&#39;;
        $errstr = &#39;&#39;;
        $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 = &#39;&#39;;
            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 = &#39;&#39;;
        $errstr = &#39;&#39;;
        $timeout = 30;
        $url = $url.&#39;?&#39;.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 = &#39;&#39;;
            while (!feof($fp)) {
                $ret .= fgets($fp, 128);
            }
        }
        usleep(20000); //fwrite之后马上执行fclose,nginx会直接返回499
        fclose($fp);
    }
   
}
?>
Copy after login

For more related php knowledge, please visit php tutorial!

The above is the detailed content of Using fsockopen in PHP to implement asynchronous requests (code example). For more information, please follow other related articles on the PHP Chinese website!

Related labels:
source:cnblogs.com
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
About us Disclaimer Sitemap
php.cn:Public welfare online PHP training,Help PHP learners grow quickly!