• FastDFS + Nginx


    普通的存储方式,图片存储过于分散

    • 图片存储过于分散
    • 图片多的服务器压力比较大,可能影响其他功能
    • 存储到项目路径中,重启会丢失。存储到外部文件中,IO操作性能低

    搭建图片服务器

    分布式文件系统概述

    通用分布式文件系统

    专用分布式文件系统

    Google FS 体系结构

    FastDFS简介

    架构图

    角色

    架构解读

    FastDFS安装

    安装C依赖

    yum install -y make cmake gcc gcc-c++

    安装C的一个库,我这边直接GitHub下载

    cd /usr/local/tmp
    git clone https://github.com/happyfish100/libfastcommon.git

    编译并安装

    cd libfastcommon-master
    ./make.sh
    ./make.sh install

    默认的固定安装位置

    • /usr/lib64
    • /usr/lib
    • /usr/include/fastcommon

    创建软链接

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

    上传并解压FastDFS主程序

    git clone https://github.com/happyfish100/fastdfs.git

    编译并安装

    cd fastdfs
    ./make.sh
    ./make.sh install

    • /usr/bin 可执行文件所在的位置
    • /etc/fdfs 配置文件所在的位置
    • /usr/bin 主程序代码所在位置
    • /usr/include/fastdfs 包含一些插件所在的位置

    配置tracker

    复制配置文件

    cd /etc/fdfs
    cp tracker.conf.sample tracker.conf

    创建数据目录

    创建防止tracker数据的目录

    mkdir -p /usr/local/fastdfs/tracker

    修改配置文件,修改tracker.conf设置tracker内容存储目录

    base_path=/usr/local/fastdfs/tracker
    vim tracker.conf

    默认端口 22122 不需要修改

    启动服务

    service fdfs_trackerd start

    启动成功后,配置文件base_path指向的目录出现FastDFS服务相关数据目录(data目录,logs目录)

    查看服务运行状态

    service fdfs_trackerd status

    如果显示 is running 表示正常运行

    关闭防火墙

    service iptables stop
    chkconfig iptables off

    配置Storage

    storage可以和tracker不在同一台服务器中,示例中把storage和tracker安装在同一台服务器

    复制配置文件

    进入到/etc/fdfs,把storage配置文件复制一份

    cd /etc/fdfs
    cp storage.conf.sample storage.conf

    创建目录

    把base用于存储基础数据和日志,store用于存储上传数据

    mkdir -p /usr/local/fastdfs/storage/base
    mkdir -p /usr/local/fastdfs/storage/store

    修改配置文件

    storage.conf配置文件用于描述存储服务的行为,需要进行下述修改

    vim /etc/fdsf/storage.conf

    配置内容如下

    base_path=/usr/local/fastdfs/storage/base
    store_path0=/usr/local/fastdfs/storage/store
    tracker_server=tracker 服务IP:22122
    • base_path,基础路径
    • store_path0,
    • base_path和store_path可以使用同一目录
    • tracker_server 跟踪服务器位置,就是跟踪服务器的IP和端口

    启动服务

    service fdfs_storaged start

    启动成功后,配置文件base_path指向的目录中出现FastDFS服务相关数据目录(data目录,logs目录库)

    配置文件中的store_path0指向的目录同样出现了FastDFS存储相关数据目录(data目录)

    其中$store_path0/data 目录中默认创建若干子孙目录(两层一共256*256),用于存储具体文件数据

    Storage服务器启动比较慢,第一次启动的时候,需要创建256*256个目录

    查看启动状态

    service fdfs_storaged status

    文件上传流程

    时序图

    流程说明

    • 客户端访问Tracker
    • Tracker返回Storage的ip和端口
    • 客户端直接访问Storage,把文件内容和元数据发送过去
    • Storage返回文件存储id,包含了组名和文件名

    Fastdfs-java-client

    添加依赖,官方地址:https://mvnrepository.com/artifact/cn.bestwu/fastdfs-client-java

    <!-- https://mvnrepository.com/artifact/cn.bestwu/fastdfs-client-java -->
    <dependency>
        <groupId>cn.bestwu</groupId>
        <artifactId>fastdfs-client-java</artifactId>
        <version>1.27</version>
    </dependency>

    编写配置文件

    fdfs_client.conf,修改成自己的tracker服务器ip

    connect_timeout = 10
    network_timeout = 30
    charset = UTF-8
    http.tracker_http_port = 8080
    tracker_server = 192.168.93.10:22122

    导入工具类

    在com.utils.FastDFSClient下粘贴配置工具类

    /**
     * FastDFS分布式文件系统操作客户端.
     */
    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();
            }
        }
    
        /**
         *
         * @param inputStream
         *    上传的文件输入流
         * @param fileName
         *    上传的文件原始名
         * @return
         */
        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_file(file_buff, getFileExt(fileName), meta_list);
                return fileids;
            } catch (Exception ex) {
                ex.printStackTrace();
                return null;
            }
        }
    
        /**
         *
         * @param file
         *            文件
         * @param fileName
         *            文件名
         * @return 返回Null则为失败
         */
        public static String[] uploadFile(File file, String fileName) {
            FileInputStream fis = null;
            try {
                NameValuePair[] meta_list = null; // new NameValuePair[0];
                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 ex) {
                return null;
            }finally{
                if (fis != null){
                    try {
                        fis.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    
        /**
         * 根据组名和远程文件名来删除一个文件
         *
         * @param groupName
         *            例如 "group1" 如果不指定该值,默认为group1
         * @param remoteFileName
         *            例如"M00/00/00/wKgxgk5HbLvfP86RAAAAChd9X1Y736.jpg"
         * @return 0为成功,非0为失败,具体为错误代码
         */
        public static int deleteFile(String groupName, String remoteFileName) {
            try {
                int result = storageClient.delete_file(groupName == null ? "group1" : groupName, remoteFileName);
                return result;
            } catch (Exception ex) {
                return 0;
            }
        }
    
        /**
         * 修改一个已经存在的文件
         *
         * @param oldGroupName
         *            旧的组名
         * @param oldFileName
         *            旧的文件名
         * @param file
         *            新文件
         * @param fileName
         *            新文件名
         * @return 返回空则为失败
         */
        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 ex) {
                return null;
            }
            return fileids;
        }
    
        /**
         * 文件下载
         *
         * @param groupName 卷名
         * @param remoteFileName 文件名
         * @return 返回一个流
         */
        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 ex) {
                return null;
            }
        }
    
        public static NameValuePair[] getMetaDate(String groupName, String remoteFileName){
            try{
                NameValuePair[] nvp = storageClient.get_metadata(groupName, remoteFileName);
                return nvp;
            }catch(Exception ex){
                ex.printStackTrace();
                return null;
            }
        }
    
        /**
         * 获取文件后缀名(不带点).
         *
         * @return 如:"jpg" or "".
         */
        private static String getFileExt(String fileName) {
            if (StringUtils.isBlank(fileName) || !fileName.contains(".")) {
                return "";
            } else {
                return fileName.substring(fileName.lastIndexOf(".") + 1); // 不带最后的点
            }
        }
    }

    Nginx

     代理方式

    正向代理

    反向代理

    二者区别

    Nginx作用

    HTTP协议代理

    搭建虚拟主机

    负载均衡

    Nginx安装

    下载fastdfs-nginx-module到/usr/local/tmp中

    cd /usr/local/tmp
    git clone https://github.com/happyfish100/fastdfs-nginx-module

    修改配置文件

    cd fastdfs-nginx-module/src
    vim config

    修改第四行路径,参数用于配置安装nginx中的FastDFS组件的时候,在什么位置查找FastDFS核心代码

    git clone https://github.com/nginx/nginx.git

    安装ngin依赖

    yum install -y gcc gcc-c++ make automake autoconf libtool pcre pcre-devel zlib zlib-devel openssl openssl-devel

    创建临时目录

    mkdir -p /var/temp/nginx

    修改配置文件参数

    ./configure 
    --prefix=/usr/local/nginx 
    --pid-path=/var/run/nginx/nginx.pid 
    --lock-path=/var/lock/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=/usr/local/tmp/fastdfs-nginx-module/src

    修改权限为777

    chmod 777 nginx -R

    编译和安装

    cd nginx
    make
    make install

    配置fastdfs-nginx-module模块配置文件

    复制 fastdfs-nginx-module/src/mod_fastdfs.conf 配置文件到/etc/fdfs目录中

    cp /usr/local/tmp/fastdfs-nginx-module/src/mod_fastdfs.conf /etc/fdfs/

    修改 mod_fastdfs.conf

    cd /etc/fdfs
    vim mod_fastdfs.conf

    文件内容修改

    connect_timeout=10
    tracker_server=192.168.93.10:22122 // 自己的ip和port
    url_have_group_name=true
    store_path0=/usr/local/fastdfs/storage/store // 自己的目录

    提供FastDFS需要的HTTP配置文件

    cp /usr/local/tmp/FastDFS/conf/http.conf /etc/fdfs/
    cp /usr/local/tmp/FastDFS/conf/mime.types /etc/fdfs/

    创建网络访问存储服务的软链接

    ln -s /usr/local/fastdfs/storage/store/data/ /usr/local/fastdfs/storage/store/data/M00

    进入nginx安装目录,修改配置文件

    cd/ usr/local/nginx/conf
    vim nginx.conf

    修改两处

    用户

    user root;

    单个group的配置

    location /M00 {
          ngx_fastdfs_module;
    }

    多个group的配置

    在server_name下面修改

    location ~/group([0-9]/M00){
        ngx_fastdfs_module;
    }

    启动nginx

    进入目录,然后

    cd /usr/local/nginx/sbin
    ./nginx

    关闭nginx

    ./nginx -s quit
    论读书
    睁开眼,书在面前
    闭上眼,书在心里
  • 相关阅读:
    .net 调用命令行进行解压缩
    《jQuery实战》第1章 引荐JQuery
    将指定URL文件下载到指定服务器
    Oracle学习笔记
    Spring3 AOP的使用
    Field类使用以及getDeclaredFields方法
    spring 3的使用
    Json数据类型
    RotateAnimation详解
    GsonJava对象生成Json串
  • 原文地址:https://www.cnblogs.com/YC-L/p/14367647.html
Copyright © 2020-2023  润新知