标签:fastdfs
随着LiveApp项目日益庞大,项目本身需要进行拆分重构,而服务架构也需要扩展优化。LiveApp项目以用户数据展示为主,而用户数据主要都是图片文件,所以在使用LVS负载均衡方案时,各负载服务器之间、各个子系统之间就存在一个文件同步问题,所以项目使用FastDFS服务来解决文件同步问题。
FastDFS介绍
要上传文件至FastDFS服务器,FastDFS的客户端--LiveApp运行的服务器的PHP要安装FastDFS扩展(fastdfs_client)。安装方法:PHP安装FastDFS扩展
对于生产环境目前已在阿里云上搭建了一台装有FastDFS+ Nginx + ngx_fastdfs_module的服务器。
1.FastDFS提供tracker(跟踪)及storage(存储)服务。
2.Nginx + ngx_fastdfs_module提供文件资源响应。
项目的生产环境、各个外网测试环境均使用这台FastDFS服务器进行文件上传。以后会再做扩展。
对于本地开发环境一般都是windows环境,无法安装PHP FastDFS扩展,只能通过安装有PHP+FastDFS的Linux服务器间接上传文件。
运维同事已经在192.168.1.39服务器上已经安装了FastDFS + Nginx + ngx_fastdfs_module + PHP + fastdfs_client。
1.FastDFS提供tracker(跟踪)及storage(存储)服务。
2.Nginx + ngx_fastdfs_module提供文件资源响应。
3.Nginx + PHP + fastdfs_clent则给我们本地开发提供间接上传服务,上传地址是http://192.168.1.39/upload.php。项目配置在文件config/fastdfs.php中的$curl_url。
clessse/upload.php
/** * 上传到本地,不使用Fdfs * @see parent::save(); */ public static function save_local(array $file, $filename = NULL, $directory = NULL, $chmod = 0644){} /** * (增加自动创建目录功能) * @see parent::save(); */ public static function save(array $file, $filename = NULL, $directory = NULL, $chmod = 0644){ @mkdir($directory, 0777, TRUE); $uploaded = parent::save($file, $filename, $directory, $chmod); if ($uploaded) { $uploaded = Fdfs::upload($uploaded); } return $uploaded; }
如果只需要零时上传到本地,使用upload::save_local()
项目原来使用的upload::save()文件上传方法,现在都会直接上传到FastDFS服务器。
FastDFS服务器搭建好后,于是项目增加了Fdfs类来上传下载文件clesses/fdfs.php。
1.上传调用upload(),程序首先检测是否已安装PHP FastDFS扩展,如果安装了则调用fdfs_upload,如果未安装则调用curl_upload。
2.下载调用download(),程序首先检测是否已安装PHP FastDFS扩展,如果安装了则调用fdfs_download,如果未安装则调用curl_download。在各自download方法里程序根据配置文件config/fastdfs.conf自动判断是本地开发环境还是外网环境,然后从相应FastDFS服务器下载图片。
clesses/fdfs.php
class Fdfs { /** * 上传文件到FastDFS * @param string $filename * @return boolean|Ambigous <boolean, mixed> */ static public function upload($filename) { if (class_exists(‘FastDFS‘)) { $fileid = self::fdfs_upload($filename); } else { $fileid = self::curl_upload($filename); } } /** * 通过CURL 接口上传到FastDFS * @param string $filename * @return Ambigous <boolean, mixed> */ static public function curl_upload($filename) {} /** * 通过FastDFS类上传文件 * @param string $filename * @return boolean */ static public function fdfs_upload($filename) {} /** * 下载文件 * @param string $filename * @return boolean|Ambigous <boolean, mixed> */ static public function download($fileid) { if (class_exists(‘FastDFS‘)) { $result= self::fdfs_download($fileid, DOCROOT.$localfile); } else { $result = self::curl_download($fileid, DOCROOT.$localfile); } } /** * fdfs下载文件 * @param string $fileid * @param string $localfile * @return boolean */ static public function fdfs_download($fileid, $localfile) {} /** * curl下载文件 * @param unknown $fileid * @param unknown $localfile * @return boolean */ static public function curl_download($fileid, $localfile) {} /** * 获取FastDFS连接 * @return FastDFS */ static public function get_fdfs_connection() {} /** * 写入fastdfs上传错误日志 * @param object $fdfs * @return boolean */ static public function error_fdfs_log(&$fdfs) {} /** * 写入curl上传错误日志 * @param string $errstr * @param number $errno * @return boolean */ static public function error_curl_log($errstr = ‘‘, $errno = 0) {}
文件上传至FastDFS后,会得到文件的文件id(file_id,文件唯一的方位路径),如group1/M00/00/00/wKjpg1QZk3-AWj1SAABPtSXMtF4011.jpg,文件id都会存入数据库。
当文件需要在页面展示时是调用方法url::site($file_id)来得到文件的相对路径,如/group1/M00/00/00/wKjpg1QZk3-AWj1SAABPtSXMtF4011.jpg,在页面展示时就如:
<img src="/group1/M00/00/00/wKjpg1QZk3-AWj1SAABPtSXMtF4011.jpg"/>
文件是存储在FastDFS服务器,而我们此时并没有为其在路径前接入如http://img.liveapp.cn的域名指向,故此时图片访问不到,我们需要对LiveApp服务器配置稍作修改来使文件能正常访问。
在Apache的配置文件httpd.conf中,开启一下模块(去掉该行前的#好)
LoadModule proxy_module modules/mod_proxy.so LoadModule proxy_ajp_module modules/mod_proxy_ajp.so LoadModule proxy_http_module modules/mod_proxy_http.so
在Apache的虚拟主机配置里增加反向代理设置:
<VirtualHost *:80> ServerName debug.liveapp.dev DocumentRoot "E:/www/liveapp_merge_test" ProxyPass /group1/ http://192.168.1.39/group1/ </VirtualHost>
在nginx的vhost配置文件中增加
rewrite ^/group1(.*) http://img.liveapp.cn/group1/$1 redirect;
1.删除了所有的对文件进行删除操作的相关代码
2.删除了所有的对文件进行复制操作的相关代码
3.删除了所有的对文件进行移动操作的相关代码
代码涉及所有的上传文件相关的地方,如场景应用初始化、上传LOGO、创作场景应用、美化二维码、图形二维码等。
无论FastDFS上传还是curl上传,遇到错误都有写入日志文件,写日志的代码如下:
Kohana::$log->add(1, ‘FastDFS Upload Error: type=fdfs, errstr=‘. $fdfs->get_last_error_info() .‘, errno=‘. $fdfs->get_last_error_no()); Kohana::$log->add(1, ‘FastDFS Upload Error: type=curl, errstr=‘. $errstr .‘, errno=‘. $errno);
日志信息会如下:
2014-09-30 12:40:31 --- CRITICAL: FastDFS Upload Error: type=curl, errstr=tracker未活动, errno=2
上传失败时刻以先看LiveApp项目日志,然后逐步判断问题。
Chrome浏览器报错:
Uncaught SecurityError: Failed to execute ‘getImageData‘ on ‘CanvasRenderingContext2D‘: The canvas has been tainted by cross-origin data.
Firefox浏览器报错:
SecurityError: The operation is insecure. ...ix:p,transitionEnd:i("TransitionEnd"),animationEnd:i("AnimationEnd")},t.fn.anima...
页面的连接是:http://www.liveapp.cn/auto/index/21
Canvas调用的图片连接是:http://www.liveapp.cn/group1/M00/02/94/wKgBJ1Q4zIGABKJCAABeF48yGDY545.jpg
而/group1/M00/02/94/wKgBJ1Q4zIGABKJCAABeF48yGDY545.jpg是存在于FastDFS服务器上,www.liveapp.cn服务器是将FastDFS图片路径rewrite到FastDFS服务器去的。
这里就产生了跨域问题,浏览器就抛出上述错误。
www.liveapp.cn不使用rewrite重写方式,使用proxy_pass方向代理方式:
location ~ ^/(group[0-9]+)/(.*) { proxy_set_header Host $host; proxy_set_header X-Real-Ip $remote_addr; proxy_set_header X-Forwarded-For $remote_addr; proxy_pass http://img.liveapp.cn/$1/$2; }
这样即可初步绕过跨域问题。
如果后期Canvas图片的路径直接使用http://img.liveapp.cn/group1/M00/02/94/wKgBJ1Q4zIGABKJCAABeF48yGDY545.jpg而不用通过www.liveapp.cn域名反向代理时,那跨域的问题还是存在。
对于FastDFS提供文件响应的nginx服务器,为请求增加跨域能力:
location ~ /group([0-9])/M00 { add_header ‘Access-Control-Allow-Origin‘ ‘liveapp.cn‘; ngx_fastdfs_module; }
对于Canvas设置跨域:
img = new Image; img.crossOrigin="";
至此就彻底解决跨域问题了。
本文出自 “smile_青春” 博客,请务必保留此出处http://smileyouth.blog.51cto.com/7273768/1579985
标签:fastdfs
原文地址:http://smileyouth.blog.51cto.com/7273768/1579985