我们使用REST进行日志记录 - 我们需要的信息比简单的文本日志所能提供的更多。因此,我们实现了一个REST服务,该服务接受有关事件的一些基本信息,然后从事件的源Web异步获取更多详细信息。所以它实际上是一个ping很少的附加信息。记录器机器比验证API密钥,连接到DB并写入基本信息以及指向更详细信息的指针。
我们遇到了一个问题,即日志记录可能会大大减慢应用程序的速度,因为连接和等待答案需要相当长的时间(速度很快,但是当您在一个请求中记录10个以上的事件时,这是一个问题)。
问题是:
在普通的PHP(5.3)中是否有办法对URL进行请求而 NOT 等待任何答案,或者只是等待HTTP 200标头确定?
我想我可以让日志服务器在收到请求后立即发送HTTP 200标头。但它需要做更多的工作;)
答案 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来记录你的详细数据。无需额外的时间成本。