48

PHPからHTTPGETリクエストを送信したい。例:

http://tracker.example.com?product_number=5230&price=123.52

アイデアは、サーバー側のWeb分析を行うことです。JavaScriptからサーバーに追跡情報を送信する代わりに、サーバーは追跡情報を別のサーバーに直接送信します。

要件:

  • PHPページの処理を著しく遅らせないように、リクエストにはできるだけ時間がかからないようにする必要があります。

  • からの応答をtracker.example.com確認する必要はありません。例として、以下からのいくつかの可能な応答 tracker.example.com

    • 200:それで問題ありませんが、確認する必要はありません。

    • 404:運が悪いですが、-もう一度-それをチェックする必要はありません。

    • 301:リダイレクトは適切ですが、PHPページの処理が遅れるので、そうしないでください。

    つまり、すべての応答を破棄できます。

ソリューションのアイデア:

  • 現在削除されている回答では、誰かが シェルプロセスでPHPからコマンドラインcurlを呼び出すことを提案しました。これは良い考えのように思えますが、高負荷の下で多くのシェルプロセスをフォークすることが賢明なことかどうかはわかりません。

  • PHPからサーバーサイドのGoogleAnalyticsを実行するためのパッケージであるphp-gaを見つけました。プロジェクトのページには、「[...]非ブロッキング要求を使用するように構成できます」と記載されています。 これまでのところ、php-gaが内部でどのメソッドを使用しているかを調査する時間はありませんが、このメソッドがそれである可能性があります。

一言で言えば:PHPから一般的なサーバー側の追跡/分析を行うための最良のソリューションは何ですか。

4

10 に答える 10

35

残念ながら、PHPは定義上ブロックしています。これは、通常処理する関数と操作の大部分に当てはまりますが、現在のシナリオは異なります。

私がHTTP-Pingと呼ぶのが好きなプロセスでは、特定のURIに触れるだけで、特定のサーバーにその内部ロジックをブートストラップさせる必要があります。一部の関数では、応答を待たずに、このHTTP-pingと非常によく似たものを実現できます。

URLにpingを実行するプロセスは、2段階のプロセスであることに注意してください。

  1. DNSを解決する
  2. リクエストする

DNSが解決されて接続が確立されると、要求の作成はかなり高速になりますが、DNSの解決を高速化する方法は多くありません。

http-pingを実行するいくつかの方法は次のとおりです。

  1. cURL、CONNECTION_TIMEOUTを低い値に設定する
  2. 書き込み直後に閉じることでfsockopen
  3. stream_socket_client(fsockopenと同じ)および追加STREAM_CLIENT_ASYNC_CONNECT

DNSが解決されている間、cURLとは両方ともブロックしています。最悪のシナリオでも、fsockopenfsockopenの方が大幅に高速であることに気づきました。

stream_socket_client一方、DNS解決に関する問題は修正され、このシナリオでは最適なソリューションになるはずですが、私はそれを機能させることができませんでした。

最後の解決策の1つは、これを行う別のスレッド/プロセスを開始することです。これをシステムコールすることは機能するはずですが、現在のプロセスをフォークすることもそれを行うはずです。残念ながら、PHPが実行されている環境を制御できないアプリケーションでは、どちらも実際には安全ではありません。

システムコールはほとんどの場合ブロックされておらず、pcntlはデフォルトで有効になっていません。

于 2013-02-03T02:03:10.247 に答える
18

私はこのようにtracker.example.comを呼び出します:

get_headers('http://tracker.example.com?product_number=5230&price=123.52');

トラッカースクリプトでは:

ob_end_clean();
ignore_user_abort(true);
ob_start();
header("Connection: close");
header("Content-Length: " . ob_get_length());
ob_end_flush();
flush();

// from here the response has been sent. you can now wait as long as you want and do some tracking stuff 

sleep(5); //wait 5 seconds
do_some_stuff();
exit;
于 2014-02-07T16:19:40.050 に答える
12

応答を待たずにURLへの高速GETリクエストの関数を実装しました。

function fast_request($url)
{
    $parts=parse_url($url);
    $fp = fsockopen($parts['host'],isset($parts['port'])?$parts['port']:80,$errno, $errstr, 30);
    $out = "GET ".$parts['path']." HTTP/1.1\r\n";
    $out.= "Host: ".$parts['host']."\r\n";
    $out.= "Content-Length: 0"."\r\n";
    $out.= "Connection: Close\r\n\r\n";

    fwrite($fp, $out);
    fclose($fp);
}
于 2016-08-02T19:42:06.380 に答える
4

私たちはコンボを使ってfsockopenいましたが、それからそれが上がって、ある日動作を停止しました。fwriteまたはそれは一種の断続的でした。少し調べてテストした後、fopenラッパーを有効にしている場合は、100分の1秒に設定されたタイムアウトで関数を使用することになりましfile_get_contentsstream_context_create。タイムアウトパラメータは変動値を受け取ることができます(https://www.php.net/manual/en/context.http.php)。サイレントに失敗するように、try...catchブロックでラップしました。それは私たちの目的のために美しく機能します。必要に応じて、キャッチでログを記録することができます。関数がランタイムをブロックしたくない場合は、タイムアウトが重要です。

function fetchWithoutResponseURL( $url )
{

    $context = stream_context_create([
        "http" => [
            "method"=>"GET",
            "timeout" => .01
            ]
        ]
    );

    try {
        file_get_contents($url, 0, $context);
    }catch( Exception $e ){
        // Fail silently
    }
}
于 2020-07-15T16:27:36.940 に答える
3

shell_exec、およびコマンドラインcurlを使用できます。

例については、この質問を参照してください

于 2013-01-16T13:54:23.670 に答える
2

同様の問題を研究している間にここに来ました。データベース接続が便利な場合、もう1つの可能性は、リクエストの詳細をテーブルにすばやく詰め込んでから、そのテーブルを定期的にスキャンして新しいレコードを処理し、トラッキングリクエストを作成して解放する個別のcronベースのプロセスを用意することです。 WebアプリケーションがHTTPリクエスト自体を作成する必要がなくなります。

于 2013-07-04T00:25:11.137 に答える
1

バックエンドとしてwordrpessを使用している人にとっては、次のように簡単です。

wp_remote_get( $url, array(blocking=>false) );

于 2020-03-03T07:08:50.283 に答える
-1

実際には、CURL直接を使用してこれを行うことができます。

非常に短いタイムアウト(CURLOPT_TIMEOUT_MS)を使用するか、を使用して実装しましたcurl_multi_exec

注意:すべての要求が正しく行われたわけではないため、最終的にこのメソッドを終了します。カールが失敗するオプションを除外することはできませんでしたが、これは自分のサーバーが原因である可能性があります。

于 2013-01-16T15:34:09.037 に答える
-1
<?php
// Create a stream
$opts = array(
  'http'=>array(
    'method'=>"GET",
    'header'=>"Accept-language: en" 
  )
);

 $context = stream_context_create($opts);

// Open the file using the HTTP headers set above
$file = file_get_contents('http://tracker.example.com?product_number=5230&price=123.52', false, $context);
?>
于 2015-09-19T18:36:11.820 に答える
-1

URLをpingしてすべての応答を破棄するだけで、同様のことを行う必要がありました。proc_closeコマンドを使用して、proc_closeを使用してプロセスをすぐに終了できるようにしました。サーバーにlynxがインストールされていると仮定します。

<?php    
function ping($url) {
      $proc = proc_open("lynx $url",[],$pipes);
      proc_close($proc);
    }
?>
于 2018-04-08T05:11:36.340 に答える