29

クライアントからの要求に応答する単純なRESTサービスを作成しています。すべてPHPで。

私の懸念は、サーバーがリクエストに応答するときに、クライアント側が「ok」応答を返すのが遅すぎると、リソースを占有してしまう可能性があることです。

lib_curlを介してPOSTリクエストを送信し、応答を待たずに、POSTデータが送信された直後に終了するように設定するにはどうすればよいですか?

これも可能ですか?ありがとうございました !

4

8 に答える 8

24

HTTPで回答を受け取らずにデータを送信することはできません。HTTPは常に要求->応答になります。応答が非常に短い場合でも(テキストのない単純な200のように)、応答が必要です。そして、すべてのHTTPソケットはその応答を待ちます。

応答を気にしない場合は、リクエストを行うサーバーにプロセスを追加し、リクエストデータをサーバーにプッシュするだけです(バックグラウンドで実行されているサービス、リクエストデータベースのチェックなど)。新しいエントリが追加されるたびにリクエストを開始します)。そうすれば、リクエストを非同期で作成し、そのリクエストをスタックに追加するとすぐに終了できます。

また、meouwが言ったように、クライアントはphpで行っている通信の一部ではありません。Phpはサーバー側の言語であるため、クライアントがWebページ(phpファイル)を要求すると、サーバーはそのファイルを実行し(そして、すべての要求をphpファイルの状態で実行し)、結果をクライアントに返します。

于 2010-02-03T09:40:52.943 に答える
13

このソリューションは、ソフトウェアの最小限の受信パッケージがスクリプトを続行するためのものです。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 &");  
    }
}
?>
于 2012-06-05T10:23:49.107 に答える
11

応答を本当に気にしない場合は、おそらくexecwgetコマンドを使用するのが最善です。これは他の回答のいくつかを渡す際に言及されていますが、_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/から適応されました

于 2016-09-28T16:35:36.603 に答える
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/

于 2010-02-03T09:37:33.630 に答える
1

私はこれを試したことがありませんが CURLOPT_TIMEOUT、を非常に低い値に設定するとうまくいくかもしれません。0またはを試してください0.1

ただし、cURLとクライアントがこれでどのように動作するか、接続がすでに確立されているときに接続がアクティブにキャンセルされ、タイムアウトに達するかどうかはわかりません。試してみる必要があります。PHPスクリプトを呼び出している場合はignore_user_abort()、スクリプトがどちらの方法でも実行されることを確認できます。

于 2010-02-03T09:30:43.130 に答える
1

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";
于 2019-10-21T18:40:42.040 に答える
0

他の人が言うように、httpリクエストを行うときは、応答を待つ必要があります。

PHPでできることは、exec関数を使用してリクエストを行うことです。

次のリンクを確認してください:結果を待たないためのphp execコマンド(または同様のもの)

于 2014-07-17T10:53:06.760 に答える
0

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

私は常に応答を知る必要がないので、これは私にとってはうまくいきます。

于 2021-06-04T16:40:47.517 に答える