搭建分佈式文件上傳系統總結(linux(ubuntu)搭建FastDFS、java後端實現文件上傳、搭建過程中遇到的各種問題總結)

背景

搭建分佈式文件上傳系統。本身所用到的知識並不是很難,但是搭建過程比較複雜,需要修改的配置很多,所以很容易出錯,尤其是對沒有linux的來說,更是南上加南。我是重裝2次虛擬機,搭建3次FastDFS才成功,所以總結下來

一、所用技術

  1. ubuntu的linux虛擬機
  2. linux搭建nginx
  3. linux搭建FastDFS
  4. Java搭建文件上傳後端微服務
  5. 前臺實現文件上傳(vue-cli)

二、具體搭建過程

linux搭建FastDFS

(1)先安裝libevent
步驟

下載地址:http://libevent.org/
解壓後進入目錄(進入目錄命令:cd 目錄地址)
執行編譯 make
執行安裝 make install
驗證 ls -al /usr/lib |grep libevent

可能出現的問題

如果make命令不能執行,按照提示要求,安裝make插件就好
apt-get install ubuntu-make

也可以採用自動安裝

yum install -y libevent

(2)安裝 libfastcommon
步驟

下載地址:https://github.com/happyfish100/libfastcommon.git
解壓後進入目錄
執行編譯 make
執行安裝 make install
注意上述安裝完之後,安裝完的路徑在/usr/lib64,但是fastDFS訪問的lib路徑在 /usr/local/lib 中 所以此時需要建立軟連接 

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

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

可能出現的問題

如果報錯缺少gcc編譯器環境,那麼使用yum -y install gcc-c++ 安裝gcc

(3)安裝FastDFS

下載地址: https://sourceforge.net/projects/fastdfs/files/FastDFS%20Server%20Source%20Code/FastDFS%20Server%20with%20PHP%20Extension%20Source%20Code%20V5.08/
解壓後進入目錄
執行編譯 make
執行安裝 make install

配置tracker服務
  1. 創建tracker的數據文件/日誌目錄(我存放在了/opt/fastdfs_tracker) 

mkdir -p /opt/fastdfs_tracker
2. 進入 /etc/fdfs/ 執行 

cd /etc/fdfs 

cp tracker.conf.sample tracker.conf
3. 編輯 tracker.conf 

disabled=false #啓用配置文件
port=22122 #設置tracker的端口號
base_path=/opt/fastdfs_tracker#設置tracker的數據文件和日誌目錄(需預先創建)
http.server_port=4418 #設置http端口號(根據需求設置),默認爲8080

爲啓動腳本創建軟引用,因爲fdfs_trackerd等命令在/usr/local/bin中並沒有,而是在/usr/bin路徑下: 

ln -s /usr/bin/fdfs_trackerd /usr/local/bin ln -s /usr/bin/stop.sh /usr/local/bin ln -s /usr/bin/restart.sh /usr/local/bin
4. 啓動 

/usr/bin/fdfs_trackerd /etc/fdfs/tracker.conf restart 

  1. 設置開機啓動 

echo ‘/usr/bin/fdfs_trackerd /etc/fdfs/tracker.conf restart’ >> /etc/rc.d/rc.local 

  1. 通過如下命令查看trackerd服務是否啓動: 

netstat -tupln | grep trackerd
7. 查看一下端口監聽情況 

netstat -unltp|grep fdfs
8. 如果有錯可以在 /opt/fastdfs_tracker/logs 中查看 

可能出現的問題 

如果重啓後發現未能自動啓動則通過命令檢查一下rc.local是否具備可執行權限 

ll /etc/rc.d/rc.local 

若是無可執行權限則進行授權 

chmod +x /etc/rc.d/rc.local

配置Storage服務
  1. 創建存放storage 數據/日誌文件目錄 

mkdir -p /opt/fastdfs_storage
mkdir /opt/fastdfs_storage_data
2. 進入/etc/fdfs 

