【问题标题】:Does PHPs fopen function implement some kind of cache?PHPs fopen 函数是否实现了某种缓存?
【发布时间】:2010-10-05 10:02:15
【问题描述】:

我正在努力从网络服务器自动收集 PHP 脚本的数据。 The files in question 包含气象数据,每 10 分钟更新一次。奇怪的是,网络服务器上的“文件修改”日期没有改变。

一个简单的fopen('http://...') 命令尝试每小时获取此目录中最后一个文件的最新版本。但通常我最终会得到一个长达 4 小时的版本。这发生在 Linux 服务器上(正如我的系统管理员向我保证的那样)不使用任何类型的代理服务器。

PHP 是否实现了自己的缓存机制?或者还有什么可能干扰这里?

(我目前的解决方法是通过 exec('wget --nocache...') 获取文件。)

【问题讨论】:

    标签: php http caching fopen


    【解决方案1】:

    由于您是通过 HTTP 获取文件,我假设 PHP 将遵守服务器响应的所有缓存标头。

    避免这种情况的一种非常简单而肮脏的方法是在每个请求中附加一些随机获取参数。

    【讨论】:

    • 这确实解决了问题,但并没有真正回答问题:为什么会发生这种情况?
    • @nickf,假设是很危险的,尤其是在检查表明你错了,所以很抱歉,但一个 -1 :-( 我将在下面给出一个完整的解释作为答案
    【解决方案2】:

    与观察到的 fopen('http://...') 访问的内容的缓存有关的问题,发帖人想知道 PHP 是否实现了自己的缓存机制?其他答案包括一些猜测,但肯定最简单的找出方法是通过查看源代码进行检查,或者更容易检测系统调用以查看发生了什么?这在 Debian 系统上很简单,如下所示:

    $ echo "Hello World" > /var/www/xx.txt
    $ strace -tt -o /tmp/strace  \
    > php -r 'echo file_get_contents("http://localhost/xx.txt");'
    Hello World
    

    我在下面包含了 strace 日志的相关摘录,但这表明 PHP RTS 只是连接到 localhost:80,发送一个“GET /xx.txt”,得到一个包含标题和文件内容的响应,然后它会回显到 STDOUT。

    在 PHP RTS 中绝对不会发生客户端缓存,因为这是直接进行 HTTP 套接字对话,所以很难想象缓存会发生在客户端的什么位置。我们留下了服务器端或中间代理缓存的可能性。 (注意,我默认为 txt 文件的 Access + 7 天过期)。

    日志文件提取

    00:15:41.887904 socket(PF_INET6, SOCK_STREAM, IPPROTO_IP) = 3
    00:15:41.888029 fcntl(3, F_GETFL)       = 0x2 (flags O_RDWR)
    00:15:41.888148 fcntl(3, F_SETFL, O_RDWR|O_NONBLOCK) = 0
    00:15:41.888265 connect(3, {sa_family=AF_INET6, sin6_port=htons(80), inet_pton(AF_INET6, "::1", &sin6_addr), sin6_flowinfo=0, sin6_scope_id=0}, 28) = -1 EINPROGRESS (Operation now in progress)
    00:15:41.888487 poll([{fd=3, events=POLLIN|POLLOUT|POLLERR|POLLHUP}], 1, 60000) = 1 ([{fd=3, revents=POLLOUT}])
    00:15:41.888651 getsockopt(3, SOL_SOCKET, SO_ERROR, [0], [4]) = 0
    00:15:41.888838 fcntl(3, F_SETFL, O_RDWR) = 0
    00:15:41.888975 sendto(3, "GET /xx.txt HTTP/1.0\r\n", 22, MSG_DONTWAIT, NULL, 0) = 22
    00:15:41.889172 sendto(3, "Host: localhost\r\n", 17, MSG_DONTWAIT, NULL, 0) = 17
    00:15:41.889307 sendto(3, "\r\n", 2, MSG_DONTWAIT, NULL, 0) = 2
    00:15:41.889437 poll([{fd=3, events=POLLIN|POLLPRI|POLLERR|POLLHUP}], 1, 0) = 0 (Timeout)
    00:15:41.889544 poll([{fd=3, events=POLLIN|POLLERR|POLLHUP}], 1, 60000) = 1 ([{fd=3, revents=POLLIN}])
    00:15:41.891066 recvfrom(3, "HTTP/1.1 200 OK\r\nDate: Wed, 15 F"..., 8192, MSG_DONTWAIT, NULL, NULL) = 285
    00:15:41.891235 poll([{fd=3, events=POLLIN|POLLERR|POLLHUP}], 1, 60000) = 1 ([{fd=3, revents=POLLIN}])
    00:15:41.908909 recvfrom(3, "", 8192, MSG_DONTWAIT, NULL, NULL) = 0
    00:15:41.909016 poll([{fd=3, events=POLLIN|POLLERR|POLLHUP}], 1, 60000) = 1 ([{fd=3, revents=POLLIN}])
    00:15:41.909108 recvfrom(3, "", 8192, MSG_DONTWAIT, NULL, NULL) = 0
    00:15:41.909198 close(3)                = 0
    00:15:41.909323 write(1, "Hello World\n", 12) = 12
    00:15:41.909532 munmap(0x7ff3866c9000, 528384) = 0
    00:15:41.909600 close(2)                = 0
    00:15:41.909648 close(1)                = 0
    

    【讨论】:

      【解决方案3】:

      因此,如果我的理解正确,部分问题可能是 *.dat 文件的时间戳始终为 1:00 AM?您是否可以控制包含数据的服务器 (http://www.iac.ethz.ch/php/chn_meteo_roof/)?如果是这样,您应该尝试找出为什么数据总是具有相同的时间戳。我必须相信它是故意设置的——操作系统将在文件被修改时更新时间戳,除非你不遗余力地让它不这样做。如果您无法弄清楚为什么将其设置为凌晨 1 点,您至少可以对文件执行“触摸”命令,这将更新其修改后的时间戳。

      这就是全部,当然,假设您对提供文件的服务器有一定的访问权限。

      【讨论】:

      • 不,我无法控制那里。
      【解决方案4】:

      为什么不尝试使用curl,我认为这是更合适的用法。

      【讨论】:

      • curl 也有同样的问题。和 wget 一样,除非我使用 --no-cache 参数。
      • 是的,但是您可以为此设置一个 curl 选项,并拥有比运行 exec 更好的代码流。问候。
      【解决方案5】:

      也许这可以解决您的问题(据我所知,无法缓存 POST 请求)

      $opts = array('http' =>
        array(
          'method'  => 'POST',
          'content'=>''
        )
      );
      $context  = stream_context_create($opts);
      $resource = fopen ('http://example.com/your-ulr', 'r', false, $context);
      
      /* or you can use file_get_contents to retrieve all the file 
         $fileContent = file_get_contents('http://example.com/your-ulr', false, $context);
      */
      

      【讨论】:

        猜你喜欢
        • 2016-12-11
        • 1970-01-01
        • 1970-01-01
        • 2018-06-02
        • 1970-01-01
        • 2018-10-12
        • 2011-07-22
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多