nginx+fastcgi文件下载不全的问题

今天遇到了一个奇怪的问题:nginx+fastcgi+php+某论坛程序的环境下,通过论坛上传的比较大(500KB)的文件下载后体积变小了。而较小的文件(100KB)则安然无恙。

用WinHex比较,可以看到文件从中间被截断了,并且没有多出任何内容。使用经多次测试,每次下载的大小在64KB左右(小于64KB),但不相同。下载到64KB左右的时候卡住了,几秒钟之后下载进度直接跳到100%,显示下载完成。为排除伟大的墙的因素,翻 墙测试,每次下载的大小在127KB左右。

找到论坛源代码,可以看到使用的是php的readfile()进行文件输出,而在输出前已经写入了content-length header。通过HttpFox进行观察,content-length的大小是正确的文件大小。

由于64KB这个大小比较敏感,所以去代码里找了有没有循环缓存读取文件的地方,并没有发现。readfile()直接读取全部内容进行输出。

为了排查,先将服务器切换到httpd(mod_php),则恢复正常,也就是说问题很可能在nginx和fastcgi上。

检查nginx.conf,注意到这个地方:

 

  
  
  fastcgi_buffer_size 64k; fastcgi_buffers 4 64k;

 

 

它的值正好等于64K,也就是说问题可能和它有关。将其修改为16K,重启nginx服务,重新下载,这次文件的大小变成了16KB左右。

检查日志发现这么一行:

  
  
2010 / 07 / 15 02 : 11 : 40 [crit] 6064 # 0: *112 open() "/var/lib/nginx/tmp/fastcgi/1/00/0000000001" failed (13: Permission denied)

 

nginx会使用fastcgi_buffer_size指定的大小的缓冲区用于缓存fastcgi流的内容。当大小超出此大小时会继续用fastcgi_buffers指定的数量和大小申请缓冲区。如果依然超出此大小,会将多出的内容写入临时文件。

也就是说,在本情况下,nginx首先会使用一个64K的缓冲区缓冲fastcgi流的第一部分,超出后最多申请4*64K=256K的缓冲区用于缓冲。如果继续超出,则写入临时文件。

下载100KB的文件时,内存完全足够,不用写入临时文件,所以没有问题。

下载500KB的文件,64KB+64KB*4已经装不下这个文件,需要使用临时文件。

而日志中反应的就是nginx无权写入临时文件。我不清楚nginx在这里具体是如何实现的,个人猜测可能在写入失败后就放弃了后面4个缓冲区,发送完第一个缓冲区后就停止发送。如果是这样,一旦超过keep-alive的时间,服务器会断开tcp连接,浏览器认为文件下载完成。考虑header的大小,浏览器下载的文件略小于64KB。这样一来就能够解释通观察到的现象。

将目录权限问题修正后,问题解决。以后有空可以看看nginx源代码确认一下。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我知道你的问题了。针对你的问题,我可以给你一些简单的部署步骤: 1.安装nginx和PHP 在CentOS 6.8中安装nginx和PHP的方式如下: ``` sudo yum install nginx sudo yum install php-fpm ``` 2.配置nginx 在配置nginx之前,你需要备份一下默认的nginx配置文件。备份命令如下: ``` sudo cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak ``` 然后,你可以通过编辑/etc/nginx/nginx.conf文件来配置nginx。 下面是一个简单的nginx配置示例,可以将它添加到/etc/nginx/nginx.conf文件中: ``` user nginx; worker_processes auto; error_log /var/log/nginx/error.log; pid /run/nginx.pid; events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; sendfile on; keepalive_timeout 65; include /etc/nginx/conf.d/*.conf; server { listen 80; server_name localhost; root /usr/share/nginx/html; index index.php index.html index.htm; location / { try_files $uri $uri/ /index.php; } location ~ \.php$ { try_files $uri =404; fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } } } ``` 在这个示例配置中,我们将nginx的根目录设置为/usr/share/nginx/html,并且将index.php添加到默认文档列表中。同时,我们还配置了一个location块,用于处理PHP文件。 3.配置PHP 在配置PHP之前,你需要备份一下默认的php-fpm配置文件。备份命令如下: ``` sudo cp /etc/php-fpm.d/www.conf /etc/php-fpm.d/www.conf.bak ``` 然后,你可以通过编辑/etc/php-fpm.d/www.conf文件来配置PHP。 下面是一个简单的PHP配置示例,可以将它添加到/etc/php-fpm.d/www.conf文件中: ``` [www] user = nginx group = nginx listen = /var/run/php-fpm/php-fpm.sock listen.owner = nginx listen.group = nginx pm = dynamic pm.max_children = 50 pm.start_servers = 5 pm.min_spare_servers = 5 pm.max_spare_servers = 35 ``` 在这个示例配置中,我们将PHP-FPM的用户和组设置为nginx,并将PHP-FPM的监听套接字设置为/var/run/php-fpm/php-fpm.sock。 4.重启服务 完成配置后,你需要重启nginx和php-fpm服务,以使配置生效。重启命令如下: ``` sudo systemctl restart nginx sudo systemctl restart php-fpm ``` 到这里,就完成了nginx+PHP的简单部署。同时,为了进一步提升性能,你可以使用Nginx+PHP+FastCGI加速模式。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值