02【熟悉】FastDFS原理及入門
1路翻,系統(tǒng)結構圖
FastDFS分為Tracker、Storage慎王,其中Storage負責存儲文件,Tracker負責存儲文件所在地址厦取,主要作用是負載均衡和資源調(diào)度。
Tracker管搪、Storage都可以實現(xiàn)集群部署虾攻,Tracker的每個節(jié)點地位平等,而Storage可以分為多個組更鲁,每個組之間保存的文件是不同的霎箍,組內(nèi)部分為多個成員,每個成員保存的內(nèi)容是一樣澡为,組成員地位一致漂坏,沒有主從概念。
使用FastDFS存儲文件優(yōu)點:可以應對互聯(lián)網(wǎng)的海量文件存儲,一旦文件較多顶别,可以隨時橫向擴展谷徙,且集群的實現(xiàn)也使系統(tǒng)不存在單點故障問題,用戶不會因為服務器宕機而無法訪問文件資源驯绎。
2完慧,工作流程詳解
文件上傳:Client會先向Tracker詢問存儲地址,Tracker查詢到存儲地址后返回給Client剩失,Client拿著地址直接和對應的Storage通訊屈尼,將文件上傳至改Storage。
文件下載:同樣赴叹,Client會向Tracker詢問地址,并帶上要查詢的文件名和組名指蚜,Tracker查詢后會將地址返回給Client乞巧,Client拿著地址和指定Storage通訊并下載文件。
03【掌握】Linux下的安裝部署fastdfs
安裝fastDFS需要分別安裝fastdfs-nginx-module摊鸡,fastdfs绽媒,nginx,libfastcommon
1免猾,安裝gcc(編譯時需要)
yum install -y gcc gcc-c++
2是辕,安裝libevent(運行時需要)
yum -y install libevent
3,安裝創(chuàng)建目錄上傳所有文件
mkdir -p /fileservice/fast
cd /fileservice/fast
4猎提,安裝libfastcommon
進入fast目錄:cd /fileservice/fast
解壓文件:tar -zxvf libfastcommon-1.0.35.tar.gz
進入libfast文件目錄:cd libfastcommon-1.0.35
執(zhí)行編譯:./make.sh
安裝:./make.sh install
安裝完成之后
5获三、安裝fastdfs
5.1,下載?
https://sourceforge.net/projects/fastdfs/files/
網(wǎng)官下載很慢锨苏,看我準備的安裝文件
5.2疙教,安裝相關依賴庫
yum install perl
yum install pcre
yum install pcre-devel
yum install zlib
yum install zlib-devel
yum install openssl
yum install openssl-devel
5.3,安裝fastdfs
進入fast目錄:cd /fileservice/fast
解壓文件:tar -zxvf fastdfs-5.11.tar.gz
進入解壓后的目錄:cd fastdfs-5.11
執(zhí)行編譯:./make.sh
安裝:./make.sh install
成功之后
5.4伞租,查看tracker和storage的可執(zhí)行腳本(后面有用)
ll /etc/init.d/ | grep fdfs
5.5贞谓,準備配置文件 ?默認在/etc/fdfs/下面
cd /etc/fdfs/
先把配置文件名中的sample去了。[可以復制一份]
cp client.conf.sample client.conf
cp storage.conf.sample storage.conf
cp storage_ids.conf.sample storage_ids.conf
cp tracker.conf.sample tracker.conf
然后修改tracker的存放數(shù)據(jù)和日志的目錄葵诈。
mkdir -p /home/leige/fastdfs/tracker
6裸弦、配置和啟動tracker
6.1,切換目錄到: /etc/fdfs/ 目錄下作喘;
cd /etc/fdfs/
6.2理疙,修改tracker.conf
?vim tracker.conf
base_path=/home/yuqing/fastdfs 改為: base_path=/home/leige/fastdfs/tracker
6.3,啟動tracker泞坦,運行如下命令:
service fdfs_trackerd? start
注意:在/home/leige/fastdfs/tracker 目錄下生成兩個目錄沪斟,一個是數(shù)據(jù),一個是日志;
7主之、配置和啟動storage
?由于上面已經(jīng)安裝過FastDFS择吊,這里只需要配置storage就好了;
7.1槽奕,切換目錄到: /etc/fdfs/ 目錄下几睛;
cd /etc/fdfs/
7.2,修改storage.conf ; vim storage.conf
group_name=group1 #配置組名
base_path=/home/yuqing/fastdfs 改為: base_path=/home/leige/fastdfs/storage
[if !vml]
[endif]
#store存放文件的位置(store_path)
store_path0=/home/yuqing/fastdfs 改為:store_path0=/home/leige/fastdfs/storage
#如果有多個掛載磁盤則定義多個store_path粤攒,如下
#store_path1=.....
#store_path2=......
#配置tracker服務器:IP
tracker_server=117.48.203.125:22122
#如果有多個則配置多個tracker
#tracker_server=117.48.203.126:22122
7.3所森,創(chuàng)建/home/leige/fastdfs/storage 目錄
mkdir -p /home/leige/fastdfs/storage
7.4,啟動storage夯接, 運行命令如下:
service fdfs_storaged start
啟動完成后進入 /home/leige/fastdfs/storage/data 目錄下焕济,顯示目錄如下:
8、使用FastDFS自帶工具測試
8.1盔几,切換目錄到 /etc/fdfs/ 目錄下晴弃;
cd /etc/fdfs/cd
8.2,修改client.conf ; vim client.conf逊拍,
修改基本路徑和tracker_server如下:
? 注意:若tracker有多個上鞠,可以配置多個,如下:
#tracker_server=......
#tracker_server=......
8.3芯丧,拷貝一張圖片baobao.png到Centos服務器上的 /root/目錄下芍阎;
8.4,進行測試
運行如下(運行測試程序,讀取/etc/fdfs/client.conf 文件缨恒,上傳/root/目錄下的baobao.png文件)
/usr/bin/fdfs_upload_file /etc/fdfs/client.conf /root/baobao.png
?結果如下谴咸,表示搭建成功;
以上圖中的文件地址:http://117.48.203.125/group1/M00/00/00/wKgAA135BdKAEOs1ADW668UZmDM218.png?對應storage服務器上的/home/leige/fastdfs/storage/data/00/00/wKgAA135BdKAEOs1ADW668UZmDM218.png文件骗露;
由于現(xiàn)在還沒有和nginx整合無法使用http下載寿冕。
9、FastDFS 和nginx整合
9.1 在tracker上安裝 nginx
?在每個tracker上安裝nginx椒袍,的主要目的是做負載均衡及實現(xiàn)高可用驼唱。如果只有一臺tracker可以不配置nginx。
?一個tracker對應多個storage驹暑,通過nginx對storage負載均衡玫恳;
9.2 在storage 上安裝nginx
?(1)上傳fastdfs-nginx-module-1.20.tar.gz 到Centos服務器上;
?(2)解壓fastdfs-nginx-module-1.20.tar.gz 并移動到/usr/local目錄下优俘;
tar -zxvf? fastdfs-nginx-module-1.20.tar.gz?? 解壓
(3)切換目錄到:fastdfs-nginx-module-1.20/src 目錄下
cd fastdfs-nginx-module-1.20/src
(4)修改config文件京办,將文件中的所有 /usr/local/ 路徑改為/usr/
修改之后
(5)將fastdfs-nginx-module/src下的mod_fastdfs.conf拷貝至/etc/fdfs/下
cp mod_fastdfs.conf /etc/fdfs/
(6)并修改/etc/fdfs/mod_fastdfs.conf 的內(nèi)容;
vi /etc/fdfs/mod_fastdfs.conf
tracker_server=117.48.203.125:22122
#tracker_server=192.168.172.20:22122 #(多個tracker配置多行)
url_have_group_name=true #url中包含group名稱
store_path0=/home/fdfs_storage #指定文件存儲路徑(上面配置的store路徑)
9.3 進入之前解壓的fastdfs目錄下帆焕,把http.conf惭婿、mime.conf移動至/etc/fdfs
cp http.conf mime.types /etc/fdfs/
10不恭, Nginx的安裝
10.1,上傳 nginx-1.15.2.tar.gz 到Centos服務器上财饥;
10.2换吧,解壓nginx-1.15.2.tar.gz?
cd /fileservice/fast/
tar -zxvf nginx-1.15.2.tar.gz
10.3,進入nginx解壓的目錄下
cd nginx-1.15.2/
10.4钥星,加入模塊命令配置
./configure --prefix=/opt/nginx --sbin-path=/usr/bin/nginx --add-module=/fileservice/fast/fastdfs-nginx-module-1.20/src
10.5沾瓦,編譯并安裝
make&&make install
10.6,修改nginx配置
cd /opt/nginx/conf
vim nginx.conf
10.7谦炒,啟動nginx
cd /usr/bin/
./nginx?? #啟動
11贯莺、在瀏覽器中訪問上傳到fastDFS的圖片
因為Centos系統(tǒng)有防火墻,需要先關閉掉宁改,才可以在瀏覽器中訪問缕探;
(1)CentOS 7.0默認使用的是firewall作為防火墻;若沒有啟用iptables 作為防火墻还蹲,則使用以下方式關閉防火墻:
systemctl stop firewalld.service #停止firewall
systemctl disable firewalld.service #禁止firewall開機啟動
firewall-cmd --state #查看默認防火墻狀態(tài)(關閉后顯示notrunning爹耗,開啟后顯示running)
(2)若已經(jīng)啟用iptables作為防火墻,則使用以下方式關閉:
service iptables stop #臨時關閉防火墻
chkconfig iptables off #永久關閉防火墻
?(3)在谷歌瀏覽器中訪問剛才上傳的圖片:
剛才上傳的圖片地址為:http://117.48.203.125/group1/M00/00/00/wKgAA135BdKAEOs1ADW668UZmDM218.png
寶寶鎮(zhèn)樓秽誊,可愛不
03【掌握】使用Docker搭建
1鲸沮,拉取鏡像并啟動
dockerrun-d--restart=always--privileged=true--net=host--name=fastdfs-eIP=192.168.149.128-eWEB_PORT=80-v${HOME}/fastdfs:/var/local/fdfsregistry.cn-beijing.aliyuncs.com/tianzuo/fastdfs
?
其中-v ${HOME}/fastdfs:/var/local/fdfs是指:將${HOME}/fastdfs這個目錄掛載到容器里的/var/local/fdfs這個目錄里琳骡。所以上傳的文件將被持久化到${HOME}/fastdfs/storage/data里锅论,IP 后面是自己的服務器公網(wǎng)ip或者虛擬機ip,-e
WEB_PORT=80 指定nginx端口
2楣号,測試上傳
//進入容器
dockerexec-itfastdfs/bin/bash
//創(chuàng)建文件
echo"Hello FastDFS!">index.html
//測試文件上傳
fdfs_test/etc/fdfs/client.confuploadindex.html
3最易,配置端口
4,測試訪問
http://192.168.149.128/group1/M00/00/00/wKiVgF3dfV6ANGAyAAAADwL5vO455_big.html
04【掌握】使用Java代碼 測試上傳
創(chuàng)建項目
修改pom.xml
創(chuàng)建fdfs_client.conf
創(chuàng)建測試類進行文件上傳
測試
05【掌握】使用springboot完成文件上傳1
創(chuàng)建項目
修改pom.xml
創(chuàng)建yml
創(chuàng)建UploadService
package com.sxt.utils;
import org.apache.commons.lang3.StringUtils;
import org.csource.fastdfs.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import java.util.HashMap;
import java.util.Map;
/**
?*@program: fastdfs-demo
?*@author:?
?*@create: 2020-01-03 10:05
?**/
@Component
public class UploadService {
@Value("${fastdfs.tracker_servers}")
private String tracker_servers;
@Value("${fastdfs.connect_timeout_in_seconds}")
private int connect_timeout;
@Value("${fastdfs.network_timeout_in_seconds}")
private int network_timeout;
@Value("${fastdfs.charset}")
private String charset;
public Map upload(MultipartFile? multipartFile) {
if (multipartFile == null) {
throw new RuntimeException("文件不能為空");
??????? }
// 上傳至fastDFS, 返回文件id
??????? String fileId = this.fdfsUpload(multipartFile);
if (StringUtils.isEmpty(fileId)) {
??????????? System.
out.println("上傳失敗");
throw?
? newRuntimeException("上傳失敗");
??????? }
??????? Map map=
new HashMap<>();
??????? map.put(
"code",200);
??????? map.put(
"msg","上傳成功");
??????? map.put(
"fileId",fileId);
return map;
??? }
/**
???? *上傳至fastDFS
???? *@param multipartFile
???? *@return 文件id
???? */
??? private String fdfsUpload(MultipartFile? multipartFile) {
// 1. 初始化fastDFS的環(huán)境
??????? initFdfsConfig();
// 2. 獲取trackerClient服務
??????? TrackerClient trackerClient = new TrackerClient();
try {
??????????? TrackerServer trackerServer? = trackerClient.getConnection();
// 3. 獲取storage服務
??????????? StorageServer storeStorage =? trackerClient.getStoreStorage(trackerServer);
// 4. 獲取storageClient
??????????? StorageClient1 storageClient1 = new StorageClient1(trackerServer,? storeStorage);
// 5. 上傳文件 (文件字節(jié), 文件擴展名, )
??????????? // 5.1獲取文件擴展名
??????????? String originalFilename =? multipartFile.getOriginalFilename();
??????????? String extName =? originalFilename.substring(originalFilename.lastIndexOf(
".") + 1);
// 5.2 上傳
??????????? String fileId =
? storageClient1.upload_file1(multipartFile.getBytes(), extName, null);
return fileId;
??????? }
catch (Exception e) {
??????????? System.
out.println(e);
return null;
??????? }
??? }
/**
???? *初始化fastDFS的環(huán)境
???? */
??? private void initFdfsConfig() {
try {
??????????? ClientGlobal.initByTrackers(
tracker_servers);
??????????? ClientGlobal.setG_connect_timeout(
connect_timeout);
??????????? ClientGlobal.setG_network_timeout(
network_timeout);
??????????? ClientGlobal.setG_charset(
charset);
??????? }
catch (Exception e) {
??????????? System.
out.println(e);
??????? }
??? }
}
創(chuàng)建UploadController
/**
?*@program: fastdfs-demo
?*@author:?
?*@create: 2020-01-03 10:08
?**/
@RestController
@RequestMapping
("upload")
public class UploadController {
@Autowired
private UploadService uploadService;
/**
???? *作上傳
???? */
??? @RequestMapping("doUpload")
public Map? doUpload(MultipartFile mf){
??????? System.
out.println(mf.getOriginalFilename());
??????? Map map =
uploadService.upload(mf);
return map;
??? }
}
創(chuàng)建static/index.html
測試
06【掌握】使用springboot完成文件上傳2
????
修改pom.xml
創(chuàng)建配置類UploadProperties
/**
?*@program: fastdfs-demo
?*@author:?
?*@create: 2020-01-03 10:44
?**/
@ConfigurationProperties(prefix = "upload")
@Data
public class UploadProperties {
private String baseUrl;
private List<String> allowTypes;
}
修改yml文件
創(chuàng)建UploadService
package com.sxt.utils;
import com.github.tobato.fastdfs.domain.fdfs.StorePath;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import com.sxt.config.UploadProperties;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.IOException;
/**
?*@program: fastdfs-demo
?*@author: 雷哥
?*@create: 2020-01-03 10:48
?**/
@Component
@EnableConfigurationProperties
(UploadProperties.class)
public class UploadService {
private Log log= LogFactory.getLog(UploadService.class);
@Autowired
private FastFileStorageClient storageClient;
@Autowired
private UploadProperties prop;
public String uploadImage(MultipartFile file) {
// 1炫狱、校驗文件類型
??????? String contentType =? file.getContentType();
if (!prop.getAllowTypes().contains(contentType))? {
throw new RuntimeException("文件類型不支持");
??????? }
// 2藻懒、校驗文件內(nèi)容
??????? try {
??????????? BufferedImage image =? ImageIO.read(file.getInputStream());
if (image == null || image.getWidth() == 0 || image.getHeight() == 0) {
throw new RuntimeException("上傳文件有問題");
??????????? }
??????? }
catch (IOException e) {
log.error("校驗文件內(nèi)容失敗....{}", e);
throw new RuntimeException("校驗文件內(nèi)容失敗"+e.getMessage());
??????? }
try {
// 3、上傳到FastDFS
??????????? // 3.1视译、獲取擴展名
??????????? String extension = StringUtils.substringAfterLast(file.getOriginalFilename(),".");
// 3.2嬉荆、上傳
??????????? StorePath storePath = storageClient.uploadFile(file.getInputStream(),
? file.getSize(), extension, null);
// 返回路徑
??????????? return prop.getBaseUrl() + storePath.getFullPath();
??????? }
catch (IOException e) {
log.error("【文件上傳】上傳文件失敗酷含!....{}", e);
throw?
? newRuntimeException("【文件上傳】上傳文件失敱稍纭!"+e.getMessage());
??????? }
??? }
}
創(chuàng)建UploadController
創(chuàng)建index.html測試