作怪的Buffer
俗话说:人丑多作怪。在编程界里面也有很多作怪之物,其中首推buffer.
上一次聊到了tar.gz创建导出的问题,我本以为自己把相关的文件流操作都摸清楚了。没想到当我开心地去研究ip库替换方案和同事们开会的时候,突然技术群里面爆了一句:线上导出文件失败,又是破损文件。
当时我的内心是崩溃的,因为在代码层面 我能解决的都解决了。在ob_clean掉那些混在缓冲区里面的渣滓之后,我的文件流输出应该是没问题的啊。
然后我反复确定了一件事儿,测试环境和我本地都是Ok的,这说明代码本身没问题。线上和测试用的php版本都是5.4.x(不是让人憋屈的php5.3.x),其实也就只剩下php和ngnix的配置问题了。我一方面开始查阅资料,一方面又换了一种思维去思考,是否可以用其他输出方式去做呢?
常见的读出方式有下面几种:
1.readfile()
readfile($downFileName); // 直接读文件内容到缓冲区
2.fread方式
这种方式就是典型的文件流方式去读。google的时候,看到有老外说,如果是比较大的文件,建议还是用这种方式,10240个字节一段一段读,保证文件读取完整。代码如下:
<?php $handle= fopen('somefile.txt', 'r');
while (feof($handle) == false) {
$part = fread($handle, 10240);
echo $part;
}
fclose($handle);
这样分段读,或者分段写入,都是比较安全稳妥的做法。其实对于php来说300M以上的文件才算大文件,所以我在线上无法导出完整文件不是因为读取上。
fread()其实还可以直接读完整个文件,eg:echo fread($fp, filesize($somefile));
3.file_get_contents()
这种方式是比较粗暴的,在文件不大的前提下是ok的,文件大了之后可能在读取过程中出错。
然后顺便我又get了新技能,下载好的文件和服务器上的文件可以对比md5,使用md5_file()函数对比。
总之我反复折腾代码,一无所获,我测试环境每一种写法都是ok的,一到线上就挂了。后面我查到了php.ini里面可以设置output_buffering,设置成On就是不限制。但是在线上设置后并没有什么卵用,且线上和测试环境在这个设置上是一样的,问题也不在这里。
其实不怕调试,就怕问题不好重现或者说只能在线上重现。时间很快就到了下班,女票打电话给我,我特么郁闷,本来想和她去玩命地enjoy life,结果要留下来陪pm一起debug online(公司没有运维,pm兼任了)。
各种倒腾之后,我又一次提出应该是ngnix的问题,是不是buffer设置太小,每次无法输出完整。pm表示反对,ngnix没问题。后来改用其他文件去尝试着下载,开始比较小的文件如40kb的都是ok的,一旦到了50kb,线上环境就傲娇地拒绝完整输出了。最后我明智地离开了公司,我很明确地知道不是code error,我不能一直耗在一个自己不能掌控的事儿上(线上我没权限搞)。
在我和女票欢乐地吃饭的时候,qq里面传来pm解决问题的message.
果不其然是ngnix的设置问题,buffer设置只有4k,而线下测试环境设施的是128k。
作怪的buffer,折腾之后反而能平静地对待了。
作怪的Buffer的更多相关文章
- Node.js:Buffer浅谈
Javascript在客户端对于unicode编码的数据操作支持非常友好,但是对二进制数据的处理就不尽人意.Node.js为了能够处理二进制数据或非unicode编码的数据,便设计了Buffer类,该 ...
- java.IO输入输出流:过滤流:buffer流和data流
java.io使用了适配器模式装饰模式等设计模式来解决字符流的套接和输入输出问题. 字节流只能一次处理一个字节,为了更方便的操作数据,便加入了套接流. 问题引入:缓冲流为什么比普通的文件字节流效率高? ...
- 一点公益商城开发系统模式Ring Buffer+
一个队列如果只生产不消费肯定不行的,那么如何及时消费Ring Buffer的数据呢?简单的方案就是当Ring Buffer"写满"的时候一次性将数据"消费"掉. ...
- CSharpGL(38)带初始数据创建Vertex Buffer Object的情形汇总
CSharpGL(38)带初始数据创建Vertex Buffer Object的情形汇总 开始 总的来说,OpenGL应用开发者会遇到为如下三种数据创建Vertex Buffer Object的情形: ...
- golang bytes.Buffer Reset
func t() { a := []'} buf := new(bytes.Buffer) buf.Write(a) b := buf.Bytes() fmt.Println(b) buf.Reset ...
- 使用Ring Buffer构建高性能的文件写入程序
最近常收到SOD框架的朋友报告的SOD的SQL日志功能报错:文件句柄丢失.经过分析得知,这些朋友使用SOD框架开发了访问量比较大的系统,由于忘记关闭SQL日志功能所以出现了很高频率的日志写入操作,从而 ...
- directx12中vetex buffer、index buffer和constant buffer绑定piple line的时机
类别 时机 函数 建Heap vetex buffer 在Draw函数中 ID3D12GraphicsCommandList::IASetVertexBuffer 否 index buffer 在Dr ...
- JAVA NIO Buffer
所谓的输入,输出,就是把数据移除或移入缓冲区. 硬件不能直接访问用户控件(JVM). 基于存储的硬件设备操控的是固定大小的数据块儿,用户请求的是任意大小的或非对齐的数据块儿. 虚拟内存:使用虚 ...
- Circular Buffer
From:http://bradforj287.blogspot.com/2010/11/efficient-circular-buffer-in-java.html import java.util ...
随机推荐
- 【 D3.js 入门系列 --- 9.6 】 生产的包图
我的个人博客是:www.ourd3js.com csdn博客为:blog.csdn.net/lzhlzz 转载请注明出处,谢谢. 打包图( Pack ).用于包括与被包括的关系,也表示各个对象的权重, ...
- 优秀个人免费私有云OwnCloud 8.0终于发布 - 亮眼新功能初探简介
OwnCloud是一个基于Linux的私有云开源项目,用户可以免费使用它来搭建自己的私有云来进行文件和多媒体等的分享. 本人有幸在大概一年多前因为项目需要而接触和使用到OwnCloud,但不幸的是当时 ...
- 还在等待漫长的iOS构建过程?来试试通过命令行的方式进行iOS应用快速构建和运行吧
不必多言,Xcode慢得很是众所周知的了.更甚者是,我有时发觉自己太依赖于Cocoa Touch的自动完成功能了,这可是个天使和魔鬼的结合体! 故此我开始去寻觅一个替代的流程来通过命令行来实现我需要的 ...
- 快速构建Windows 8风格应用7-页面视图概览
原文:快速构建Windows 8风格应用7-页面视图概览 本篇博文主要介绍Windows 8风格应用中包含哪些视图.Visual Studio 2012和模拟器中如何开发和调试不同的页面视图.页面视图 ...
- 快速构建Windows 8风格应用19-基础控件II
原文:快速构建Windows 8风格应用19-基础控件II 本篇博文接着上篇博文<快速构建Windows 8风格应用18-基础控件I>介绍开发Windows 8风格应用中常用控件. Sli ...
- ASP.NET MVC之单元测试
ASP.NET MVC之单元测试分分钟的事2014-07-15 13:05 by 书洞里的猫, 550 阅读, 4 评论, 收藏, 编辑 一.为什么要进行单元测试? 大部分开发者都有个习惯(包括本人在 ...
- mass种子模块之domready
总结:由于IE6/7/8不支持DOMContentLoaded事件,虽然它支持onreadystatechange事件,但是readyState=complete几乎和onload事件一样,需要等页面 ...
- c#编写的基于Socket的异步通信系统
c#编写的基于Socket的异步通信系统 SanNiuSignal是一个基于异步socket的完全免费DLL:它里面封装了Client,Server以及UDP:有了这个DLL:用户不用去关心心跳:粘包 ...
- 迁移Model元数据设置项
.NET/ASP.NETMVC 大型站点架构设计—迁移Model元数据设置项(自定义元数据提供程序) 阅读目录: 1.需求背景介绍(Model元数据设置项应该与View绑定而非ViewModel) 1 ...
- c# in deep 之委托
通俗来讲,委托就是吩咐别人去做某件事,但不知道他具体会怎么做.使用委托必须注意的一个问题是内存泄露问题:假如委托实例本身不能被回收,委托实例会阻止他的目标被作为垃圾回收.尤其是假如某“短命”的对象调用 ...