FastDFS是一個開源的輕量級分布式文件系統,它對文件進行管理,功能包括:文件存儲、文件同步、文件訪問(文件上傳、文件下載)等,解決了大容量存儲和負載均衡的問題。特別適合以文件為載體的在線服務,如相冊網站、視頻網站等等。
FastDFS為互聯網量身定制,充分考慮了冗余備份、負載均衡、線性擴容等機制,并注重高可用、高性能等指標,使用FastDFS很容易搭建一套高性能的文件服務器集群提供文件上傳、下載等服務。
FastDFS服務端有兩個角色:跟蹤器(tracker)和存儲節點(storage)。跟蹤器主要做調度工作,在訪問上起負載均衡的作用。
存儲節點存儲文件,完成文件管理的所有功能:就是這樣的存儲、同步和提供存取接口,FastDFS同時對文件的metadata進行管理。所謂文件的meta data就是文件的相關屬性,以鍵值對(key value)方式表示,如:width=1024,其中的key為width,value為1024。文件metadata是文件屬性列表,可以包含多個鍵值對。
跟蹤器和存儲節點都可以由一臺或多臺服務器構成。跟蹤器和存儲節點中的服務器均可以隨時增加或下線而不會影響線上服務。其中跟蹤器中的所有服務器都是對等的,可以根據服務器的壓力情況隨時增加或減少。
為了支持大容量,存儲節點(服務器)采用了分卷(或分組)的組織方式。存儲系統由一個或多個卷組成,卷與卷之間的文件是相互獨立的,所有卷的文件容量累加就是整個存儲系統中的文件容量。一個卷可以由一臺或多臺存儲服務器組成,一個卷下的存儲服務器中的文件都是相同的,卷中的多臺存儲服務器起到了冗余備份和負載均衡的作用。
在卷中增加服務器時,同步已有的文件由系統自動完成,同步完成后,系統自動將新增服務器切換到線上提供服務。
當存儲空間不足或即將耗盡時,可以動態添加卷。只需要增加一臺或多臺服務器,并將它們配置為一個新的卷,這樣就擴大了存儲系統的容量。
FastDFS中的文件標識分為兩個部分:卷名和文件名,二者缺一不可。
自行百度,重點介紹docker安裝方式
docker pull delron/fastdfs
docker run -dti --network=host --name tracker -v /var/fdfs/tracker:/var/fdfs -v /etc/localtime:/etc/localtime delron/fastdfs tracker
TRACKER_SERVER=本機的ip地址:22122 ,本機ip地址不要使用127.0.0.1
docker run -dti --network=host --name storage -e TRACKER_SERVER=192.168.157.133:22122 -v /var/fdfs/storage:/var/fdfs -v /etc/localtime:/etc/localtime delron/fastdfs storage
#進入容器
docker exec -it storage bash
#進入目錄
cd /etc/fdfs/
#編輯文件
vi storage.conf
默認端口是8888,也可以不進行更改。
cd /usr/local/nginx/conf
vi nginx.conf
docker stop storage
docker start storage
如果重啟后無法啟動的會,可能是報下面錯誤了,手動創建 vi /var/fdfs/logs/storaged.log 文件即可 tail: cannot open '/var/fdfs/logs/storaged.log' for reading: No such file or directory
7.1 進入storage容器,進入/var/fdfs目錄
docker exec -it storage bash
cd /var/fdfs
echo hello 這是我的第一個測試文件,大家覺得不錯關注下吧>a.txt
/usr/bin/fdfs_upload_file /etc/fdfs/client.conf a.txt
瀏覽器訪問 http://ip:8888/group1/M00/00/00/wKgcgF-_Le6AS4LvAAAATzab9Do068.txt 端口根據你在starage里面設置的要保持一致,訪問之前關閉防火墻或者自己單獨開放端口
firewall-cmd --zone=public --permanent --add-port=8888/tcp
firewall-cmd --zone=public --permanent --add-port=22122/tcp
firewall-cmd --zone=public --permanent --add-port=23000/tcp
重啟防火墻
systemctl restart firewalld
設置容器隨docker啟動而啟動(由于docker是開機啟動的,所以容器也會隨之啟動)
docker update --restart=always tracker
docker update --restart=always storage
由于服務器防火墻的原因,導致指定的端口未暴露會出現如下問題: 1、瀏覽器訪問fastdfs上傳的資源訪問不到http://192.168.157.133:8888/group1/M00/00/00/wKidhWF1ABqAYqUwAAAATzab9Do485.txt 2、fastdfs-client客戶端連接fastdfs服務出錯 會報下面錯誤:
fastDFS報錯:Unable to borrow buffer from pool
解決方案(centos7):
由于FastDFS安裝在Linux中 22122端口被管控,windows系統訪問時需要先關閉防火墻或者開放該端口 1.查看防火墻狀態:
firewall-cmd --state
2.關閉并禁用防火墻,可能需要重啟服務器
sudo systemctl stop firewalld.service sudo systemctl disable firewalld.service
3.查看防火墻狀態:
firewall-cmd --state not running
firewall-cmd --zone=public --permanent --add-port=8888/tcp
firewall-cmd --zone=public --permanent --add-port=22122/tcp
firewall-cmd --zone=public --permanent --add-port=23000/tcp
#重啟防火墻
systemctl restart firewalld
然后重啟fastdfs服務(tracker、storage、nginx)
Controller層
package com.xjt.fdfs.controller;
import cn.hutool.core.io.FileUtil;
import com.github.tobato.fastdfs.domain.fdfs.StorePath;
import com.github.tobato.fastdfs.domain.proto.storage.DownloadByteArray;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.apache.commons.io.FilenameUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Api(tags="FastDFS測試")
@RestController
@RequestMapping("/api/fastdfs")
public class FileController {
@Autowired
private FastFileStorageClient storageClient;
public final static String server_host="http://192.168.157.134:8888/";
@ResponseBody
@ApiOperation(value="上傳文件",httpMethod="POST")
@PostMapping("/upload")
public String uploadFile(@ApiParam("文件") MultipartFile file) throws IOException {
StorePath storePath=storageClient.uploadFile(file.getInputStream(),
file.getSize(), FilenameUtils.getExtension(file.getOriginalFilename()),null);
String filepath=server_host + storePath.getFullPath();
return "文件上傳成功 地址為:"+filepath;
}
@ResponseBody
@ApiOperation(value="刪除文件",httpMethod="POST")
@PostMapping("/delete")
public void deleteFile(String fileUrl){
if (StringUtils.isEmpty(fileUrl)) {
return;
}
try {
StorePath storePath=StorePath.parseFromUrl(fileUrl);
storageClient.deleteFile(storePath.getGroup(), storePath.getPath());
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
@ResponseBody
@ApiOperation(value="下載文件",httpMethod="POST")
@PostMapping("/download")
public void downloadFile(HttpServletRequest request, HttpServletResponse response,String fileUrl){
try {
StorePath storePath=StorePath.parseFromUrl(fileUrl);
System.out.println(storePath.getGroup());
System.out.println(storePath.getPath());
byte[] bytes=storageClient.downloadFile(storePath.getGroup(), storePath.getPath(), new DownloadByteArray());
response.getOutputStream().write(bytes);
FileUtil.writeBytes(bytes,FileUtil.file(storePath.getPath()));
} catch (Exception e) {
return;
}
}
}
配置文件application.properties
在后臺測試過程中,我們有時候需要上傳文件到某個文件服務器,在實現一定的測試步驟。我們可以通過前端腳本來實現,但是我們如果不需要測試前端頁面,只需要測試后臺服務。
是否可以通過Python腳本來實現這樣的操作?
這里用FastDFS文件服務器來舉個例子。
希望能幫助大家拓展思路。也希望大家在自己的時間工作中,多用代碼來解決一些具體的問題,不斷的提高自己的代碼水平和測試能力。
代碼大概長這樣,額 ……就是這樣
上面的圖給出了代碼,但是有幾個注意點
1.你得有一個專門來處理fdfs文件服務器的客戶端模塊,就是這個fdfs_client,為了方便大家使用我已打包上傳的pypi。
python3安裝命令
pip install fast-client
2.配置文件,你應該可以看到我引入了一個BASE_DIR來簡化配置文件的路徑
這里的.conf配置文件大概長這樣
# charset=UTF-8
# http.anti_steal_token=no
# http.secret_key=FastDFS1234567890
# connect timeout in seconds
# default value is 30s
connect_timeout=30
# network timeout in seconds
# default value is 30s
network_timeout=60
# the base path to store log files
# you can create a new dir and set this base_path
base_path=D:\fdfs
# tracker_server can ocur more than once, and tracker_server format is
# "host:port", host can be hostname or ip address
tracker_server=*.*.*.*:22122
#standard log level as syslog, case insensitive, value list:
### emerg for emergency
### alert
### crit for critical
### error
### warn for warning
### notice
### info
### debug
log_level=info
# if use connection pool
# default value is false
# since V4.05
use_connection_pool=false
# connections whose the idle time exceeds this time will be closed
# unit: second
# default value is 3600
# since V4.05
connection_pool_max_idle_time=3600
# if load FastDFS parameters from tracker server
# since V4.05
# default value is false
load_fdfs_parameters_from_tracker=false
# if use storage ID instead of IP address
# same as tracker.conf
# valid only when load_fdfs_parameters_from_tracker is false
# default value is false
# since V4.05
use_storage_id=false
# specify storage ids filename, can use relative or absolute path
# same as tracker.conf
# valid only when load_fdfs_parameters_from_tracker is false
# since V4.05
storage_ids_filename=storage_ids.conf
#HTTP settings
http.tracker_server_port=18080
#use "#include" directive to include HTTP other settiongs
##include http.conf
3.具體的代碼中,我使用了兩個不同的fdfs文件服務器,你可以根據自己的需求改寫代碼,已實現通過參數來控制上傳到哪個服務器。
我們運行一下測試,來看一下實際運行的效果
上傳成功后文件服務器會有響應
上圖我們可以看到fdfs文件服務器已經響應給了我們上傳文件成功后,文件在服務器上的信息,我們可以通過這些信息來直接訪問文件。
比如我們上傳的是一張圖片,通過瀏覽器url就可以直接訪問圖片。
注意URL前面的地址根據自己的實際情況更改
到此我們就實現了fdfs服務器的文件上傳。