首页 > 其他分享 >线上导出csv出现失败-网路错误

线上导出csv出现失败-网路错误

时间:2022-12-16 18:34:30浏览次数:38  
标签:php 网路 buffers header 导出 nginx 线上 csv fastcgi

一次,在线上后台导出了比平时多几倍的数据,发现导出了部分之后停止了,出现失败-网络错误的提示:

导出的核心代码是这样的

set_time_limit(0);
    ini_set('memory_limit', '256M');
    
    header("Content-type:text/csv;charset=UTF-8");
    header('Content-Encoding: UTF-8');
    header('Content-Disposition: attachment;filename=' . $fileName . '.csv');
    header('Cache-Control:must-revalidate,post-check=0,pre-check=0');
    header('Expires:0');
    header('Pragma:public');

    // 打开php标准输出流
    $fp = fopen('php://output', 'a');

    // 添加BOM头,以UTF8编码导出CSV文件,如果文件头未添加BOM头,打开会出现乱码。
    fwrite($fp, chr(0xEF).chr(0xBB).chr(0xBF));
    // 添加导出标题
    fputcsv($fp, $titleFields);

    // 导出内容
    $curl = app('curl');
    $params['page'] = 1;
    $params['limit'] = 1000;

    do {
        $result = $curl->get($uri, $params);
        $params['page']++;

        if (empty($result['data']['list'])) {
            break;
        }

        foreach ($result['data']['list'] as $item) {
            fputcsv($fp, $item);
        }

        // 每获取一页数据就输出到浏览器中
        ob_flush();
        flush();
    } while (!empty($result['data']['list']));
    exit(0);

刚开始怀疑是不是内存溢出导致的,那就去查看php的错误日志,但并没有发现Fatal error: Allowed memory size of xx bytes exhausted...之类的报错。

接着查看业务日志,有没有捕获到异常,也没有发现!

这个时候只能静下来梳理下这个过程:

导出请求 -> 服务器 -> nginx -> php -> 导出文件

其中nginx通过fastcgi协议和php进行通信,php通过php-fpm进程处理nginx的请求。

查看nginx的访问日志,发现了导出请求,请求参数也正常。

接着查看nginx的错误日志,发现有这样的报错:

2022/12/13 10:48:50 [error] 34#34: *29 readv() failed (104: Connection reset by peer) while reading upstream...

从字面上猜测,nginx和php的通信被迫断开了,到底是nginx主动断开,还是php主动断开呢

假设是nginx主动断开,那么就需要查看相关的fastcgi的配置了:

# fastcgi_buffers表示需要用多少个多大的缓冲区缓冲fastcgi的响应
fastcgi_buffers 256 4k;
# fastcgi_buffer_size表示指定读取FastCGI应答第一部分需要多大的缓冲区
fastcgi_buffer_size 4k;
# fastcgi_busy_buffers_size默认是fastcgi_buffers两倍
fastcgi_busy_buffers_size 256k;
# 表示在写入缓存文件时使用多大的数据块,默认值也是fastcgi_buffers的两倍
fastcgi_temp_file_write_size 256k;

然后把相关参数进行调高,发现并没有效果!暂时排除nginx的问题。

接下来查看php的配置,由于是断开连接,可能是超时导致的,所以先查看:

php.ini:
max_execution_time = 30
php-fpm:
request_terminate_timeout = 5

其中,max_execution_time表示脚本执行的最大时间(这里只会统计php代码执行时间,对于sleep、数据库操作、流操作等带来的时间消耗是不包括的),request_terminate_timeout表示php-fpm进程的最大存在时间。

这两个配置都会导致超时的发生!如果max_execution_time足够大,request_terminate_timeout配置过小,可能发生php-fpm进程被杀掉,这里会记录一个php-fpm的日志;如果request_terminate_timeout足够大,max_execution_time配置过小,可能发生脚本没执行完就断开了,这里也会记录一个php错误日志。

接着把request_terminate_timeout的值调高,问题得到了解决

标签:php,网路,buffers,header,导出,nginx,线上,csv,fastcgi
From: https://www.cnblogs.com/xiaoxiaobug/p/16987986.html

相关文章