我希望从PHP发送HTTP GET请求。例如:
http://tracker.example.com?product_number=5230&price=123.52
我们的想法是进行服务器端网络分析:而不是发送跟踪 从JavaScript到服务器的信息,服务器发送跟踪 信息直接发送到另一台服务器。
要求:
请求应尽可能少花时间,以便不这样做 显着延迟处理PHP页面。
tracker.example.com
的回复不需要
检查。作为例子,一些可能的回应来自
tracker.example.com
:
200:没关系,但不需要检查。
404:运气不好,但是 - 再次 - 无需检查。
301:虽然重定向是合适的,但会延迟 处理PHP页面,所以不要这样做。
简而言之:所有响应都可以被丢弃。
解决方案的想法:
在一个现已删除的答案中,有人建议调用命令行 来自PHP的curl在shell进程中。这似乎是一个好主意, 只是我不知道是否分配了很多shell进程 重负荷是明智之举。
我找到了php-ga,这是一个用于服务器端Google的软件包 来自PHP的分析。在项目的页面上,它是 提到:“可以配置为[...]使用非阻塞请求。” 到目前为止,我还没有时间去研究php-ga的方法 在内部使用,但这种方法可以是它!
简而言之:做通用服务器端的最佳解决方案是什么 来自PHP的跟踪/分析。
答案 0 :(得分:29)
不幸的是,PHP的定义是阻止。虽然这适用于您通常会处理的大多数功能和操作,但当前情况不同。
我喜欢调用HTTP-Ping的过程要求您只触摸特定的URI,强制特定服务器启动它的内部逻辑。某些功能允许您通过不等待响应来实现与此 HTTP-ping 非常相似的功能。
请注意 ping 网址的过程分为两个步骤:
虽然在解析DNS并建立连接后,请求应该相当快,但DNS解析速度的方法并不多。
进行http-ping的一些方法是:
STREAM_CLIENT_ASYNC_CONNECT
虽然正在解析DNS,cURL
和fsockopen
都会阻塞。我注意到 fsockopen 明显更快,即使在最坏的情况下也是如此。
stream_socket_client
应该解决有关DNS解析的问题,并且应该是这种情况下的最佳解决方案,但我还没有设法让它工作。
最后一个解决方案是启动另一个为您执行此操作的线程/进程。为此系统调用应该有效,但forking当前进程也应该这样做。不幸的是,在无法控制运行PHP的环境的应用程序中,两者都不是很安全。
系统调用通常被阻止,默认情况下不启用pcntl。
答案 1 :(得分:13)
我会这样调用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;
答案 2 :(得分:10)
我实现了对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);
}
答案 3 :(得分:3)
您可以使用shell_exec
和命令行卷曲。
有关示例,请参阅this question
答案 4 :(得分:1)
在研究类似问题的同时来到这里。如果你有一个方便的数据库连接,另一种可能是快速将请求详细信息填充到表中,然后有一个单独的基于cron的进程,定期扫描该表以处理新记录,并发出跟踪请求,释放您的Web应用程序必须自己发出HTTP请求。
答案 5 :(得分:1)
我们使用了fsockopen
和fwrite
组合,然后有一天它停止工作。还是有点断断续续。经过一些研究和测试,并且如果您启用了fopen包装器,我最终使用了file_get_contents
和stream_context_create
函数,并将超时设置为100秒。超时参数可以接收浮点值(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
}
}
答案 6 :(得分:0)
<?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);
?>
答案 7 :(得分:0)
我需要做类似的事情,只需ping一个网址并丢弃所有回复。我使用了proc_open命令,它允许你使用proc_close立即结束进程。我假设你的服务器上安装了lynx:
<?php
function ping($url) {
$proc = proc_open("lynx $url",[],$pipes);
proc_close($proc);
}
?>
答案 8 :(得分:0)
对于那些使用wordrpess作为后端的人- 它很简单:
wp_remote_get( $url, array(blocking=>false) );
答案 9 :(得分:-1)
您实际上可以直接使用CURL
执行此操作。
我已经使用非常短暂的超时(CURLOPT_TIMEOUT_MS
)和/或使用curl_multi_exec
实现了它。
建议:最终我退出此方法,因为并非每个请求都是正确的。这可能是由我自己的服务器造成的,虽然我无法排除卷曲失败的选项。