web-dev-qa-db-ja.com

POST応答を待たずにリクエストを送信しますか?

私はクライアントからのリクエストに応答する単純なRESTサービスを書いています。すべてPHPで。

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

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

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

28
Gotys

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

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

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

18
poke

ここに:

ob_end_clean();
header("Connection: close\r\n");
header("Content-Encoding: none\r\n");
header("Content-Length: 1");
ignore_user_abort(true);

そしてカール:

 curl_setopt($curl, CURLOPT_TIMEOUT_MS, 1);
 curl_setopt($curl, CURLOPT_NOSIGNAL, 1);
13

応答を本当に気にしない場合は、おそらくwgetコマンドをexec- ingすることをお勧めします。これは他の回答の一部で渡されますが、ここに_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/ から適応されました

8
Ben D

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/

2
Tahir Akhtar

私はこれを試したことはありませんが、_CURLOPT_TIMEOUT_を非常に低い値に設定するとうまくいく場合があります。 _0_または_0.1_を試してください。

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

1
Pekka 웃

2 PHPサーバーが相互に通信している場合、例えばserver 1はJSONデータを送信したいserver 2server 2は重い作業を行っており、接続権を終了しますserver 1は結果を待つ必要がないため、データを受信した後、次のように実行できます。

サーバー1(POST JSONデータを含むリクエスト)を作成するクライアント):

CURLを使用し、file_get_contents()は使用しないでください。私の経験では、file_get_contents()Connection:closeHTTPヘッダーが正しく、必要に応じて接続を終了しません。

    $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";
1
OndrejC

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

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

このリンクを確認してください: php exec command(または類似の)結果を待たないため

0
JesusIniesta