Java EE--组件篇 FastDFS

目录

前言

FastDFS

下载安装

SpringBoot集成FastDFS


前言

带着问题学java系列博文之java基础篇。从问题出发,学习java知识。


FastDFS

FastDFS是一个开源的分布式文件系统,功能包括:文件存储、文件同步、文件访问(文件上传、文件下载)等,解决了大容量存储和负载均衡的问题。特别适合以文件为载体的在线服务,如相册网站、视频网站等等。FastDFS服务端有两个角色:跟踪器(tracker)和存储节点(storage)。跟踪器主要做调度工作,在访问上起负载均衡的作用。

FastDFS系统结构图:

FastDFS文件上传交互图:

1. client询问tracker上传到的storage,不需要附加参数;

2. tracker返回一台可用的storage;

3. client直接和storage通讯完成文件上传。

FastDFS文件下载交互图:

1. client询问tracker下载文件的storage,参数为文件标识(卷名和文件名);

2. tracker返回一台可用的storage;

3. client直接和storage通讯完成文件下载。

 

下载安装

linux上安装fastdfs:

首先安装fastdfs依赖的两个组件GCC和libfastcommon

一.安装GCC

yum install make cmake gcc gcc-c++

二.安装libfastcommon

1.下载安装包 link:https://github.com/happyfish100/libfastcommon/releases

2.上传服务器 rz -y 选择压缩包

3.解压缩 tar -zxvf libfastcommon-1.0.42.tar.gz

4.进入解压文件夹 cd libfastcommon-1.0.42

5.编译 ./make.sh

6.安装 ./make.sh install

libfastcommon 默认安装到了 /usr/lib64/libfastcommon.so /usr/lib64/libfdfsclient.so

因为 FastDFS 主程序设置的 lib 目录是/usr/local/lib,所以需要创建软链接:

ln -s /usr/lib64/libfastcommon.so /usr/lib/libfastcommon.so

ln -s /usr/lib64/libfastcommon.so /usr/lib/libfastcommon.so

ln -s /usr/lib64/libfdfsclient.so /usr/local/lib/libfdfsclient.so

ln -s /usr/lib64/libfdfsclient.so /usr/lib/libfdfsclient.so

三.安装FastDFS

1.下载安装包 link:https://github.com/happyfish100/fastdfs/releases

2.上传服务器 rz -y 选择压缩包

3.解压缩 tar -zxvf fastdfs-6.04.tar.gz

4.进入解压文件夹 cd fastdfs-6.04

5.编译 ./make.sh

6.安装 ./make.sh install

安装完成之后,fastdfs的默认配置文件在 /etc/fdfs/下:

client.conf.sample                            storage.conf.sample

storage_ids.conf.sample                  tracker.conf.sample

这四个是样板,以后的配置就是复制样板修改。

默认的启动文件在 /etc/init.d/下:

fdfs_storage :storage存储节点服务启动文件 启动storage命令 ./fdfs_storage start

fdfs_tracker :tracker跟踪服务器启动文件 启动tracker命令 ./fdfs_tracker start

修改启动文件,因为fdfs服务脚本设置的bin目录是/usr/local/bin,但是实际安装之后文件都在/usr/bin,因此需要修改两个启动文件,把其中/usr/local/bin的全换成/usr/bin。

方式一:

sed -i ‘s#/usr/local/bin/#/usr/bin/#g’ /etc/init.d/fdfs_storaged

sed -i ‘s#/usr/local/bin/#/usr/bin/#g’ /etc/init.d/fdfs_trackerd

方式二:

vi /etc/init.d/fdfs_storaged 修改其中的路径;

vi /etc/init.d/fdfs_tracker 修改其中的路径

7.配置

i.先创建文件夹用来存放fdfs的日志和数据存储

mkdir -p /data/fdfs/tracker

mkdir -p /data/fdfs/storage

ii.配置tracker

cd /etc/fdfs/

cp tracker.conf.sample tracker.conf (复制模板,去掉sample,tracker会自动启用)

vi tracker.conf

修改的内容如下: disabled=false #启用配置文件 port=22122 #tracker的端口号,一般采用 22122 这个默认端口 base_path=/data/fdfs/tracker #tracker的数据文件和日志目录

保存退出后,测试启动tracker

cd /etc/init.d/ => ./fdfs_trackerd start

