我正在编写一个简单的 REST 服务,它响应客户端的请求。全部用 PHP 编写。
我担心的是,当我的服务器响应请求时,如果客户端发送回“ok”响应的速度太慢,它最终可能会占用资源。
如何通过 lib_curl 发送 POST 请求,将其设置为不等待任何响应,而是在发送 POST 数据后立即退出?
这可能吗?谢谢!
您不能仅发送数据而未收到 HTTP 应答。 HTTP 总是请求 -> 响应。即使响应非常短(例如没有文本的简单 200),也需要响应。每个 HTTP 套接字都会等待该响应。
如果您不关心响应,您可以向发出请求的服务器添加一个进程,然后您只需将请求数据push给它(就像在后台运行的服务,检查请求数据库) ,并且每当添加新条目时总是启动请求)。这样您就可以异步发出请求,并且在将该请求添加到stack后就可以退出。
也正如 meouw 所说,客户端不是您使用 php 进行的任何通信的一部分。 Php 是一种服务器端语言,因此当客户端请求网页(php 文件)时,服务器 执行该文件(并执行所有请求 php 文件状态),然后将结果返回给客户端。
此解决方案适用于软件最小接收包来继续脚本。如果您愿意,请不要在意回复
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 脚本,也许
可以确保您的脚本以任一方式运行。
想要将 JSON 数据发送到 服务器 2,服务器 2 正在做一些繁重的工作,并在收到数据后立即终止连接,因此 服务器 1 不必等待结果。你可以这样做:
服务器 1(客户端使用 JSON 数据创建 POST 请求):使用 CURL,不要使用
file_get_contents(),因为根据我的经验,file_get_contents() 无法正确处理 Connection: close HTTP 标头,并且不会按应有的方式终止连接。
ignore_user_abort()
使用了
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;
// 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";
这对我有用,因为我不需要总是知道答案。