1

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

但是我们有一个问题,日志记录可能会大大降低应用程序的速度,因为连接和等待应答需要相当长的时间(速度很快,但是当您在一个请求中记录 10 多个事件时,就会出现问题)。

问题是:

有没有办法在普通的 PHP (5.3) 中向 URL 发出请求而不等待任何答案,或者只是等待 HTTP 200 标头确定?

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

4

2 回答 2

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

于 2013-04-22T00:32:56.113 回答
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();
?>

二、使用函数 apache_note 写入日志是比插入数据库更轻量级的选择。因为 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

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

于 2013-04-22T02:40:41.810 回答