Starting FastDFS tracker server:(显示信息表示启动成功,可以在配置的存储目录下看到自动创建了data和base两个文件夹,服务所在端口是22122)

设置开机启动:

vi /etc/rc.d/rc.local

添加如下内容:

## FastDFS Tracker /etc/init.d/fdfs_trackerd start

iii.配置storage存储

cd /etc/fdfs

cp storage.conf.sample storage.conf

vi storage.conf

修改的内容如下:

disabled=false #启用配置文件 

group_name=group1 #组名(第一组为 group1,第二组为 group2)

port=23000 #storage的端口号,同一个组的 storage 端口号必须相同 

base_path=/data/fdfs/storage #设置storage 的日志目录 

store_path0=/data/fdfs/storage #存储路径 

store_path_count=1 #存储路径个数,需要和 store_path个数匹配 

tracker_server=192.168.218.130:22122 #tracker 服务器的 IP 地址和端口 

#tracker_server=192.168.1.132:22122 #多个 tracker 直接添加多条配置 

http.server_port=8888 #设置 http server 端口号

保存退出之后,测试启动storage

cd /etc/init.d => ./fdfs_storaged start

Starting FastDFS storage server:(显示信息表示启动成功,可以在配置的存储目录下看到自动创建了data和logs两个文件夹,服务所在端口是23000)

设置 FastDFS 存储器开机启动: vi /etc/rc.d/rc.local 添加:

## FastDFS Storage 

/etc/init.d/fdfs_storaged start

至此fastdfs安装配置完成,可以编写程序测试文件上传下载。完成第三步之后,使用代码操作fdfs,可以实现文件上传下载,不过此时文件上传成功之后返回的url,通过浏览器http方式是无法访问的。这是由于V4.05 以后的版本就把内置HTTP服务去掉了,搭建好fastdfs 系统后 还需要搭建web容器功能。

四.安装nginx web插件

安装配置fastdfs-nginx-module:

1.下载 link:https://github.com/happyfish100/fastdfs-nginx-module/

2.上传 rz -y 选择压缩包

3.解压缩 tar -zxvf fastdfs-nginx-module-1.22.tar.gz

4.修改配置 vi fastdfs-nginx-module-1.22/src/config 把文件中的/usr/local 都改为 /usr

5.复制配置文件到fdfs的配置文件夹下  cp fastdfs-nginx-module-1.22/src/mod_fastdfs.conf /etc/fdfs

6.修改配置  vi /etc/fdfs/mod_fastdfs.conf   修改内容如下:

connect_timeout=10 #连接超时时间
network_timeout=30 #发送接收数据超时时间
base_path=/tmp #日志文件位置
load_fdfs_parameters_from_tracker=true #是否从tracker读取信息
storage_server_port=23000 #本机storage的端口
group_name=group1 #group组名
# url链接中是否包含组名(这个url是fastdfs返回的,目前还不清楚如何配置不返回组名,所以这里的配置
# 要根据url来配置,否则nginx转发无法访问),类似/M00/00/00/xxxx 和 group1/M00/00/00/xxxx;如果# 选择true,即包含组名,则需要修改nginx的映射路径:
# location /M00 改为 location /group1/M00
# 这里考虑到有可能有多组,所以可以灵活配置:
# location ~*/M00 或者是 location /group[0-9]/M00 匹配所有group)
url_have_group_name = true #(注意这里必须和url中一致,如果返回的url中有组名,则这里必须配置成true)

tracker_server=192.168.218.130:22122 #tracker服务器ip和端口
store_path_count=1 #存储路径数量,必须和 storage.conf文件一致
store_path0=/data/fdfs/storage #存储路径,必须和 storage.conf文件一致
#(当文件在本地不存在时怎样回应:
# proxy 代理,从其它存储服务器获取内容,然后发送给客户
# redirect  重定向原始存储服务器的http头)
response_mode=proxy
group_count = 0 #设置组的数量,0表示只有一个组,如果有多个组,则配合【group1】组合配置

7.复制fdfs安装包中的配置文件到fdfs的配置文件夹下(/root/fastdfs-6.04/conf)

cp /root/fastdfs-6.04/conf/http.conf /etc/fdfs

cp /root/fastdfs-6.04/conf/mime.types /etc/fdfs

