网页右边,向下滑有目录索引,可以根据标题跳转到你想看的内容 |
---|
如果右边没有就找找左边 |
- 通用分布式文件系统
和传统的本地文件系统(ext3,NTFS等)相对应。典型代表Iustre、MooseFS
- 优点:表中文件系统操作方式,对开发者门槛较低
- 缺点:系统复杂性较高,需要支持若干标准的文件操作,如:目录结构、文件读写权限、文件锁等。复杂性更高,系统整体性能有所降低,因为要支持POSIX标准(表示可移植操作系统接口,POSIX标准定义了操作系统应该为应用程序提供的接口标准)
- 专用分布式文件系统
基于google File System的思想,文件上传后不能修改。需要使用专有API对文件进行访问,也可称作分布式文件存储服务。典型代表:MogileFS、FastDFS、TFS。
- 优点:系统复杂性较低,不需要支持若干标准的文件操作,如:目录结构、文件读写权限、文件锁等,系统比较简洁。系统整体性能较高,因为无需支持POSIX标准,可以省去支持POSIX引入的环节,系统更加高效
- 缺点:采用专用API,对开发者门槛较高(直接封装成工具类)
- 两个角色
- 名字服务器(索引服务器)
- 存储服务器
- 架构特点
- 不支持文件修改功能
- 文件分块存储,需要索引服务器
- 一个文件可以存储多份,一个文件存储到哪些存储服务器,通常采用动态分配的方式
- FastDFS是一个轻量级的开源分布式文件系统。2008年4月份开始启动。类似google FS的一个轻量级分布式文件系统,存C语言实现,支持Linux、FreeBSD、AIX等UNIX系统
- 主要解决了大容量的文件存储和高并发访问的问题,文件存取时实现了负载均衡。实现了软件方式的磁盘阵列(RAID),可以使用廉价IDE硬盘进行存储。并且支持存储服务器在线扩容。支持相同内容的文件只保存一份,节约磁盘空间。
- FastDFS只能通过ClientAPI访问,不支持POSIX访问方式。
- FastDFS特别适合大中型网站使用,用来存储资源文件(如:图片、文档、音频、视频等等)
- FastDFS没有官网,但是作者happy_fish100余庆担任chinaunix中FastDFS板块版主。并且会不定期更新板块中内容。http://bbs.chinaunix.net
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/c023e156bf493d153d2b4a9f4ce305a3.png)
- FastDFS软件可以在sourceforge中下载https://sourceforge.net/projects/fastdfs/files/(不推荐使用这种下载方式,具体下载请看下面环境搭建内容)
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/47976d4056cfc77d3b5223ec7d0f8bf9.png)
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/a090fe59daa4174a39b1df8b97dff2c4.png)
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/bc182bf3c886d7e9d927617d7c340804.png)
- Client:客户端。使用java语言编写的项目属于客户端
- Tracker Server:跟踪服务器,主要做调度工作,在访问上起均衡负载的作用。在内存中记录集群中group和storage server的状态信息,是连接Client和Storage server的枢纽
- Storage Server:存储服务器,文件和文件属性(meta data)都保存到存储服务器上,按组group存储,就是上图白色的框框,有若干组,不同组之间不会互相通信
- 架构解读
- 只有两个角色,tracker server和storage server,不需要存储文件索引信息。
- 所有服务器都是对等的,不存在Master-Slave关系。
- 不同组中storage server之间不会相信通信。
- 由storage server主动向tracker server报告状态,tracker server之间不会互相通信。
一、环境搭建
- libfastcommon 下载地址: https://github.com/happyfish100/libfastcommon/releases
- libfastcommon是FastDFS官方提供的,libfastcommon包含了FastDFS运行所需要的一些c语言基础库
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/70435a76cb4da7a55799498b358b85f6.png)
- FastDFS 下载地址 https://github.com/happyfish100/fastdfs/releases
注意:请大家下载6.4以上版本,推荐6.4,因为和nginx做整合时,低版本会发生冲突问题
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/4fc4b5fed9ddf418b794d1df0cca816c.png)
- 打开Linux,安装c语言环境,不会Linux请参考文章https://blog.csdn.net/grd_java/article/details/115676099
FastDFS 是C语言开发的应用。安装必须使用make,cmake和gcc编译器
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/003cb05742e343de9c1340392fcff8e7.png)
yum install -y make cmake gcc gcc-c++
yum -y install libevent
- 安装libfastcommon
- 将两个包传过去
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/81990a5f37e40cfadc13fb5b7f8b9880.png)
- 解压
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/a24cc7f1b9666fcb493a2eb8f4f9fab5.png)
tar -zxvf libfastcommon-1.0.49.tar.gz -C /opt/module/
- 编译
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/5fc99a3a502a5ca2ad0181ead668d3b0.png)
- 执行安装(有固定的默认安装位置。在/usr/lib64和/usr/include/fastcommon两个目录中)
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/a09ae16e8419cfa50f1c932c93567ff5.png)
- 创建软连接(因为FastDFS主程序设置的lib目录是/usr/local/lib所以需要创建软连接,就是快捷方式)
ln -s /usr/lib64/libfastcommon.so /usr/local/lib/libfastcommon.so
ln -s /usr/local/lib64/libfdfsclient.so /usr/local/lib/libfdfsclient.so
- 解压FastDFS
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/408e637ff2a8124331f55bbf3aa23a2d.png)
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/094c7dfb9419c16958a2f1fe3d5fe9de.png)
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/b73dcdc95baac1ba52f7bc08a2a2e59d.png)
- 文件解析
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/372dac5217458f68f3b8ba270f7e9a07.png)
- 配置tracker
- 复制配置文件(进入/etc/fdfs中,把tracker配置文件复制一份)
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/a73f917d5e85ed9f31d3de5db820775a.png)
cp tracker.conf.sample tracker.conf
- 创建数据目录(创建放置tracker数据的目录)
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/c918f7743fbb4010e3e65c3ad96ff897.png)
mkdir -p /usr/local/fastdfs/tracker
- 修改配置文件(修改tracker.conf设置tracker内容存储目录)
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/923ff09d5e102e28416ec741165c83ca.png)
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/566b1a735673239377e9a24a685c4e23.png)
- 启动服务(启动成功后,配置文件中指定的目录出现data目录和logs目录)
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/4cd6053cedf66c1d7e740f36b6d13e54.png)
service fdfs_trackerd start
- 查看服务运行状态
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/9e2b083b1a5280f6c545cf13f86e9491.png)
service fdfs_trackerd status
- 配置storage(可以和tracker不在同一台服务器)
- 复制配置文件(进入/etc/fdfs,把storage配置文件复制一份)
[root@hadoop105 tracker]# cd /etc/fdfs/
[root@hadoop105 fdfs]# cp storage.conf.sample storage.conf
- 创建目录(创建两个,base用于存储基础数据和日志,store用于存储上传数据)
[root@hadoop105 fdfs]# mkdir -p /user/local/fastdfs/storage/base
[root@hadoop105 fdfs]# mkdir -p /user/local/fastdfs/storage/store
- 修改配置文件(storage.conf配置文件用于描述存储服务的行为,需要进行如下修改)
[root@hadoop105 fdfs]# vim /etc/fdfs/storage.conf
# 基础路径,用于保存storage server基础数据内容和日志内容的目录
base_path=/user/local/fastdfs/storage/base
#存储路径,用于保存FastDFS中存储文件的目录,就是要创建256*256个子目录位
store_path0=/user/local/fastdfs/storage/store
# tracker服务的ip和端口,注意ip写你自己虚拟机或服务器ip,22122是tracker的默认端口,可以在上面tracker.conf文件中配置
tracker_server=192.168.10.105:22122
- 启动(成功后,指定目录出现data和logs,path0指定目录,只出现data,第一次启动需要创建256*256子目录,会比较慢)
[root@hadoop105 fdfs]# service fdfs_storaged start
[root@hadoop105 fdfs]# service fdfs_storaged status
二、文件上传
- 客户端访问Tracker
- Tracker返回Storage的ip和端口
- 客户端直接访问Storage,把文件内容和元数据发送过去
- Storage返回文件存储id,包含了组名和文件名
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/404b8638d37a778760c178b77abeb3f3.png)
- 创建maven项目添加依赖
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/d65bd25653470c0a1c4cbad5f23abb51.png)
<dependencies>
<!--这个依赖,作者没有写,所以很多人提供了很多版本,内容都一样,如果这个失效,请去maven仓库换一个fastdfs-client-java-->
<dependency>
<groupId>net.oschina.zcx7878</groupId>
<artifactId>fastdfs-client-java</artifactId>
<version>1.27.0.0</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.4</version>
</dependency>
</dependencies>
- 编写配置文件
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/e82ce0092857fe31b364d8e53b5a540e.png)
connect_timeout = 10
network_timeout = 30
charset = UTF-8
http.tracker_http_port = 8080
tracker_server = 192.168.10.105:22122
- 工具类
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/d2e8081b4ac64b13877584e811039260.png)
import org.apache.commons.lang3.StringUtils;
import org.csource.common.NameValuePair;
import org.csource.fastdfs.*;
import java.io.*;
public class FastDFSClient {
private static final String CONF_FILENAME=Thread.currentThread().getContextClassLoader().getResource("").getPath()+"fdfs_client.conf";
private static StorageClient storageClient = null;
static{
try {
ClientGlobal.init(CONF_FILENAME);
TrackerClient trackerClient = new TrackerClient(ClientGlobal.g_tracker_group);
TrackerServer trackerServer = trackerClient.getConnection();
StorageServer storageServer = trackerClient.getStoreStorage(trackerServer);
storageClient = new StorageClient(trackerServer,storageServer);
} catch (Exception e) {
e.printStackTrace();
}
}
public static String[] uploadFile(InputStream inputStream,String fileName){
try {
NameValuePair[] meta_list = new NameValuePair[2];
meta_list[0] = new NameValuePair("file name",fileName);
meta_list[1] = new NameValuePair("file length",inputStream.available()+"");
byte[] file_buff = null;
if (inputStream != null){
int len = inputStream.available();
file_buff = new byte[len];
inputStream.read(file_buff);
}
String[] fileids = storageClient.upload_appender_file(file_buff,getFileExt(fileName),meta_list);
return fileids;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public static String[] uploadFile(File file,String fileName){
FileInputStream fis = null;
try {
NameValuePair[] meta_list = null;
fis = new FileInputStream(file);
byte[] file_buff = null;
if(fis != null){
int len = fis.available();
file_buff = new byte[len];
fis.read(file_buff);
}
String[] fileids = storageClient.upload_file(file_buff,getFileExt(fileName),meta_list);
return fileids;
} catch (Exception e) {
e.printStackTrace();
return null;
}finally {
if(fis != null){
try{
fis.close();
}catch (IOException e){
e.printStackTrace();
}
}
}
}
public static int deleteFile(String groupName,String remoreFileName){
try {
int result = storageClient.delete_file(groupName == null ? "group1" : groupName, remoreFileName);
return result;
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
public static String[] modifyFile(String oldGroupName,String oldFileName,File file,String fileName){
String[] fileids = null;
try{
fileids = uploadFile(file,fileName);
if(fileids == null){
return null;
}
int delResult = deleteFile(oldGroupName,oldFileName);
if(delResult != 0){
return null;
}
}catch (Exception e){
return null;
}
return fileids;
}
public static InputStream downloadFile(String groupName,String remoteFileName){
try{
byte[] bytes = storageClient.download_file(groupName, remoteFileName);
InputStream inputStream = new ByteArrayInputStream(bytes);
return inputStream;
}catch (Exception e) {
return null;
}
}
public static NameValuePair[] getMetaDate(String groupName,String remoteFileName){
try{
NameValuePair[] nvp = storageClient.get_metadata(groupName, remoteFileName);
return nvp;
}catch (Exception e){
e.printStackTrace();
return null;
}
}
private static String getFileExt(String fileName){
if(StringUtils.isBlank(fileName)||!fileName.contains(".")){
return "";
}else{
return fileName.substring(fileName.lastIndexOf(".")+1);
}
}
}
- 编写客户端代码,上传一张图片测试(上传后的文件名,是FastDFS自动生成,和我们代码设置的文件名没啥关系)
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/79caf0faf289e1db6b28f4c63f1ea1d0.png)
import com.yzpnb.utils.FastDFSClient;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.Arrays;
import java.util.UUID;
public class MyClient {
public static void main(String[] args) {
try{
File file = new File("D:/a.jpg");
InputStream inputStream = new FileInputStream(file);
String fileName = UUID.randomUUID().toString()+ ".jpg";
String[] result = FastDFSClient.uploadFile(inputStream, fileName);
System.out.println(Arrays.toString(result));
}catch (Exception e){
e.printStackTrace();
}
}
}
三、下载
- 编写代码并运行
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/30518940944e64f7254424f650514399.png)
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/e11c673290218a0b455e88b3e32f4d86.png)
import com.yzpnb.utils.FastDFSClient;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.Arrays;
import java.util.UUID;
public class MyClient {
public static void main(String[] args) {
try{
InputStream is = FastDFSClient.downloadFile("group1", "M00/00/00/wKgKaWENAOWEMeDCAAAAAOFj66Y127.jpg");
FileOutputStream os = new FileOutputStream(new File("D:/b.jpg"));
int index = 0;
while((index = is.read())!=-1){
os.write(index);
}
os.flush();
os.close();
is.close();
}catch (Exception e){
e.printStackTrace();
}
}
}
四、图片访问
- FastDFS没有提供图片访问功能
- 所以我们需要使用代理来实现
- nginx提供的代理功能可以实现图片访问,但只支持http请求代理(只要支持http协议访问的内容,nginx都可以代理),当接受到外部http请求,返回本地文件资源给客户端
- 我们需要借助nginx来实现,外部请求图片,把图片信息响应给请求方
- 上传到虚拟机并安装:
- fastdfs-nginx-module模块 :https://github.com/happyfish100/fastdfs-nginx-module
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/1c2eb3660a2c28ba1d79dff9bad1a8b3.png)
- nginx: http://nginx.org/en/download.html
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/c878d68cdfcabee6fa149c3ed43ab64b.png)
- 上传两个文件,解压
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/dfbcc68635a33fd3f999004a0dce7668.png)
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/201595b2e8505654da647feff4a5b0d5.png)
- 修改fastdfs-nginx-module配置文件,在文件中src目录下的config文件,因为配置文件中指定的是fastDFS核心代码位置,我们需要指定
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/8f56e5c0ce17e6722fc292542e10492e.png)
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/71bc7afbfb0e3e36948d4d8a2191b722.png)
/usr/include/fastdfs /usr/include/fastcommon/
- 安装nginx
- 安装一些c++之类的运行库
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/083175c8502a6e38915b6e2f30f8b3ef.png)
yum install -y gcc gcc-c++ make automake autoconf libtool pcre pcre-devel zlib zlib-devel openssl openssl-devel
- 修改配置文件之前,创建一个目录(修改配置文件中好多位置都使用了/var/temp/nginx目录,我们需要手动创建这个目录)
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/a8bd50d028c60fbb005dfc8e7d999749.png)
- 给nginx加权限
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/c97907b10b88adcfcdb871090368a207.png)
- 进入nginx目录,添加配置(
你需要修改最后一行,指定路径到你安装fastdfs-nginx-module的src路径
)
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/7a37cee8730a4b5a9d80c2fd62def0d7.png)
./configure \
--prefix=/usr/local/nginx \
--pid-path=/var/local/nginx/nginx.pid \
--lock-path=/var/lock/nginx/nginx.lock \
--error-log-path=/var/log/nginx/error.log \
--http-log-path=/var/log/nginx/access.log \
--with-http_gzip_static_module \
--http-client-body-temp-path=/var/temp/nginx/client \
--http-proxy-temp-path=/var/temp/nginx/proxy \
--http-fastcgi-temp-path=/var/temp/nginx/fastcgi \
--http-uwsgi-temp-path=/var/temp/nginx/uwsgi \
--http-scgi-temp-path=/var/temp/nginx/scgi \
--add-module=/opt/module/fastdfs-nginx-module-master/src
- 编译并安装(在nginx目录下,执行make命令编译安装,make install运行)
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/7ee5a1aef16930352aeb44cee79e8058.png)
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/57c4eb7d34cc1575058b24e2058544ba.png)
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/8327b688bbd5e3f146a9c8de0250f399.png)
- 复制fastdfs-nginx-module/src/mod-fastdfs.conf配置文件到/etc/fdfs目录,并修改它
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/2f9c1dbda04f878abdb0b0db3fac016d.png)
cp /opt/module/fastdfs-nginx-module-master/src/mod_fastdfs.conf /etc/fdfs/
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/36afcf78f5541da5943dfe140ea416ec.png)
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/bf11f89422324ae373bbf03f1ae43227.png)
connect_timeout=10 # 连接超时时间,单位秒
tracker_server=192.168.10.105:22122# tracker服务结点
url_have_group_name = true# URL是否包含group名称
store_path0=/user/loacl/fastdfs/storage/store#storage服务结点的存储位置,配置与storage结点一致
- 提供FastDFS需要的HTTP配置文件(复制FastDFS安装包中两个配置文件http.conf和mine.types到/etc/fdfs目录中)
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/2f7bc176b39a4ee1d3913f1d5e244dac.png)
- 创建网络访问存储服务的软连接(在上传文件到FastDFS后,FastDFS会返回group1/M00/00/00/xxxxx/xx其中group1是卷名,在mod_fastdfs.conf配置文件中已配置了url_have_group_name,以保证URL解析正确。其中的M00是FastDFS保存数据时使用的虚拟目录,需要将这个虚拟目录定位到真实数据目录上)
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/e1d901dcf79518d146660d239bd6b266.png)
ln -s /user/local/fastdfs/storage/store/data/ /user/local/fastdfs/storage/store/data/M00
- 修改nginx配置文件
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/cb64bdae2373034872432fc419e60708.png)
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/65b59748d9d8104c5b45938da751fdef.png)
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/9b1b6439ccd819fcc681733e505ddda5.png)
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/f347cb3b5a9279778b0f17ea3adebc43.png)
- 启动nginx
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/fd9324c0f4b2914454ee104448b0c45d.png)
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/4cdad138578e2af705b8a6e867847a41.png)
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/82723c04aef6632fa7625e6a169a05a0.png)
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/dcc58084d41fd99adb2382b344198b41.png)
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/cf69b5d432962b4357165f6a7f9275d3.png)
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/20b68f6aed65e62820f2d52dfc1a1d52.png)
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/a4de0d47bbf9afac447f7a5a0ee0d556.png)
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/ef3f560bddde96469b568b4a719908b0.png)