FastDFS 构建分布式文件管理系统并实现Java 客户端调用图片上传
最近项目有个需求,要实现图片上传,要用到 FastDFS,正好拿自己的服务器玩一下,搭建一台上传下载的服务器。FastDFS的相关呢就不介绍了,这里主要是快速搭建,学技术,代码走一遍就会了,开搞:
参考:
https://blog.csdn.net/qq_34301871/article/details/80060235
https://zhuanlan.zhihu.com/p/110089695
1.FastDFS 安装
安装,我们首先需要准备一个环境两个库以及一个安装包。
「1.一个环境」
先来看一个环境,由于 FastDFS 采用 C 语言开发,所以在安装之前,如果没有 gcc 环境,需要先安装,安装命令如下:
yum install gcc-c++
「2.两个库」
再来看两个库,由于 FastDFS 依赖 libevent 库,安装命令如下:
yum -y install libevent
安装libfastcommon
另一个库是 libfastcommon,这是 FastDFS 官方提供的,它包含了 FastDFS 运行所需要的一些基础库。
libfastcommon 下载地址:
https://github.com/happyfish100/libfastcommon/archive/V1.0.43.tar.gz
将下载好的 libfastcommon 拷贝至 /usr/local/ 目录下,然后依次执行如下命令:
cd /usr/local tar -zxvf libfastcommon-1.0.43.tar.gz cd libfastcommon-1.0.43/ ./make.sh ./make.sh install
「3.下载并安装 Tracker」
安装FastDfs
安装文件可以从 FastDFS 的 GitHub 仓库上下载,下载地址:
https://github.com/happyfish100/fastdfs/archive/V6.06.tar.gz
下载成功后,将下载文件拷贝到 /usr/local 目录下,然后依次执行如下命令安装:
cd /usr/local tar -zxvf fastdfs-6.06.tar.gz cd fastdfs-6.06/ ./make.sh ./make.sh install
安装成功后,执行如下命令,
/etc/fdfs 目录下的配置文件 是 .sample 结尾的,并不是我们要操作的
[root@localhost muyou]# cd /etc/fdfs/ [root@localhost fdfs]# ll -rw-r--r-- 1 root root 1461 Jun 8 21:56 client.conf.sample -rw-r--r-- 1 root root 7927 Jun 8 21:56 storage.conf.sample -rw-r--r-- 1 root root 7389 Jun 8 21:56 tracker.conf.sample
我们需要把这三个实例文件服务一份,去掉sample才是我们要用到的配置文件
cp client.conf.sample client.conf
cp storage.conf.sample storage.conf
cp tracker.conf.sample tracker.conf
复制完是这样的:
· 配置tracker
接下来进入 /etc/fdfs/ 目录下进行配置:
打开 tracker.conf 文件:
vim tracker.conf
打开后找到下面4处然后修改即可
1.disabled=false #默认开启 2.port=22122 #默认端口号 3.base_path=/data/fastdfs/fastdfs_tracker #自己创建的目录 4.http.server_port=6666 #默认端口是8080
保存修改文件
启动 tracker 命令如下。
service fdfs_trackerd start
成功之后可以看见
[root@localhost fdfs]# service fdfs_trackerd start
Starting fdfs_trackerd (via systemctl): [ OK ]
进入 创建的tracker目录。发现目录多了data和log两个目录
[root@localhost fdfs]# cd /data/fastdfs/fastdfs_tracker/ [root@localhost fastdfs_tracker]# ll total 0 drwxr-xr-x 2 root root 178 Jun 16 21:19 data drwxr-xr-x 2 root root 26 Jun 13 22:01 logs
由于我是在自己的云服务器上搭建的,并不会随着自己电脑的开关机而停止掉,但如果是在虚拟机上玩的话,我们不能每次都这么启动tracker,我们需要给tracker加入开机启动
首先需要给执行权限,
chmod +x /etc/rc.d/rc.local
然后开始修改rc.local
vim /etc/rc.d/rc.local
在配置文件最后加下最后一句话即可
#!/bin/bash # THIS FILE IS ADDED FOR COMPATIBILITY PURPOSES # # It is highly advisable to create own systemd services or udev rules # to run scripts during boot instead of using this file. # # In contrast to previous versions due to parallel execution during boot # this script will NOT be run after all other services. # # Please note that you must run 'chmod +x /etc/rc.d/rc.local' to ensure # that this script will be executed during boot. touch /var/lock/subsys/local service fdfs_trackerd start
保存,然后 查看tracker端口监听情况
[root@localhost fastdfs_tracker]# netstat -unltp|grep fdfs tcp 0 0 0.0.0.0:22122 0.0.0.0:* LISTEN 2233/fdfs_trackerd 871/article/details/80060235
到此22122端口监听成功。
3.2 配置storage
为storage配置工作目录,由于storage还需要一个目录用来存储数据,所以我另外多建了一个fasdfs_storage_data
[root@localhost fastdfs]# ls
fastdfs_storage fastdfs_storage_data fastdfs_tracker
修改storage配置文件,即修改storage.conf
vim /etc/fdfs/storage.conf
找到如下几处地方修改即可
port=23000 #设置storage的端口号,默认是23000,同一个组的storage端口号必须一致 base_path=/data/fastdfs/fastdfs_storage #设置storage数据文件和日志目录 store_path0=/data/fastdfs/fastdfs_storage_data tracker_server=192.168.150.132:22122 #我CentOS7的ip地址
其实只要改3个地方就行,其他都是默认的,分别是 base_path、store_path0 以及 tracker_server ,tracker_server 模板有两个地址,我们这里只有一个,配置完成后,记得注释掉另外一个不用的。
配置完成后,执行如下命令启动 Storage:
service fdfs_storaged start
成功应该是如下
[root@localhost fdfs]# service fdfs_stroaged start
Starting fdfs_storaged (via systemctl): [ OK ]
同样设置开机启动
修改rc.local
vim /etc/rc.d/rc.local
加上下面这几行
touch /var/lock/subsys/local service fdfs_trackerd start service fdfs_storaged start
查看服务是否启动
[root@localhost fastdfs]# netstat -unltp | grep fdfs tcp 0 0 0.0.0.0:22122 0.0.0.0:* LISTEN 2233/fdfs_trackerd tcp 0 0 0.0.0.0:23000 0.0.0.0:* LISTEN 2323/fdfs_storaged
如果没有见启动成功,先看看你是服务器的端口是否开放,我就是因为云服务器的端口没有开放成功,导致storage没有启动成功,卡了我半天!
服务启动,到此fastdfs已经配置完成了。最后我们再确认一下,storage是否注册到了tracker中去。
/usr/bin/fdfs_monitor /etc/fdfs/storage.conf
成功后可以看到:
Storage 1: id = 192.168.150.132 ip_addr = 192.168.150.132 ACTIVE http domain = version = 6.06 join time = 2022-07-22 10:52:15 ACTIVE 的字样
ok,修改客户端配置文件
vim /etc/fdfs/client.conf
base_path=/data/fastdfs/fastdfs_tracker #tracker服务器文件路径 tracker_server=192.168.150.132:22122 #tracker服务器IP地址和端口号 http.tracker_server_port=6666 # tracker 服务器的 http端口号,必须和tracker的设置对应起来
接下来上传图片到服务器测试一下
/usr/bin/fdfs_upload_file /etc/fdfs/client.conf /root/测试1.png #你上传的图片路径(linux上的)
成功之后会返回图片的路径
group1/M00/00/00/wKiWhFrdeCeAC_vCAABqgowGIFg399.png
我们去刚才上传的路径查看是否上传成功~~~
cd /data/fastdfs/fastdfs_storage_data/data
[root@localhost 00]# ls 0 0D 1A 27 34 41 4E 5B 68 75 82 8F 9C A9 B6 C3 D0 DD EA F7 01 0E 1B 28 35 42 4F 5C 69 76 83 90 9D AA B7 C4 D1 DE EB F8 02 0F 1C 29 36 43 50 5D 6A 77 84 91 9E AB B8 C5 D2 DF EC F9 03 10 1D 2A 37 44 51 5E 6B 78 85 92 9F AC B9 C6 D3 E0 ED FA 04 11 1E 2B 38 45 52 5F 6C 79 86 93 A0 AD BA C7 D4 E1 EE FB 05 12 1F 2C 39 46 53 60 6D 7A 87 94 A1 AE BB C8 D5 E2 EF FC 06 13 20 2D 3A 47 54 61 6E 7B 88 95 A2 AF BC C9 D6 E3 F0 FD 07 14 21 2E 3B 48 55 62 6F 7C 89 96 A3 B0 BD CA D7 E4 F1 FE 08 15 22 2F 3C 49 56 63 70 7D 8A 97 A4 B1 BE CB D8 E5 F2 FF 09 16 23 30 3D 4A 57 64 71 7E 8B 98 A5 B2 BF CC D9 E6 F3 M00 0A 17 24 31 3E 4B 58 65 72 7F 8C 99 A6 B3 C0 CD DA E7 F4 0B 18 25 32 3F 4C 59 66 73 80 8D 9A A7 B4 C1 CE DB E8 F5 0C 19 26 33 40 4D 5A 67 74 81 8E 9B A8 B5 C2 CF DC E9 F6 [root@localhost data]# cd 00 [root@localhost 00]# ls 00 0D 1A 27 34 41 4E 5B 68 75 82 8F 9C A9 B6 C3 D0 DD EA F7 01 0E 1B 28 35 42 4F 5C 69 76 83 90 9D AA B7 C4 D1 DE EB F8 02 0F 1C 29 36 43 50 5D 6A 77 84 91 9E AB B8 C5 D2 DF EC F9 03 10 1D 2A 37 44 51 5E 6B 78 85 92 9F AC B9 C6 D3 E0 ED FA 04 11 1E 2B 38 45 52 5F 6C 79 86 93 A0 AD BA C7 D4 E1 EE FB 05 12 1F 2C 39 46 53 60 6D 7A 87 94 A1 AE BB C8 D5 E2 EF FC 06 13 20 2D 3A 47 54 61 6E 7B 88 95 A2 AF BC C9 D6 E3 F0 FD 07 14 21 2E 3B 48 55 62 6F 7C 89 96 A3 B0 BD CA D7 E4 F1 FE 08 15 22 2F 3C 49 56 63 70 7D 8A 97 A4 B1 BE CB D8 E5 F2 FF 09 16 23 30 3D 4A 57 64 71 7E 8B 98 A5 B2 BF CC D9 E6 F3 0A 17 24 31 3E 4B 58 65 72 7F 8C 99 A6 B3 C0 CD DA E7 F4 0B 18 25 32 3F 4C 59 66 73 80 8D 9A A7 B4 C1 CE DB E8 F5 0C 19 26 33 40 4D 5A 67 74 81 8E 9B A8 B5 C2 CF DC E9 F6 [root@localhost 00]# cd 00 [root@localhost 00]# ls
wKiWhFrdeCeAC_vCAABqgowGIFg399.png
果然我们找到了图片了。data下有256个1级目录,每级目录下又有256个2级子目录,总共65536个文件,新写的文件会以hash的方式被路由到其中某个子目录下,然后将文件数据直接作为一个本地文件存储到该目录中。
然后我们HTTP访问文件
http://192.168.150.132:9999/group1/M00/00/00/wKiWhFrdeCeAC_vCAABqgowGIFg399.png
我们发现,http不能直接访问到图片。这是为什么呢。
HTTP请求不能访问文件的原因
我们在使用FastDFS部署一个分布式文件系统的时候,通过FastDFS的客户端API来进行文件的上传、下载、删除等操作。同时通过FastDFS的HTTP服务器来提供HTTP服务。但是FastDFS的HTTP服务较为简单,无法提供负载均衡等高性能的服务,所以FastDFS的开发者——淘宝的架构师余庆同学,为我们提供了Nginx上使用的FastDFS模块(也可以叫FastDFS的Nginx模块)。
FastDFS通过Tracker服务器,将文件放在Storage服务器存储,但是同组之间的服务器需要复制文件,有延迟的问题.假设Tracker服务器将文件上传到了192.168.128.131,文件ID已经返回客户端,这时,后台会将这个文件复制到192.168.128.131,如果复制没有完成,客户端就用这个ID在192.168.128.131取文件,肯定会出现错误。这个fastdfs-nginx-module可以重定向连接到源服务器取文件,避免客户端由于复制延迟的问题,出现错误。
正是这样,FastDFS需要结合nginx,所以取消原来对HTTP的直接支持。
FastDFS的nginx模块安装
如果你已经安装过nginx,那你可以跳过nginx安装这一步
准备nginx安装
cd /data/nginx
在安装nginx之前要安装nginx所需的依赖lib:
yum -y install pcre pcre-devel yum -y install zlib zlib-devel yum -y install openssl openssl-devel
安装nginx并添加fastdfs-nginx-module,解压nginx,和fastdfs-nginx-module:
tar -zxvf nginx-1.12.0.tar.gz unzip fastdfs-nginx-module-1.22.tar.gz
然后进入nginx安装目录,添加fastdfs-nginx-module:
./configure --prefix=/usr/local/nginx --add-module=/usr/muyou/dev/nginx/fastdfs-nginx-module-master/src #解压后fastdfs-nginx-module所在的位置
添加f完astdfs-nginx-module: 如果没有错误信息,开始安装
make
make install
安装完后需要把fastdfs-nginx-module安装目录中src目录下的mod_fastdfs.conf拷贝到/etc/fdfs目录下:
cp /usr/muyou/dev/nginx/fastdfs-nginx-module-master/src/mod_fastdfs.conf /etc/fdfs/
对刚刚拷贝的mod_fastdfs.conf文件进行修改:
vim /etc/fdfs/mod_fastdfs.conf
base_path=/data/fastdfs/fastdfs_storage #保存日志目录 tracker_server=192.168.150.132:22122 #tracker服务器的IP地址以及端口号 url_have_group_name = true #文件 url 中是否有 group 名 store_path0=/data/fastdfs/fastdfs_storage_data #存储路径
修改nginx.conf
nginx的默认目录是/usr/local/nginx 开始 配置storage nginx
root@localhost nginx-1.12.0]# cd /usr/local/nginx
[root@localhost nginx]# ll
修改nginx.conf:
[root@localhost nginx]# cd conf/
[root@localhost conf]# ls fastcgi.conf koi-win scgi_params fastcgi.conf.default mime.types scgi_params.default fastcgi_params mime.types.default uwsgi_params fastcgi_params.default nginx.conf uwsgi_params.default koi-utf nginx.conf.default win-utf
[root@localhost conf]# vim nginx.conf
修改监听 8端口0.然后 新增本地location,在这里配置 nginx 请求转发。
启动nginx:
/usr/local/nginx/sbin/nginx
成功启动:
[root@localhost conf]# /usr/local/nginx/sbin/nginx ngx_http_fastdfs_set pid=1231
通过nginx访问图片:
ok 看到能访问成功!
「疑问:fastdfs-nginx-module 有啥用」
看了整个安装过程之后,很多小伙伴有疑问,到头来还是 nginx 本身直接找到了图片文件目录,fastdfs-nginx-module 到底有啥用?
前面我们说过,Storage 由很多组构成,每个组又是一个小的集群,在每一个组里边,数据会进行同步,但是如果数据还没同步,这个时候就有请求发来了,该怎么办?此时fastdfs-nginx-module 会帮助我们直接从源 Storage 上获取文件。
安装成功了。
Java 客户端调用
安装成功后,接下来我们就用 Java 客户端来测试一下文件上传下载。
首先我们来创建一个普通的 Maven 工程,添加如下依赖:
<dependency> <groupId>net.oschina.zcx7878</groupId> <artifactId>fastdfs-client-java</artifactId> <version>1.27.0.0</version> </dependency>
然后,在项目的 resources 目录下添加 FastDFS 的配置文件 fastdfs-client.properties,内容如下:
fastdfs.connect_timeout_in_seconds = 5 fastdfs.network_timeout_in_seconds = 30 fastdfs.charset = UTF-8 fastdfs.http_anti_steal_token = false fastdfs.http_secret_key = FastDFS1234567890 fastdfs.http_tracker_http_port = 80 fastdfs.tracker_servers = 192.168.91.128:22122 fastdfs.connection_pool.enabled = true fastdfs.connection_pool.max_count_per_entry = 500 fastdfs.connection_pool.max_idle_time = 3600 fastdfs.connection_pool.max_wait_time_in_ms = 1000
上传一张图片试试
@Test void testUpload() { try { ClientGlobal.initByProperties("fastdfs-client.properties"); TrackerClient tracker = new TrackerClient(); TrackerServer trackerServer = tracker.getConnection(); StorageServer storageServer = null; StorageClient1 client = new StorageClient1(trackerServer, storageServer); NameValuePair nvp[] = null; //上传到文件系统 String fileId = client.upload_file1("C:\\Users\\javaboy\\Pictures\\picpick\\1.png", "png", nvp); logger.info(fileId); } catch (Exception e) { e.printStackTrace(); } }
2022-07-23 17:46:03.017 INFO 6184 --- [ main] o.j.fastdfs.FastdfsApplicationTests : group1/M00/00/00/wKhbgF5aMteAWy0gAAJkI7-2yGk361.png
这里,首先加载配置文件,然后构造一个 TrackerClient 对象,接着再根据这个对象获取到一个 TrackerServer,然后创建一个 StorageClient1 实例。NameValuePair 中保存的是文件的元数据信息,如果有的话,就以 key/value 的方式来设置,如果没有的话,直接给一个 null 即可。
最后,调用 client 的 upload_file1 方法上传文件,第一个参数是文件路径,第二个参数是文件的扩展名,第三个参数就是文件的元数据信息,这个方法的返回值,就是上传文件的访问路径。
可以看到运行成功,并返回了图片的地址。
group1/M00/00/00/wKhbgF5aMteAWy0gAAJkI7-2yGk361.png 就是文件的路径,此时,在浏览器中输入
http://192.168.91.128/group1/M00/00/00/wKhbgF5aMteAWy0gAAJkI7-2yGk361.png
就可以看到上传的图片了。
文件下载
@Test void testDownload() { try { ClientGlobal.initByProperties("fastdfs-client.properties"); TrackerClient tracker = new TrackerClient(); TrackerServer trackerServer = tracker.getConnection(); StorageServer storageServer = null; StorageClient1 client = new StorageClient1(trackerServer, storageServer); byte[] bytes = client.download_file1("group1/M00/00/00/wKhbgF5aMteAWy0gAAJkI7-2yGk361.png"); FileOutputStream fos = new FileOutputStream(new File("C:\\Users\\javaboy\\Pictures\\picpick\\666.png")); fos.write(bytes); fos.close(); } catch (Exception e) { e.printStackTrace(); } }
这段代码就很好理解了,直接调用 download_file1 方法获取到一个 byte 数组,然后通过 IO 流写出到本地文件即可。
至此,fastDFS的搭建就结束了,又学会一项新技能,开心。