安装配置nginx(nginx安装配置详见 Java EE--组件篇 Nginx

创建软链接: ln -s /data/fdfs/storage/data/ /data/fdfs/storage/data/M00

配置nginx代理

vi /usr/local/nginx/conf/nginx.conf

添加内容:

# 这种配置是利用nginx的web容器功能,进行静态资源代理
# 有个致命问题是,如果有多个storage节点,并且其他的storage节点是部署在别的服务器上,则这种代理
# 方式将无法确保所有的资源都可以支持访问
server{
    listen 8888; 
    server_name 192.168.218.130;

    location ~/group[0~9]/M[0~9][0~9]{
        root /data/fdfs/storage/data;
        ngx_fastdfs_module;
}

注意:如果上面的mod_fastdfs.conf文件中配置了
url_have_group_name = true 即url中包含组名,
则映射路径应该配置成:
location /group1/M00 (组名是啥就添加啥,很明显,这个并不好,因为具体有多少group就得配置多少,所以不推荐使用)
或者配置成:
location ~*/M00  或者 location /group[0-9]/M00

至此fdfs的全部配置完成,与nginx的整合也搞定,上传成功之后fdfs返回的url:

192.168.218.130:8888/M00/00/00/wKjagl3zR6uAVOedAAHOvkPMWig767.png

可以直接在浏览器中打开。

 

 

 

SpringBoot集成FastDFS

1.引入依赖

        <dependency>
            <groupId>com.github.tobato</groupId>
            <artifactId>fastdfs-client</artifactId>
            <version>RELEASE</version>
        </dependency>

2.增加配置(application.yml):

fdfs:
  so-timeout: 1501 #socket读取超时时长
  connect-timeout: 601 #连接tracker服务器超时时长
  pool:
    max-total: 200 #连接池最大数量
    max-total-per-key: 50 #每个tracker地址的最大连接数
    max-wait-millis: 5000 #连接耗尽时等待获取连接的最大毫秒数
  thumb-image:
    height: 150 #缩略图的高
    width: 150  #缩略图的宽
  web-server-url: 192.168.218.129:80/  #storage的webserver地址,nginx代理的ip+port
  tracker-list:
    - 192.168.218.129:22122   #tracker服务器地址
  group-name: group1 #个人配置的组名

3.引入起步配置:

@SpringBootApplication
// 因为springboot没有封装fastdfs(从引入的依赖可以看出,不是标准的spring-boot-starter),所以需
// 要手动引入起步依赖
@Import(FdfsClientConfig.class)
public class SpringBootFdfsApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringBootFdfsApplication.class,args);
    }
}

4.封装fastdfsClient工具类(可选):

@Component
public class FastDFSClient {
    private static final Logger LOGGER = LoggerFactory.getLogger(FastDFSClient.class);


    @Autowired
    private FdfsWebServer fdfsWebServer;

    @Autowired
    private FastFileStorageClient fastFileStorageClient;

    @Autowired
    private AppendFileStorageClient appendFileStorageClient;

    /**
     * 上传文件MultipartFile类型
     * @param file 文件对象
     * @return 文件访问地址
     * @throws IOException
     */
    public String uploadFile(MultipartFile file) throws IOException {
        InputStream inputStream = file.getInputStream();
        //通过file.getOriginalFilename()获取文件名称,再通过FilenameUtils.getExtension()获取文件类型名
        StorePath storePath = fastFileStorageClient.uploadFile(inputStream, file.getSize(),
                FilenameUtils.getExtension(file.getOriginalFilename()), null);
        inputStream.close();
        return getResAccessUrl(storePath);
    }

    /**
     * 上传文件File类型
     * @param file 文件对象
     * @return 文件访问地址
     * @throws IOException
     */
    public String uploadFile(File file) throws IOException {
        InputStream inputStream = new FileInputStream(file);
        StorePath storePath = fastFileStorageClient.uploadFile(inputStream, FileUtils.sizeOf(file),
                FilenameUtils.getExtension(file.getName()), null);
        inputStream.close();
        return getResAccessUrl(storePath);
    }

    /**
     * 封装文件完整URL地址
     * @param storePath
     * @return
     */
    private String getResAccessUrl(StorePath storePath) {
        String fileUrl = fdfsWebServer.getWebServerUrl() + storePath.getFullPath();
        return fileUrl;
    }