cd /etc/fdfs/ 

cp storage.conf.sample storage.conf
3. 編輯 storage.conf 

disabled=false #啓用配置文件
group_name=group1  #組名,根據實際情況修改
port=23000 #設置storage的端口號
base_path=/opt/fastdfs_storage #設置storage的日誌目錄(需預先創建)
store_path_count=1 #存儲路徑個數,需要和store_path個數匹配
store_path0=/opt/fastdfs_storage_data #實際文件存儲路徑
tracker_server=192.168.25.130:22122 #tracker服務器的IP地址和端口號 (如果是虛擬機,用虛擬機的地址)
http.server_port=4419  #設置http端口號

配置完成後同樣要爲Storage服務器的啓動腳本設置軟引用:

ln -s /usr/bin/fdfs_storaged /usr/local/bin
4. 啓動 

/usr/bin/fdfs_storaged /etc/fdfs/storage.conf restart 

  1. service fdfs_storaged start開機啓動
    echo ‘/usr/bin/fdfs_storaged /etc/fdfs/storage.conf restart’ >> /etc/rc.d/rc.local
  2. 是否啓動 

netstat -tupln | grep storaged
7. 查看一下端口監聽情況  

netstat -unltp|grep fdfs
8. 如果有錯可以在 /opt/fastdfs_storage/logs 中查看 

可能出現的問題 

storage的23000端口不能正常被監聽到,導致失敗

查看tracker_server=192.168.25.130:22122的地址是否配置正確

配置client

cd /etc/fdfs/

cp client.conf.sample client.conf

vi client.conf

base_path=/opt/fastdfs_storage # 日誌路徑
tracker_server=172.16.1.40:22122  # 可以配置自己虛擬機的地址
http.tracker_server_port=4418    # tracker服務器的http端口號,必須和tracker的設置對應起來
文件上傳測試

/usr/bin/fdfs_upload_file /etc/fdfs/client.conf /opt/1.jpg

如果有類似的信息group1/M00/00/00/wKhXgl2ExjWACzHWAASe8_3bspM447.png證明上傳成功

常用命令
  1. 啓動

    /usr/bin/fdfs_trackerd /etc/fdfs/tracker.conf restart

    /usr/bin/fdfs_storaged /etc/fdfs/storage.conf restart
  2. 查看進程 

    netstat -tupln | grep 進程名稱
  3. 查看端口監聽情況 

    netstat -unltp|grep 端口名稱
(4)安裝fastdfs-nginx-module

下載地址:https://sourceforge.net/projects/fastdfs/files/FastDFS%20Nginx%20Module%20Source%20Code/

