发送 POST 请求而不等待响应?

问题描述 投票:0回答:8

我正在编写一个简单的 REST 服务,它响应客户端的请求。全部用 PHP 编写。

我担心的是,当我的服务器响应请求时,如果客户端发送回“ok”响应的速度太慢,它最终可能会占用资源。

如何通过 lib_curl 发送 POST 请求,将其设置为不等待任何响应,而是在发送 POST 数据后立即退出?

这可能吗?谢谢!

php libcurl
8个回答
25
投票

您不能仅发送数据而未收到 HTTP 应答。 HTTP 总是请求 -> 响应。即使响应非常短(例如没有文本的简单 200),也需要响应。每个 HTTP 套接字都会等待该响应。

如果您不关心响应,您可以向发出请求的服务器添加一个进程,然后您只需将请求数据push给它(就像在后台运行的服务,检查请求数据库) ,并且每当添加新条目时总是启动请求)。这样您就可以异步发出请求,并且在将该请求添加到stack后就可以退出。

也正如 meouw 所说,客户端不是您使用 php 进行的任何通信的一部分。 Php 是一种服务器端语言,因此当客户端请求网页(php 文件)时,服务器 执行该文件(并执行所有请求 php 文件状态),然后将结果返回给客户端。


14
投票

此解决方案适用于软件最小接收包来继续脚本。如果您愿意,请不要在意回复


11
投票

如果你真的不关心响应,你可能最好使用 wget 命令。在传递一些其他答案时提到了这一点,但这里有一个超级简单的函数,用于通过这种方法发送

exec
包(这是异步的,需要 1-2 毫秒):

_POST

鸣谢:函数改编自
https://segment.com/blog/how-to-make-async-requests-in-php/


2
投票
http://curl.haxx.se/mail/lib-2002-05/0090.html

libcurl 没有异步接口。 你可以自己做这件事 使用线程或使用 非阻塞“多接口” libcurl 提供。阅读多 界面在这里:

http://curl.haxx.se/libcurl/c/libcurl-multi.html

多接口的PHP示例在这里:

http://www.phpied.com/simultaneuos-http-requests-in-php-with-curl/


1
投票
function wget_request($url, $post_array, $check_ssl=true) { $cmd = "curl -X POST -H 'Content-Type: application/json'"; $cmd.= " -d '" . json_encode($post_array) . "' '" . $url . "'"; if (!$check_ssl){ $cmd.= "' --insecure"; // this can speed things up, though it's not secure } $cmd .= " > /dev/null 2>&1 &"; //just dismiss the response exec($cmd, $output, $exit); return $exit == 0; }

设置为非常低的值可能会成功。尝试

CURLOPT_TIMEOUT
0

但是,我不知道cURL和客户端会如何处理这个问题,当连接已经建立、超时时是否会主动取消连接。你必须尝试一下。如果您正在调用 PHP 脚本,也许

0.1

 可以确保您的脚本以任一方式运行。


1
投票
服务器 1

想要将 JSON 数据发送到 服务器 2服务器 2 正在做一些繁重的工作,并在收到数据后立即终止连接,因此 服务器 1 不必等待结果。你可以这样做:

服务器 1(客户端使用 JSON 数据创建 POST 请求):

使用 CURL,不要使用

file_get_contents()

,因为根据我的经验,file_get_contents() 无法正确处理 Connection: close HTTP 标头,并且不会按应有的方式终止连接。 ignore_user_abort()

服务器2:

使用了

bubba-h57

的修改代码。 $curl = curl_init('http://server2.com/'); curl_setopt($curl, CURLOPT_HEADER, false); curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); curl_setopt($curl, CURLOPT_HTTPHEADER, ["Content-type: application/json"]); curl_setopt($curl, CURLOPT_POST, true); curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode(['some data'])); $response = curl_exec($curl); $status = curl_getinfo($curl, CURLINFO_HTTP_CODE); if ($status !== 200) { exit("Failed with status {$status}, response {$response}, curl_error " . curl_error($curl) . ", curl_errno " . curl_errno($curl)); } curl_close($curl); echo $response;



1
投票

// Cause we are clever and don't want the rest of the script to be bound by a timeout. // Set to zero so no time limit is imposed from here on out. set_time_limit(0); // Client disconnect should NOT abort our script execution ignore_user_abort(true); // Clean (erase) the output buffer and turn off output buffering // in case there was anything up in there to begin with. ob_end_clean(); // Turn on output buffering, because ... we just turned it off ... // if it was on. ob_start(); echo 'I received the data, closing connection now, bye.'; // Return the length of the output buffer $size = ob_get_length(); // Send headers to tell the browser to close the connection // Remember, the headers must be called prior to any actual // input being sent via our flush(es) below. header("Connection: close"); // Hack how to turn off mod deflate in Apache (gzip compression). header("Content-Encoding: none"); header("Content-Length: {$size}"); // Set the HTTP response code http_response_code(200); // Flush (send) the output buffer and turn off output buffering ob_end_flush(); // Flush (send) the output buffer // This looks like overkill, but trust me. I know, you really don't need this // unless you do need it, in which case, you will be glad you had it! @ob_flush(); // Flush system output buffer // I know, more over kill looking stuff, but this // Flushes the system write buffers of PHP and whatever backend PHP is using // (CGI, a web server, etc). This attempts to push current output all the way // to the browser with a few caveats. flush(); // Close current session. session_write_close(); // Here, you can proceed with some heavy work. echo "This won't be sent, the connection should be already closed";

这对我有用,因为我不需要总是知道答案。


0
投票

在 PHP 中,您可以使用 exec 函数发出请求。

检查此链接:

php exec 命令(或类似命令)以不等待结果

© www.soinside.com 2019 - 2024. All rights reserved.