    /**
     * 上传头像,并生成缩略图(MultipartFile类型)
     * @param file 文件对象
     * @return 文件访问地址
     * @throws IOException
     */
    public String uploadFace(MultipartFile file) throws IOException {
        InputStream inputStream = file.getInputStream();
        StorePath storePath = fastFileStorageClient.uploadImageAndCrtThumbImage(inputStream, file.getSize(),
                FilenameUtils.getExtension(file.getOriginalFilename()), null);
        inputStream.close();
        return getResAccessUrl(storePath);
    }


    /**
     * 上传头像,并生成缩略图(File类型)
     * @param file 文件对象
     * @return 文件访问地址
     * @throws IOException
     */
    public String uploadFace(File file) throws IOException {
        InputStream inputStream = new FileInputStream(file);
        StorePath storePath = fastFileStorageClient.uploadImageAndCrtThumbImage(inputStream, FileUtils.sizeOf(file),
                FilenameUtils.getExtension(file.getName()), null);
        inputStream.close();
        return getResAccessUrl(storePath);
    }

    /**
     * 根据返回的图片地址获取缩略图地址
     * @param url 图片地址
     * @return  缩略图地址(生成规则与配置有关,150x150)
     */
    public String getThumbImageUrl(String url){
        int index = url.lastIndexOf(".");
        String fileName = url.substring(0,index)+"_150x150.";
        String ext = url.substring(index+1);
        return fileName+ext;
    }


    /**
     * 上传可追加内容文件
     * @param file 文件对象
     * @param groupName 组名
     * @return 文件访问地址
     * @throws IOException
     */
    public String uploadAppenderFile(MultipartFile file,String groupName) throws IOException {
        InputStream inputStream = file.getInputStream();
        StorePath storePath = appendFileStorageClient.uploadAppenderFile(groupName, inputStream,
                file.getSize(), FilenameUtils.getExtension(file.getOriginalFilename()));
        inputStream.close();
        return getResAccessUrl(storePath);
    }

    /**
     * 上传可追加内容,指定文件类型
     * @param data 上传内容
     * @param groupName 组名
     * @param ext  文件类型
     * @return 文件访问地址
     * @throws IOException
     */
    public String uploadAppenderFile(byte[] data,String groupName,String ext) throws IOException {
        InputStream inputStream = new ByteArrayInputStream(data);
        StorePath storePath = appendFileStorageClient.uploadAppenderFile(groupName, inputStream,data.length, ext);
        inputStream.close();
        return getResAccessUrl(storePath);
    }

    /**
     * 追加上传
     * @param file 文件对象
     * @param url  可追加文件访问地址
     * @throws IOException
     */
    public void appendFile(MultipartFile file,String url) throws IOException {
        InputStream inputStream = file.getInputStream();
        StorePath storePath = StorePath.parseFromUrl(url);
        appendFileStorageClient.appendFile(storePath.getGroup(),storePath.getPath(),inputStream,
                file.getSize());
        inputStream.close();
    }

    /**
     * 追加上传
     * @param data 追加内容
     * @param url  可追加文件访问地址
     * @throws IOException
     */
    public void appendFile(byte[] data,String url) throws IOException {
        InputStream inputStream = new ByteArrayInputStream(data);
        StorePath storePath = StorePath.parseFromUrl(url);
        appendFileStorageClient.appendFile(storePath.getGroup(),storePath.getPath(),inputStream,data.length);
        inputStream.close();
    }

    /**
     * 删除文件
     * @param fileUrl
     * @return
     */
    public boolean deleFile(String fileUrl) {
        if (StringUtils.isEmpty(fileUrl)) {
            return false;
        }
        try {
            StorePath storePath = StorePath.parseFromUrl(fileUrl);
            fastFileStorageClient.deleteFile(storePath.getGroup(), storePath.getPath());
        } catch (FdfsUnsupportStorePathException e) {
            LOGGER.error("删除文件异常!", e);
            return false;
        }
        return true;
    }

    /**
     * 下载文件
     * @param fileUrl
     * @return
     */
    public byte[] downloadFile(String fileUrl) {
        StorePath storePath = StorePath.parseFromUrl(fileUrl);
        byte[] bytes = fastFileStorageClient.downloadFile(storePath.getGroup(), storePath.getPath(),
                new DownloadByteArray());
        return bytes;
    }
}

 

参考文档:https://www.oschina.net/p/fastdfs?hmsr=aladdin1e1


以上系个人理解,如果存在错误,欢迎大家指正。原创不易,转载请注明出处!

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值