解壓進入目錄
修改fastdfs-nginx-module-1.20/src/config文件(解決make時報錯問題——fatal error: fdfs_define.h: 沒有那個文件或目錄
#include “fdfs_define.h”)
配置mod_fastdfs.conf

connect_timeout=10                  		# 客戶端訪問文件連接超時時長(單位:秒)
tracker_server=192.168.56.101:22122  	# tracker服務IP和端口(自己設置)
url_have_group_name=true            		# 訪問鏈接前綴加上組名
store_path0=/opt/fastdfs_storage        		# 文件存儲路徑

複製FastDFS/conf/的部分配置文件到/etc/fdfs目錄

cp http.conf mime.types /etc/fdfs/

(5)安裝Nginx

注:如果之前安裝過nginx在之後的fastdfs-nginx-module編譯肯能會報錯,博主就是遇到這樣的問題,然後重新寫在nginx然後重裝

附:徹底卸載nginx

rm -rf /etc/nginx

rm -rf /usr/sbin/nginx

apt-get remove nginx* (apt-get remove --purge nginx)

sudo apt-get remove nginx #Removes all but config files

sudo apt-get purge nginx #Removes everything

有提示沒有可卸載的,不用理會

安裝一、基於APT源安裝

sudo apt-get install nginx

/usr/sbin/nginx:主程序

/etc/nginx:存放配置文件

/usr/share/nginx:存放靜態文件

/var/log/nginx:存放日誌

其實從上面的根目錄文件夾可以知道,Linux系統的配置文件一般放在/etc,日誌一般放在/var/log,運行的程序一般放在/usr/sbin或者/usr/bin。

當然,如果要更清楚Nginx的配置項放在什麼地方,可以打開/etc/nginx/nginx.conf

我猜測,Nginx如果指定默認加載/etc/nginx/nginx.conf的配置文件。如果要查看加載的是哪個配置文件,可以用這個命令sudo nginx -t或者ps -ef | grep nginx

然後通過這種方式安裝的,會自動創建服務,會自動在/etc/init.d/nginx新建服務腳本,然後就可以使用sudo service nginx {start|stop|restart|reload|force-reload|status|configtest|rotate|upgrade}的命令啓動

安裝二、通過源碼包編譯安裝

下載地址:http://nginx.org/en/download.html

關閉防火牆

ufw enable

ufw disable

安裝依賴:

安裝gcc g++的依賴庫

sudo apt-get install build-essential

sudo apt-get install libtool

安裝pcre依賴庫(http://www.pcre.org/)

sudo apt-get update

sudo apt-get install libpcre3 libpcre3-dev

安裝zlib依賴庫(http://www.zlib.net)

sudo apt-get install zlib1g-dev

安裝SSL依賴庫(16.04默認已經安裝了)

sudo apt-get install openssl

之後正式開始安裝:

進入解壓目錄

配置

sudo ./configure --prefix=/opt/nginx --sbin-path=/usr/bin/nginx --add-module=/home/leyou/fdfs/fastdfs-nginx-module/src

#編譯:

make

#安裝:

sudo make install

配置nginx整合fastdfs-module模塊,修改nginx配置文件,在/opt/nginx/config/nginx.conf文件中:
sudo vim /opt/nginx/conf/nginx.conf

server {
        listen       80;
        server_name  image.taotao.com;

    	# 監聽域名中帶有group的,交給FastDFS模塊處理
        location ~/group([0-9])/ {
            ngx_fastdfs_module;
        }

        location / {
            root   html;
            index  index.html index.htm;
        }

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
        
    }

nginx # 啓動

nginx -s stop # 停止

nginx -s reload # 重新加載配置

#查看進程:

ps -ef | grep nginx

配置開機啓動服務

在/etc/init.d/下創建nginx文件,sudo vim /etc/init.d/nginx,內容如下:

#!/bin/sh
#
# nginx - this script starts and stops the nginx daemon
#
# chkconfig:   - 85 15
# description:  NGINX is an HTTP(S) server, HTTP(S) reverse \
#               proxy and IMAP/POP3 proxy server
# processname: nginx
# config:      /etc/nginx/nginx.conf
# config:      /etc/sysconfig/nginx
# pidfile:     /var/run/nginx.pid

# Source function library.
. /etc/rc.d/init.d/functions

# Source networking configuration.
. /etc/sysconfig/network

# Check that networking is up.
[ "$NETWORKING" = "no" ] && exit 0

nginx="/usr/bin/nginx"
prog=$(basename $nginx)

NGINX_CONF_FILE="/opt/nginx/conf/nginx.conf"

[ -f /etc/sysconfig/nginx ] && . /etc/sysconfig/nginx

lockfile=/var/lock/subsys/nginx

make_dirs() {
   # make required directories
   user=`$nginx -V 2>&1 | grep "configure arguments:.*--user=" | sed 's/[^*]*--user=\([^ ]*\).*/\1/g' -`
   if [ -n "$user" ]; then
      if [ -z "`grep $user /etc/passwd`" ]; then
         useradd -M -s /bin/nologin $user
      fi
      options=`$nginx -V 2>&1 | grep 'configure arguments:'`
      for opt in $options; do
          if [ `echo $opt | grep '.*-temp-path'` ]; then
              value=`echo $opt | cut -d "=" -f 2`
              if [ ! -d "$value" ]; then
                  # echo "creating" $value
                  mkdir -p $value && chown -R $user $value
              fi
          fi
       done
    fi
}

start() {
    [ -x $nginx ] || exit 5
    [ -f $NGINX_CONF_FILE ] || exit 6
    make_dirs
    echo -n $"Starting $prog: "
    daemon $nginx -c $NGINX_CONF_FILE
    retval=$?
    echo
    [ $retval -eq 0 ] && touch $lockfile
    return $retval
}

stop() {
    echo -n $"Stopping $prog: "
    killproc $prog -QUIT
    retval=$?
    echo
    [ $retval -eq 0 ] && rm -f $lockfile
    return $retval
}

restart() {
    configtest || return $?
    stop
    sleep 1
    start
}

reload() {
    configtest || return $?
    echo -n $"Reloading $prog: "
    killproc $nginx -HUP
    RETVAL=$?
    echo
}

force_reload() {
    restart
}

configtest() {
  $nginx -t -c $NGINX_CONF_FILE
}

rh_status() {
    status $prog
}

rh_status_q() {
    rh_status >/dev/null 2>&1
}

case "$1" in
    start)
        rh_status_q && exit 0
        $1
        ;;
    stop)
        rh_status_q || exit 0
        $1
        ;;
    restart|configtest)
        $1
        ;;
    reload)
        rh_status_q || exit 7
        $1
        ;;
    force-reload)
        force_reload
        ;;
    status)
        rh_status
        ;;
    condrestart|try-restart)
        rh_status_q || exit 0
            ;;
    *)
        echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload|configtest}"
        exit 2
