聊聊架构

这可能是你在使用vagrant+virtualBox过程中遇到的一个巨坑

导读:在上一篇文章中,我们介绍了《基于Window+Vagrant+VirtualBox搭建开发环境》,这或许已经给苦于搭建开发环境的同学带来了新的解决方案的选择。本文主要介绍在使用vagrant+virtualBox配套环境中,遇到的静态文件更新失败或意外出现奇怪的随机字符问题。

Image
Image
Image

上一篇文章,我们已经介绍了vagrant+virtualBox解决开发环境搭建的问题,同时,也介绍了在windows环境下可能出现的一些异常并提供了解决方案。这个配套相对成熟、轻量,而且box镜像也不区分操作系统,很容易在不同客户端移植。相比docker而言,上手简单,成了很多开发者的选择。

但可能,某一天你更新虚拟机中的文件时,意外地发现了静态文件在浏览器上显示的效果和想要的不同或者前端js文件报错,你可能会发现:

  • git pull / svn update 提示已经是最新,但在浏览器查看效果时,打开开发者工具,dom节点或js等静态内容还是更新之前的

  • js报错,通常为文件末出现一串奇怪的字符串,类似“�����”

查阅了vagrant官方文档,这是virtualBox的一个bug(有人之前提过issue,但目前window下最新的5.2.18版本仍有此问题),需要关闭nginx和httpd的sendfile。在apache官方也给出建议:

EnableSendfile指令控制是否httpd可以使用内核的sendfile支持将文件内容传输到客户端。默认情况下,当处理请求不需要访问文件中的数据时 - 例如,在传递静态文件时 - 如果操作系统支持,Apache使用sendfile传送文件内容而不读取文件。

此sendfile机制避免了单独的读取和发送操作以及缓冲区分配。但是在某些平台或某些文件系统中,最好禁用此功能以避免操作问题:

  • 某些平台可能已经破坏了构建系统未检测到的sendfile支持,特别是如果二进制文件是在另一个盒子上构建并移动到这样一台具有损坏的sendfile支持的机器上的话。

  • 在Linux上,使用sendfile时,sendfile会触发TCP校验和卸载某些网卡上的错误。

  • 在Linux on Itanium上,sendfile可能无法处理大小超过2GB的文件。

  • 对于网络安装DocumentRoot(例如,NFS或SMB),内核可能无法通过其自己的缓存来提供网络文件。

sendfile是一个比read和write更高性能的系统接口(引伸:它不但能减少上下文切换次数,还能减少数据拷贝次数。关于sendfile“零拷贝”的概念,大家可以查看下资料),在virtualBox虚拟机环境中我们需要关闭sendfile,具体操作如下:

  • nginx作为web服务器:修改nginx.conf,配置 sendfile off;

  • apache作为web服务器:修改httpd.conf,配置 EnableSendfile Off

注意下,由于nginx可以作为反向代理服务器,而sendfile是将输入fd的内容发送到输出fd,输入fd不能是socket,也就是只能是句柄。所以当nginx是一个静态文件服务器的时候,开启sendfile配置项能大大提高nginx的性能。 但是当nginx是作为一个反向代理来使用的时候,sendfile则没什么用了,因为nginx是反向代理的时候,输入fd就不是文件句柄而是socket,此时就不符合sendfile函数的参数要求了。换句话说,virtualBox中选择nginx做反向代理服务器,apache做web服务器时,遇到上文提到的静态文件出错时,直接有效解决问题的修改是关闭apache的sendfile,即:EnableSendfile Off

参考资料:

1. https://www.vagrantup.com/docs/synced-folders/virtualbox.html

2. https://github.com/hashicorp/vagrant/issues/351

3. http://httpd.apache.org/docs/2.2/mod/core.html#enablesendfile

▼
往期精彩回顾
▼
基于Window+Vagrant+VirtualBox搭建开发环境
PHPExcel导出Excel时超时超内存分析与解决方案
Image

·END·

聊聊架构

青春有限·艺无止境

Image

微信号:ArchNote
更多精彩,点击下方“阅读原文”查看。