从PHP发送HTTP请求而不等待响应?

2022-08-30 10:45:08

我想从 PHP 发送一个 HTTP GET 请求。例:

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

这个想法是进行服务器端Web分析:服务器不是将跟踪信息从JavaScript发送到服务器,而是将跟踪信息直接发送到另一台服务器。

要求:

  • 请求应尽可能少地花费时间,以免明显延迟 PHP 页面的处理。

  • 不需要检查 来自 的响应。例如,来自以下方面的一些可能响应:tracker.example.comtracker.example.com

    • 200:这很好,但不需要检查。

    • 404:运气不好,但是 - 再次 - 没有必要检查。

    • 301:虽然重定向是合适的,但它会延迟PHP页面的处理,所以不要这样做。

    简而言之:可以丢弃所有响应。

解决方案的想法:

  • 在现在删除的答案中,有人建议在shell进程中从PHP调用命令行curl。这似乎是一个好主意,只是我不知道在重负载下分叉很多shell进程是否是一件明智的事情。

  • 我找到了php-ga,一个从PHP做服务器端Google Analytics的软件包。在项目的页面上,提到了:“可以配置为[...]使用非阻塞请求。到目前为止,我还没有找到时间来调查php-ga在内部使用什么方法,但这种方法可能是它!

简而言之:从PHP进行通用服务器端跟踪/分析的最佳解决方案是什么?


答案 1

不幸的是,根据定义,PHP是阻塞的。虽然这适用于您通常要处理的大多数功能和操作,但当前的情况有所不同。

我喜欢称之为HTTP-Ping的过程,要求您只触摸特定的URI,迫使特定服务器引导它的内部逻辑。某些函数允许您通过不等待响应来实现与此HTTP-ping非常相似的功能。

请注意,ping url 的过程是一个两步过程:

  1. 解析域名解析
  2. 提出请求

虽然在解析 DNS 并建立连接后,发出请求应该相当快,但使 DNS 解析速度更快的方法并不多。

执行 http-ping 的一些方法是:

  1. cURL,通过将CONNECTION_TIMEOUT设置为较低的值
  2. 通过在编写后立即关闭来打开 fsockopen
  3. stream_socket_client(与fsockopen相同)并添加STREAM_CLIENT_ASYNC_CONNECT

虽然两者和都在解析DNS时阻塞。我注意到fsockopen明显更快,即使在最坏的情况下也是如此。cURLfsockopen

stream_socket_client另一方面,应该解决有关DNS解析的问题,并且应该是在这种情况下的最佳解决方案,但我还没有设法让它工作。

最后一个解决方案是启动另一个线程/进程来为您执行此操作。为此进行系统调用应该可以工作,但分叉当前进程也应该这样做。不幸的是,在无法控制运行PHP的环境的应用程序中,两者都不是很安全。

系统调用经常被阻止,并且默认情况下不启用 pcntl。


答案 2

我会这样称呼 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;

推荐