多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
## 1.简介 FastDFS是一款开源的、分布式文件系统(Distributed File System),由淘宝开发平台部资深架构师余庆开发。 github源码:https://github.com/happyfish100/fastdfs ### 1.1适用场景 FastDFS是一个开源的分布式文件系统,她对文件进行管理,功能包括:文件存储、文件同步、文件访问(文件上传、文件下载)等,解决了大容量存储和负载均衡的问题。特别适合以文件为载体的在线服务,如相册网站、视频网站等等。 ### 1.2架构 FastDFS服务端有两个角色:跟踪器(tracker)和存储节点(storage)。跟踪器主要做调度工作,在访问上起负载均衡的作用。 FastDFS系统结构如下图所示: ![](https://box.kancloud.cn/2016-07-22_5791e8035b51e.png) 跟踪器和存储节点都可以由一台多台服务器构成。跟踪器和存储节点中的服务器均可以随时增加或下线而不会影响线上服务。其中跟踪器中的所有服务器都是对等的,可以根据服务器的压力情况随时增加或减少。 为了支持大容量,存储节点(服务器)采用了分卷(或分组)的组织方式。存储系统由一个或多个卷组成,卷与卷之间的文件是相互独立的,所有卷 的文件容量累加就是整个存储系统中的文件容量。一个卷可以由一台或多台存储服务器组成,一个卷下的存储服务器中的文件都是相同的,卷中的多台存储服务器起 到了冗余备份和负载均衡的作用。 在卷中增加服务器时,同步已有的文件由系统自动完成,同步完成后,系统自动将新增服务器切换到线上提供服务。 当存储空间不足或即将耗尽时,可以动态添加卷。只需要增加一台或多台服务器,并将它们配置为一个新的卷,这样就扩大了存储系统的容量。 FastDFS中的文件标识分为两个部分:**卷名和文件名,二者缺一不可**。 ![](https://box.kancloud.cn/2016-07-22_5791e8038bece.png) FastDFS file upload 上传文件交互过程: 1. client询问tracker上传到的storage,不需要附加参数; 2. tracker返回一台可用的storage; 3. client直接和storage通讯完成文件上传。 ![](https://box.kancloud.cn/2016-07-22_5791e8038bece.png) FastDFS file download 下载文件交互过程: 1. client询问tracker下载文件的storage,参数为文件标识(卷名和文件名); 2. tracker返回一台可用的storage; 3. client直接和storage通讯完成文件下载。 ## 2.安装 ### 2.1 安装脚本说明 Github地址: ``` wget https://github.com/hanxt/fastdfs_fastsetup/archive/master.zip ``` * common_setup.sh,通用安装脚本,主要用于安装libfastcommon,fastdfs以及与其相关的依赖. * tracker_setup.sh,tracker节点配置脚本 * storage_setup.sh,storage节点配置脚本 * startup.sh 启动脚本,tracker和storage的启动. * fastdfs-5.05 fastdfs安装包 * fastdfs-nginx-module-master 安装包 * libfastcommon-1.0.7 安装包 ### 2.2安装libfastcommon和Fastdfs * libfastcommon是FastDFS项目的通用函数库。其中的方法包括:string,logger,chain,hash,socket,ini file reader,base64 encode / decode,url encode / decode,fasttimer等。 **每一个节点都需要执行,这个安装脚本,安装过程中需要输入sudo密码** ``` common_setup.sh ``` 可以看到libfastcommon.so安装到了“/usr/lib64”目录。 脚本中执行了如下的创建软链接操作,以下文件都存在libfastcommon,就成功了: ``` ls /usr/lib64/libfastcommon.so /usr/local/lib/libfastcommon.so; ls /usr/lib64/libfastcommon.so /usr/lib/libfastcommon.so; ls /usr/lib64/libfdfsclient.so /usr/local/lib/libfdfsclient.so; ls /usr/lib64/libfdfsclient.so /usr/lib/libfdfsclient.so; ``` fastdfs安装完成后,所有可执行文件在目录“/usr/bin”下,以fdfs_开头: ``` aixin@DC-server1:~/fastdfs-5.05$ ls /usr/bin/fdfs_* /usr/bin/fdfs_append_file /usr/bin/fdfs_appender_test1 /usr/bin/fdfs_delete_file /usr/bin/fdfs_file_info /usr/bin/fdfs_storaged /usr/bin/fdfs_test1 /usr/bin/fdfs_upload_appender /usr/bin/fdfs_appender_test /usr/bin/fdfs_crc32 /usr/bin/fdfs_download_file /usr/bin/fdfs_monitor /usr/bin/fdfs_test /usr/bin/fdfs_trackerd /usr/bin/fdfs_upload_file ``` 另外可以看到,配置文件存储在目录“/etc/fdfs”下,证明安装成功! ## 2.3配置FastDFS * client.conf 客户端上传配置文件 * storage.conf 文件存储服务器配置文件 * tracker.conf 负责均衡调度服务器配置文件 * mod_fastdfs.conf fastdfs的nginx模块配置文件 在本例中,使用的是ubuntu14.04的服务器,三台.部署结构如下: |ip|负载均衡(nginx或ha)|tracker|storage+nginx| |---|---|---| |192.168.1.158|是|是|| |192.168.1.60|||是| |192.168.1.24|||是| ### 2.3.1配置及启动Tracker Server **自动配置执行脚本** ```bash tracker_setup.sh ``` 此脚本主要做了两件事 * /etc/fdfs/tracker.conf参数配置 * /etc/fdfs/client.conf参数配置 主要配置了以下参数 ``` # tracker数据存储位置 DATA_DIR=/home/aixin/data/fastdfs/tracker # storage图片http访问端口 HTTP_SERVERPORT=8987 # 客户端数据存储位置,用于测试 CLIENT_DATA_DIR=/home/aixin/data/fastdfs/client # tracker服务器的ip TRACKER_SERVER=192.168.1.158 ``` **启动Tracker Server的脚本** ``` startup.sh tracker ``` trackerd.log查看tracker的启动日志,如果看到类似 ``` aixin@DC-server1:~/data/fastdfs/tracker/logs$ more trackerd.log [2016-07-28 14:31:09] INFO - FastDFS v5.05, base_path=/home/aixin/data/fastdfs/tracker, run_by_group=, run_by_user=, connect_timeout=30s, network_timeout=60s, port=22122, bind_addr=, max_connections=256, a ccept_threads=1, work_threads=4, store_lookup=2, store_group=, store_server=0, store_path=0, reserved_storage_space=10.00%, download_server=0, allow_ip_count=-1, sync_log_buff_interval=10s, check_active_in terval=120s, thread_stack_size=64 KB, storage_ip_changed_auto_adjust=1, storage_sync_file_max_delay=86400s, storage_sync_file_max_time=300s, use_trunk_file=0, slot_min_size=256, slot_max_size=16 MB, trunk_ file_size=64 MB, trunk_create_file_advance=0, trunk_create_file_time_base=02:00, trunk_create_file_interval=86400, trunk_create_file_space_threshold=20 GB, trunk_init_check_occupying=0, trunk_init_reload_f rom_binlog=0, trunk_compress_binlog_min_interval=0, use_storage_id=0, id_type_in_filename=ip, storage_id_count=0, rotate_error_log=0, error_log_rotate_time=00:00, rotate_error_log_size=0, log_file_keep_day s=0, store_slave_file_use_link=0, use_connection_pool=0, g_connection_pool_max_idle_time=3600s [2016-07-28 14:31:09] INFO - local_host_ip_count: 5, 127.0.0.1 192.168.1.158 10.0.3.1 172.19.0.1 172.17.0.1 ``` 恭喜你,tracker server已经启动成功! ### 2.3.2配置及启动Storage Server **自动配置执行脚本** ``` storage_setup.sh ``` 此脚本中做了以下几件事情: * /etc/fdfs/storage.conf的文件参数设置 * 编译nginx + fastdfs-nginx-module * /etc/fdfs/mod_fastdfs.conf参数配置 另外,需要手工做一件事情,修改/etc/nginx/nginx.conf,修改以下部分. ``` server { listen 8987; #这里改成和http.serverport一致的 server_name localhost; #这里注释掉 # location / { # root html; # index index.html index.htm; # } location /group1/M00 { root /home/aixin/data/fastdfs/storage/data; #这里是storage的data存储路径 ngx_fastdfs_module; } error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } } ``` **启动Storage Server的脚本** ``` startup.sh storage ``` storage.log查看storage服务器启动日志,如果看到类似 ``` mkdir data path: FE ... mkdir data path: FF ... data path: /home/aixin/data/fastdfs/storage/data, mkdir sub dir done. [2016-07-30 13:33:50] INFO - file: storage_param_getter.c, line: 191, use_storage_id=0, id_type_in_filename=ip, storage_ip_changed_auto_adjust=1, store_path=0, reserved_storage_space=10.00%, use_trunk_file=0, slot_min_size=256, slot_max_size=16 MB, trunk_file_size=64 MB, trunk_create_file_advance=0, trunk_create_file_time_base=02:00, trunk_create_file_interval=86400, trunk_create_file_space_threshold=20 GB, trunk_init_check_occupying=0, trunk_init_reload_from_binlog=0, trunk_compress_binlog_min_interval=0, store_slave_file_use_link=0 [2016-07-30 13:33:50] INFO - file: storage_func.c, line: 254, tracker_client_ip: 192.168.1.60, my_server_id_str: 192.168.1.60, g_server_id_in_filename: 1006741696 [2016-07-30 13:33:51] INFO - local_host_ip_count: 4, 127.0.0.1 192.168.1.60 172.18.0.1 172.17.0.1 [2016-07-30 13:33:51] INFO - file: tracker_client_thread.c, line: 310, successfully connect to tracker server 192.168.1.158:22122, as a tracker client, my ip is 192.168.1.60 [2016-07-30 13:34:21] INFO - file: tracker_client_thread.c, line: 1235, tracker server 192.168.1.158:22122, set tracker leader: 192.168.1.158:22122 [2016-07-30 13:53:51] INFO - file: storage_sync.c, line: 2698, successfully connect to storage server 192.168.1.24:23000 [2016-07-30 13:54:21] INFO - file: storage_sync.c, line: 2698, successfully connect to storage server 192.168.1.24:23000 ``` 恭喜你,storage server已经启动成功! ## 多tracker配置 如果需要启动多个tracker,可以在下面的文件,配置tracker_server,多行 ./client.conf:tracker_server=192.168.2.26:22122 ./mod_fastdfs.conf:tracker_server=192.168.2.26:22122 ./storage.conf:tracker_server=192.168.2.26:22122 ## 3.使用命令行操作文件 FastDFS安装包中,自带了客户端程序,通过程序可以进行文件上传。在使用这个客户端程序之前,首先需要配置client.conf,然后再进行文件上传及下载。 > 前提,上传下载测试,需要在tracker节点上执行。因为在tracker_setup.sh脚本里面自动化做了client的配置. ### 3.1上传文件 ``` # fdfs_upload_file /etc/fdfs/client.conf <被上传的文件> $ fdfs_upload_file /etc/fdfs/client.conf ./nohup.out group1/M00/00/00/wKgBGFecR5uAMDDeAAAAAAAAAAA698.out ``` ### 3.2 查看fastdfs文件系统信息 ``` $ fdfs_file_info /etc/fdfs/client.conf group1/M00/00/00/wKgBGFecR5uAMDDeAAAAAAAAAAA698.out source storage id: 0 source ip address: 192.168.1.24 file create timestamp: 2016-07-30 14:22:19 file size: 0 file crc32: 0 (0x00000000) ``` ### 3.3 下载文件 ``` # fdfs_download_file /etc/fdfs/client.conf <要下载的文件> $ fdfs_download_file /etc/fdfs/client.conf group1/M00/00/00/wKgBGFecR5uAMDDeAAAAAAAAAAA698.out ``` ### 3.4 查看集群状态 ``` fdfs_monitor %FastDFS%/storage.conf ``` 通过这个命令可以看到,如果有多个tracker,会发生变化! ## 4.使用JAVAAPI ### 调用API的上传接口 通过Servlet得到InputStream、文件名称和文件长度,然后通过调用FastDFS提供的Java API把文件上传到FastDFS服务器。下段代码中的getFileBuffer可参考本博客上一篇博文。(by Poechant) ``` /** * Upload File to DFS. * @param fileBuff, file to be uploaded. * @param uploadFileName, the name of the file. * @param fileLength, the length of the file. * @return the file ID in DFS. * @throws IOException */ public String uploadFile(InputStream inStream, String uploadFileName, long fileLength) throws IOException { byte[] fileBuff = getFileBuffer(inStream, fileLength); String fileId = ""; String fileExtName = ""; if (uploadFileName.contains(".")) { fileExtName = uploadFileName.substring(uploadFileName.lastIndexOf(".") + 1); } else { logger.warn("Fail to upload file, because the format of filename is illegal."); return fileId; } //建立连接 TrackerClient tracker = new TrackerClient(); TrackerServer trackerServer = tracker.getConnection(); StorageServer storageServer = null; StorageClient1 client = new StorageClient1(trackerServer, storageServer); //设置元信息 NameValuePair[] metaList = new NameValuePair[3]; metaList[0] = new NameValuePair("fileName", uploadFileName); metaList[1] = new NameValuePair("fileExtName", fileExtName); metaList[2] = new NameValuePair("fileLength", String.valueOf(fileLength)); //上传文件 try { fileId = client.upload_file1(fileBuff, fileExtName, metaList); } catch (Exception e) { logger.warn("Upload file \"" + uploadFileName + "\"fails"); } trackerServer.close(); return fileId; } ``` ## Ngnix的安装与操作,这部分已经集成到脚本里面,只做了解即可。 在storage的节点上部署nginx相关组件,主要目的是提供http的访问服务. ``` $sudo apt-get install nginx ``` ### ubuntu安装Nginx之后的文件结构大致为: 所有的配置文件都在/etc/nginx下,并且每个虚拟主机已经安排在了/etc/nginx/sites-available下 启动程序文件在/usr/sbin/nginx 日志放在了/var/log/nginx中,分别是access.log和error.log 并已经在/etc/init.d/下创建了启动脚本nginx 默认的虚拟主机的目录设置在了/usr/share/nginx/www ### 配置Nginx反向代理(这一步通过haproxy也可以实现,通常我喜欢用haproxy来做) ``` user www-data; worker_processes 4; pid /run/nginx.pid; events { worker_connections 768; # multi_accept on; } http { ## # Basic Settings ## sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; types_hash_max_size 2048; # server_tokens off; # server_names_hash_bucket_size 64; # server_name_in_redirect off; include /etc/nginx/mime.types; default_type application/octet-stream; ## # Logging Settings ## access_log /var/log/nginx/access.log; error_log /var/log/nginx/error.log; ## # Gzip Settings ## gzip on; gzip_disable "msie6"; # gzip_vary on; # gzip_proxied any; # gzip_comp_level 6; # gzip_buffers 16 8k; # gzip_http_version 1.1; # gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript; ## # nginx-naxsi config ## # Uncomment it if you installed nginx-naxsi ## #include /etc/nginx/naxsi_core.rules; ## # nginx-passenger config ## # Uncomment it if you installed nginx-passenger ## #passenger_root /usr; #passenger_ruby /usr/bin/ruby; ## # Virtual Host Configs ## include /etc/nginx/conf.d/*.conf; include /etc/nginx/sites-enabled/*; #设置 group1 的服务器 upstream fdfs_group1 { server 192.168.1.60:8987 weight=1 max_fails=2 fail_timeout=30s; server 192.168.1.24:8987 weight=1 max_fails=2 fail_timeout=30s; } server { #设置 group1 的反向代理参数 location /group1/M00 { proxy_pass http://fdfs_group1; } } } ``` ### 测试nginx配置的正确性 ``` $ sudo nginx -t nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful ``` 如果出现如下错误,执行`sudo mkdir /var/run/nginx` ``` $ sudo nginx -t ngx_http_fastdfs_set pid=8581 nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: [emerg] open() "/var/run/nginx/nginx.pid" failed (2: No such file or directory) nginx: configuration file /etc/nginx/nginx.conf test failed ``` ### 启动Nginx ``` $sudo /etc/init.d/nginx start # 检查是否启动成功 $ sudo netstat -antp | grep nginx tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 29444/nginx tcp6 0 0 :::80 :::* LISTEN 29444/nginx ``` ### 单台机器启动多个storage http://blog.csdn.net/zglwy/article/details/52783244