如何快速提出请求而不是等待答案?

时间:2013-04-21 23:48:18

标签: php httprequest

我们使用REST进行日志记录 - 我们需要的信息比简单的文本日志所能提供的更多。因此,我们实现了一个REST服务,该服务接受有关事件的一些基本信息,然后从事件的源Web异步获取更多详细信息。所以它实际上是一个ping很少的附加信息。记录器机器比验证API密钥,连接到DB并写入基本信息以及指向更详细信息的指针。

我们遇到了一个问题,即日志记录可能会大大减慢应用程序的速度,因为连接和等待答案需要相当长的时间(速度很快,但是当您在一个请求中记录10个以上的事件时,这是一个问题)。

问题是:

在普通的PHP(5.3)中是否有办法对URL进行请求而 NOT 等待任何答案,或者只是等待HTTP 200标头确定?

我想我可以让日志服务器在收到请求后立即发送HTTP 200标头。但它需要做更多的工作;)

2 个答案:

答案 0 :(得分:2)

您想要的是一个异步请求。

解决方案可能如下所示(引用):

function curl_post_async($url, $params)
{
    foreach ($params as $key => &$val) {
      if (is_array($val)) $val = implode(',', $val);
        $post_params[] = $key.'='.urlencode($val);
    }
    $post_string = implode('&', $post_params);

    $parts=parse_url($url);

    $fp = fsockopen($parts['host'],
        isset($parts['port'])?$parts['port']:80,
        $errno, $errstr, 30);

    $out = "POST ".$parts['path']." HTTP/1.1\r\n";
    $out.= "Host: ".$parts['host']."\r\n";
    $out.= "Content-Type: application/x-www-form-urlencoded\r\n";
    $out.= "Content-Length: ".strlen($post_string)."\r\n";
    $out.= "Connection: Close\r\n\r\n";
    if (isset($post_string)) $out.= $post_string;

    fwrite($fp, $out);
    fclose($fp);
}

如果您需要更多信息,请查看:

http://petewarden.typepad.com/searchbrowser/2008/06/how-to-post-an.html

答案 1 :(得分:1)

这里有两个技巧可能有帮助。

予。 http连接关闭后继续执行。这意味着您可以在主函数完成后立即关闭连接,然后继续您的日志过程。

<?php
ignore_user_abort(true);//avoid apache to kill the php running
ob_start();//start buffer output
echo "show something to user";//do something you need -- your main function
session_write_close();//close session file on server side if needed
header("Content-Encoding: none");//send header to avoid the browser side to take content as gzip format
header("Content-Length: ".ob_get_length());//send length header
header("Connection: close");//or redirect to some url 
ob_end_flush();flush();//really send content, can't change the order:1.ob buffer to normal buffer, 2.normal buffer to output
//continue do something on server side
ob_start();
sleep(5);//the user won't wait for the 5 seconds
echo 'for log';//user can't see this
file_put_contents('/tmp/process.log', ob_get_contents());
// or call remote server like http://your.log.server/log.php?xxx=yyy&aaa=bbb
ob_end_clean();
?>

II。使用函数apache_note来编写日志是非常轻量级的选择,而不是插入到数据库中。因为Apache将在Apache运行期间打开日志文件并保留句柄。它稳定且非常快。

Apache配置:

<VirtualHost *:80>
DocumentRoot /path/to/your/web
ServerName your.domain.com
ErrorLog /path/to/your/log/error_log
    <Directory /path/to/your/web>
        AllowOverride All
        Order allow,deny
        Allow from all
    </Directory>
    SetEnvIf Request_URI "/log\.php" mylog
    LogFormat "%{mylog}n" log1
    CustomLog "|/usr/sbin/cronolog /path/to/logs/mylog/%Y%m%d/mysite.%Y%m%d%H.log" log1 env=mylog
</VirtualHost>

PHP代码:

<?php
apache_note('mylog', session_id()); //you can log any data you need, see http://www.php.net/manual/en/function.apache-note.php

然后你可以使用我和我的技巧,在连接主页关闭后调用URL http://your.log.server/log.php?xxx=yyy&aaa=bbb来记录你的详细数据。无需额外的时间成本。