码迷,mamicode.com
首页 > 其他好文 > 详细

FastDFS方案应用

时间:2014-11-20 15:44:47      阅读:280      评论:0      收藏:0      [点我收藏+]

标签:fastdfs

2014年9月FastDFS方案应用[编辑]

    随着LiveApp项目日益庞大,项目本身需要进行拆分重构,而服务架构也需要扩展优化。LiveApp项目以用户数据展示为主,而用户数据主要都是图片文件,所以在使用LVS负载均衡方案时,各负载服务器之间、各个子系统之间就存在一个文件同步问题,所以项目使用FastDFS服务来解决文件同步问题。
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。

FastDFS方案对于现有项目的改动[编辑]

文件上传入口类修改[编辑]

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文件上传类[编辑]

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服务器[编辑]

在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服务器[编辑]

在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项目日志,然后逐步判断问题。

前端Canvas与FastDFS图片跨域问题[编辑]


现象[编辑]

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方案应用

标签:fastdfs

原文地址:http://smileyouth.blog.51cto.com/7273768/1579985

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!