クライアントからの要求に応答する単純なRESTサービスを作成しています。すべてPHPで。
私の懸念は、サーバーがリクエストに応答するときに、クライアント側が「ok」応答を返すのが遅すぎると、リソースを占有してしまう可能性があることです。
lib_curlを介してPOSTリクエストを送信し、応答を待たずに、POSTデータが送信された直後に終了するように設定するにはどうすればよいですか?
これも可能ですか?ありがとうございました !
HTTPで回答を受け取らずにデータを送信することはできません。HTTPは常に要求->応答になります。応答が非常に短い場合でも(テキストのない単純な200のように)、応答が必要です。そして、すべてのHTTPソケットはその応答を待ちます。
応答を気にしない場合は、リクエストを行うサーバーにプロセスを追加し、リクエストデータをサーバーにプッシュするだけです(バックグラウンドで実行されているサービス、リクエストデータベースのチェックなど)。新しいエントリが追加されるたびにリクエストを開始します)。そうすれば、リクエストを非同期で作成し、そのリクエストをスタックに追加するとすぐに終了できます。
また、meouwが言ったように、クライアントはphpで行っている通信の一部ではありません。Phpはサーバー側の言語であるため、クライアントがWebページ(phpファイル)を要求すると、サーバーはそのファイルを実行し(そして、すべての要求をphpファイルの状態で実行し)、結果をクライアントに返します。
このソリューションは、ソフトウェアの最小限の受信パッケージがスクリプトを続行するためのものです。execを使用してスクリプトをバックグラウンドで呼び出すよりも、応答を気にせずにexecにアクセスできるようにしたい場合。最初の受信者ファイル:
recevier.php
ignore_user_abort(true); //continue script if connetions become close by webbrowser(client) within working script
ob_end_clean(); // this 4 lines just extra sending to web about close connect it just in case
header("Connection: close\r\n"); //send to website close connect
header("Content-Encoding: none\r\n");
header("Content-Length: 1"); //
fastcgi_finish_request(); //close nginx,apache connect to php-fpm (php working but nginx or apache stop communication with php)
//continue scripting
// ...DO HERE WHAT YOU WANT ...
//check test with your mongo or mysql to sure php still keep connection with db
HTTPへのPHPリクエストによるFRONTGROUND: このソリューションはバックグラウンドよりも優れており、1ミリ秒待つだけで済みます
sender.php:
curl_setopt($curl, CURLOPT_TIMEOUT_MS, 1); //HERE MAGIC (We wait only 1ms on connection) Script waiting but (processing of send package to $curl is continue up to successful) so after 1ms we continue scripting and in background php continue already package to destiny. This is like apple on tree, we cut and go, but apple still fallow to destiny but we don't care what happened when fall down :)
curl_setopt($curl, CURLOPT_NOSIGNAL, 1); // i'dont know just it works together read manual ;)
---------解決策を完了するために次の答えを確認してください------------
バックグラウンドHTTPへのサーバーリクエストによる:これは、WindowsとUnixの両方で、PHPが終了するのを待たずにバックグラウンドで(cmdウィンドウなしで)$cmdを実行します。@source https://www.php.net/manual/en/function.exec.php
<?php
function execInBackground($cmd) {
if (substr(php_uname(), 0, 7) == "Windows"){
pclose(popen("start /B ". $cmd, "r"));
}
else {
exec($cmd . " > /dev/null &");
}
}
?>
応答を本当に気にしない場合は、おそらくexec
wgetコマンドを使用するのが最善です。これは他の回答のいくつかを渡す際に言及されていますが、_POST
これはこのアプローチ(非同期で1〜2ミリ秒かかる)を介してパッケージを送信するための非常に簡単な関数です:
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;
}
クレジット:関数は https://segment.com/blog/how-to-make-async-requests-in-php/から適応されました
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/
私はこれを試したことがありませんが CURLOPT_TIMEOUT
、を非常に低い値に設定するとうまくいくかもしれません。0
またはを試してください0.1
。
ただし、cURLとクライアントがこれでどのように動作するか、接続がすでに確立されているときに接続がアクティブにキャンセルされ、タイムアウトに達するかどうかはわかりません。試してみる必要があります。PHPスクリプトを呼び出している場合はignore_user_abort()
、スクリプトがどちらの方法でも実行されることを確認できます。
2つのPHPサーバーが相互に通信している場合、たとえばサーバー1がサーバー2にJSONデータを送信したい場合、サーバー2は重い作業を行っており、データを受信した直後に接続を終了するため、サーバー1は結果を待ちます。あなたはこのようにそれを行うことができます:
サーバー1(JSONデータを使用してPOSTリクエストを作成するクライアント):
私の経験では、file_get_contents()は接続を処理しないため、CURLを使用し、 file_get_contents()は使用しないでください。HTTPヘッダーを正しく閉じ、接続を適切に終了しません。
$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;
サーバー2:
使用されるbubba-h57からの変更されたコード。
// 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";
他の人が言うように、httpリクエストを行うときは、応答を待つ必要があります。
PHPでできることは、exec関数を使用してリクエストを行うことです。
次のリンクを確認してください:結果を待たないためのphp execコマンド(または同様のもの)
Laravelで
use Illuminate\Support\Facades\Http;
...Some Code here
$prom = Http::timeout(1)->async()->post($URL_STRING, $ARRAY_DATA)->wait();
... Some more important code here
return "Request sent"; //OR whatever you need to return
私は常に応答を知る必要がないので、これは私にとってはうまくいきます。