• 【PHP】如何关闭buffer实时输出内容到前端


    前言

    默认情况下,我们在PHP里使用echo等函数输出的内容,是不会马上发送给前端的,原因是有 buffer 的存在,buffer又分两处,一处是PHP本身的buffer,另一处是Nginx的buffer。只有当buffer满了之后,内容才会发送。

    但有时候我们会希望输出的内容可以马上发送给前端,例如类似ChatGPT之类的应用,回答都是一个一个字的实时输出的,给用户良好的体验。

    那么,怎么关闭 PHP 和 Nginx 的 buffer 呢?

    环境

    Nginx 1.19
    PHP 7.4

    解决方法

    一、PHP的buffer

    PHP里有两个函数可以关闭buffer缓冲,一个是ob_end_flush,一个是ob_end_clean,前者是输出缓冲区内容后关闭缓冲区,后者是销毁缓冲区内容直接关闭。

    但即使我们关闭了 PHP 的缓冲区,每次输出完内容也还是要手动 flush 的,例如:

    echo 'Hello World';
    flush();
    
    • 1
    • 2

    每次echo完都要调用一次flush函数,太麻烦了,此时我们可以使用ob_implicit_flush函数来解决这个问题。

    二、Nginx的buffer

    Nginx有两种方法关闭缓冲区,第一种是改Nginx的配置文件
    在这里插入图片描述
    加上图中红色框的配置指令就可以。

    这种改配置文件的方法影响范围会比较大,会导致所有的PHP请求都会关闭缓冲区,不太推荐。

    第二种方法是在 PHP 里输出 HTTP 响应头,只要在响应头里加上一个X-Accel-Buffering: no,Nginx看到此响应头就会放弃使用buffer缓冲。由于这种方法是通过代码来控制,所以影响范围我们可以自由操控,推荐使用。

    PHP代码示例

    function stream()
    {
        // 如果缓冲区没有开启,直接调用ob_end_clean()会报错的,要先判断缓冲区有没有开启
        // 如果ob_get_contents()不是返回false,说明有开启缓冲区(ob_start())
        $buf = ob_get_contents();
        if ($buf !== false) {
            // 输出header前,不能有任何输出内容,否则会报错,所以缓冲区里的内容要全部清空
            ob_end_clean();
        }
        ob_implicit_flush(); // 每次输出后都自动flush,这样就不需要咱们手动flush了
    
        // 输出header,让Nginx不要使用buffer
        header('X-Accel-Buffering: no');
    
        // 每隔一秒输出一个数字
        for ($i = 0; $i < 10; $i++) {
            echo "$i\n";
            sleep(1);
        }
    }
    
    stream();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    在 PowerShell 命令行中访问此页面,可以看到数字会一个一个的实时显示出来:
    在这里插入图片描述

    为什么要在命令行中访问?
    答:因为有部分前端程序也是有自己的缓冲区的,即使后端实时输出内容了,前端也不会马上显示出来,为了避免这种问题,使用命令行来访问就很适合了。

  • 相关阅读:
    驻波在物理上的应用与魅力
    设计模式(十二)行为型模式---模板方法模式
    c++ primer中文版第五版作业第三章
    从Spring中学到的--读懂继承链
    Data security.隐私保护-多方安全计算技术基础
    C语言经典例题-17
    Excel里实现 sum(case when xxx then xxx else xxx end)的用法
    文件包含漏洞
    Docker(四):Docker可视化管理工具
    C# 之 FileInfo API参考
  • 原文地址:https://blog.csdn.net/ljfrocky/article/details/133376603