esac

#設置服務腳本有執行權限

sudo chmod +x /etc/init.d/nginx  #註冊服務

cd /etc/init.d/

sudo update-rc.d nginx defaults

此時在虛擬機所有的配置已經完成

三、java後端搭建圖片上傳服務

這裏只展示上傳文件的類

@Service
public class UploadService {

    private static final Logger logger = LoggerFactory.getLogger(UploadController.class);

    // 支持的文件類型
    private static final List<String> suffixes = Arrays.asList("image/png", "image/jpeg");

    @Autowired
    FastFileStorageClient storageClient;

    public String upload(MultipartFile file) {
        try {
            // 1、圖片信息校驗
            // 1)校驗文件類型
            String type = file.getContentType();
            if (!suffixes.contains(type)) {
                logger.info("上傳失敗,文件類型不匹配:{}", type);
                return null;
            }
            // 2)校驗圖片內容
            BufferedImage image = ImageIO.read(file.getInputStream());
            if (image == null) {
                logger.info("上傳失敗,文件內容不符合要求");
                return null;
            }

            // 2、將圖片上傳到FastDFS
            // 2.1、獲取文件後綴名
            String extension = StringUtils.substringAfterLast(file.getOriginalFilename(), ".");
            // 2.2、上傳
            StorePath storePath = this.storageClient.uploadFile(
                    file.getInputStream(), file.getSize(), extension, null);
            // 2.3、返回完整路徑
            return "http://image.xxx.com/" + storePath.getFullPath();
        } catch (Exception e) {
            return null;
        }
    }
}

如果想要更加方便去返回,如果使用了springboot的話,可以在配置文件中配置suffixes的文件支持類型和return的域名前綴
這個操作省略

(6)測試

在瀏覽器中輸入http://image.xxx.com/group1/M00/00/00/wKhXgl2ExjWACzHWAASe8_3bspM447.png
去訪問圖片
nginx、FastDFS都沒有問題可以訪問成功

可能遇到的問題
  1. win10訪問linux的nginx,瀏覽器報502  Bad&nbspGateway 的錯誤
    在nginx的配置文件中將localhost改爲虛擬機的地址
前臺實現向後臺請求,然後上傳圖片相對簡單,暫時省略
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章