FastDFS是用c語言編寫的一款開源的分佈式文件系統。FastDFS爲互聯網量身定製,充分考慮了冗餘備份、負載均衡、線性擴容等機制,並注重高可用、高性能等指標,使用FastDFS很容易搭建一套高性能的文件服務器集羣提供文件上傳、下載等服務。FastDFS是爲互聯網應用量身定作的一套分佈式文件存儲系統,很是適合用來存儲用戶圖片、視頻、文檔等文件。html
FastDFS服務端有兩個角色:跟蹤器(tracker)和存儲節點(storage)。跟蹤器主要作調度工做,在訪問上起負載均衡的做用。前端
存儲節點存儲文件,完成文件管理的全部功能:存儲、同步和提供存取接口,FastDFS同時對文件的meta data進行管理。所謂文件的meta data就是文件的相關屬性,以鍵值對(key value pair)方式表示,如:width=1024,其中的key爲width,value爲1024。文件meta data是文件屬性列表,能夠包含多個鍵值對。java
FastDFS架構包括 Tracker server和Storage server。客戶端請求Tracker server進行文件上傳、下載,經過Trackerserver調度最終由Storage server完成文件上傳和下載。nginx
Trackerserver做用是負載均衡和調度,經過Trackerserver在文件上傳時能夠根據一些策略找到Storageserver提供文件上傳服務。能夠將tracker稱爲追蹤服務器或調度服務器。
Storageserver做用是文件存儲,客戶端上傳的文件最終存儲在Storage服務器上,Storage server沒有實現本身的文件系統而是利用操做系統 的文件系統來管理文件。能夠將storage稱爲存儲服務器。c++
跟蹤器和存儲節點均可以由一臺或多臺服務器構成。跟蹤器和存儲節點中的服務器都可以隨時增長或下線而不會影響線上服務。其中跟蹤器中的全部服務器都是對等的,能夠根據服務器的壓力狀況隨時增長或減小。git
爲了支持大容量,存儲節點(服務器)採用了分卷(或分組)的組織方式。存儲系統由一個或多個卷組成,卷與卷之間的文件是相互獨立的,全部卷 的文件容量累加就是整個存儲系統中的文件容量。一個卷能夠由一臺或多臺存儲服務器組成,一個卷下的存儲服務器中的文件都是相同的,卷中的多臺存儲服務器起到了冗餘備份和負載均衡的做用。github
在卷中增長服務器時,同步已有的文件由系統自動完成,同步完成後,系統自動將新增服務器切換到線上提供服務。web
當存儲空間不足或即將耗盡時,能夠動態添加捲。只須要增長一臺或多臺服務器,並將它們配置爲一個新的卷,這樣就擴大了存儲系統的容量。正則表達式
FastDFS中的文件標識分爲兩個部分:卷名和文件名,者缺一不可。spring
FastDFS集羣中的Tracker server能夠有多臺,Trackerserver之間是相互平等關係同時提供服務,Trackerserver不存在單點故障。客戶端請求Trackerserver採用輪詢方式,若是請求的tracker沒法提供服務則換另外一個tracker。
Storage集羣採用了分組存儲方式。storage集羣由一個或多個組構成,集羣存儲總容量爲集羣中全部組的存儲容量之和。一個組由一臺或多臺存儲服務器組成,組內的Storage server之間是平等關係,不一樣組的Storageserver之間不會相互通訊,同組內的Storageserver之間會相互鏈接進行文件同步,從而保證同組內每一個storage上的文件徹底一致的。一個組的存儲容量爲該組內存儲服務器容量最小的那個,因而可知組內存儲服務器的軟硬件配置最好是一致的。
採用分組存儲方式的好處是靈活、可控性較強。好比上傳文件時,能夠由客戶端直接指定上傳到的組也能夠由tracker進行調度選擇。一個分組的存儲服務器訪問壓力較大時,能夠在該組增長存儲服務器來擴充服務能力(縱向擴容)。當系統容量不足時,能夠增長組來擴充存儲容量(橫向擴容)。
Storage server會鏈接集羣中全部的Tracker server,定時向他們報告本身的狀態,包括磁盤剩餘空間、文件同步情況、文件上傳下載次數等統計信息。
tracker根據請求的文件路徑即文件ID 來快速定義文件。
好比請求下邊的文件:
# github地址:https://github.com/happyfish100 wget https://github.com/happyfish100/fastdfs/archive/V5.11.tar.gz wget https://github.com/happyfish100/libfastcommon/archive/V1.0.39.tar.gz wget https://github.com/happyfish100/fastdfs-nginx-module/archive/V1.20.tar.gz wget https://github.com/happyfish100/fastdfs-client-java/archive/master.zip # openresty(nginx+lua) wget https://openresty.org/download/openresty-1.15.8.1.tar.gz
FastDFS是C語言開發,安裝FastDFS須要先將官網下載的源碼進行編譯,編譯依賴gcc環境,若是沒有gcc環境,須要安裝gcc
[sandu@bogon ~]$ sudo yum install -y gcc gcc-c++ [sandu@bogon ~]$ sudo yum -y groupinstall 'Development Tools' [sandu@bogon ~]$ sudo yum -y install wget
若安裝了桌面圖形界面,就不須要安裝;FastDFS依賴libevent庫,須要安裝:
[sandu@bogon ~]$ sudo yum -y install libevent
libfastcommon是FastDFS官方提供的,libfastcommon包含了FastDFS運行所須要的一些基礎庫。
github地址:https://github.com/happyfish100/libfastcommon/
[sandu@bogon ~]$ sudo wget https://github.com/happyfish100/libfastcommon/archive/master.zip [sandu@bogon ~]$ sudo unzip master.zip [sandu@bogon ~]$ sudo cd libfastcommon-master [sandu@bogon ~]$ sudo ./make.sh [sandu@bogon ~]$ sudo ./make.sh install # libfastcommon安裝好後會在/usr/lib64 目錄下生成 libfastcommon.so 庫文件 [sandu@bogon fdfs]$ ll /usr/lib64 | grep fdfs -rwxr-xr-x. 1 root root 316136 Jul 31 09:53 libfdfsclient.so # 因爲FastDFS程序引用/usr/lib目錄因此須要將/usr/lib64下的libfdfsclient.so拷貝至/usr/lib下,如有的話則不用再操做了。 [sandu@bogon src]$ sudo cp /usr/lib64/libfdfsclient.so /usr/lib/ [sandu@bogon fdfs]$ ll /usr/lib | grep fdfs -rwxr-xr-x. 1 root root 316136 Jul 31 09:53 libfdfsclient.so
官方github地址:https://github.com/happyfish100/fastdfs
[sandu@bogon ~]$ sudo wget https://github.com/happyfish100/fastdfs/archive/V5.11.tar.gz [sandu@bogon ~]$ sudo tar -zxv -f V5.11.tar.gz [sandu@bogon ~]$ sudo cd fastdfs-5.11/ [sandu@bogon ~]$ sudo ./make.sh [sandu@bogon ~]$ sudo ./make.sh install
若在[sandu@bogon ~]$ sudo ./make.sh
這一步報錯以下:
cc -Wall -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE -g -O -DDEBUG_FLAG -c -o ../common/fdfs_global.o ../common/fdfs_global.c -I../common -I/usr/include/fastcommon ../common/fdfs_global.c:20:20: fatal error: logger.h: No such file or directory #include "logger.h" ^ compilation terminated. make: *** [../common/fdfs_global.o] Error 1
則是由於須要先安裝libfastcommon
安裝成功將安裝目錄下的conf下的倆文件拷貝到/etc/fdfs/下
[sandu@bogon conf]$ sudo cp /usr/local/src/fastdfs-5.11/conf/http.conf /etc/fdfs/ [sandu@bogon conf]$ sudo cp /usr/local/src/fastdfs-5.11/conf/mime.types /etc/fdfs/ # 其他的配置文件在/etc/fdfs/目錄下有sample文件,用這個修改就好了
安裝以後sample配置文件在目錄/etc/fdfs下,複製一份並重命名做爲配置文件使用
[sandu@bogon ~]$ sudo cp tracker.conf.sample tracker.conf
修改配置文件: /etc/fdfs/tracker.conf,修改路徑到/opt/fdfs_data目錄。
[sandu@bogon fdfs]$ sudo mkdir -p /opt/{fastdfs,fdfs_storage} [sandu@bogon fdfs]$ sudo vim tracker.conf # the base path to store data and log files #base_path=/home/yuqing/fastdfs base_path=/opt/fastdfs # HTTP port on this tracker server #http.server_port=8080 http.server_port=80
啓動,查看端口號
[sandu@bogon ~]$ sudo /usr/bin/fdfs_trackerd /etc/fdfs/tracker.conf start [sandu@bogon fdfs_data]$ ps -ef | grep fdfs root 2397 1 0 10:23 ? 00:00:00 /usr/bin/fdfs_trackerd /etc/fdfs/tracker.conf start [sandu@bogon fdfs]$ sudo netstat -tulnp (yum install net-tools) Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 0.0.0.0:22122 0.0.0.0:* LISTEN 2313/fdfs_trackerd ...... # 命令行選項 Usage: /usr/bin/fdfs_trackerd <config_file> [start | stop | restart]
注意:在/opt/fdfs_data目錄下生成兩個目錄, 一個是數據,一個是日誌;
設置開機自啓動,新增以下一行內容
[sandu@bogon ~]$ sudo vim /etc/rc.d/rc.local /usr/bin/fdfs_trackerd /etc/fdfs/tracker.conf restart
安裝以後sample配置文件在目錄/etc/fdfs下,複製一份並重命名做爲配置文件使用
修改配置文件: /etc/fdfs/storage.conf,修改路徑到/data/fdfs目錄,同時配置tracker_server地址。
[sandu@bogon ~]$ sudo cp storage.conf.sample storage.conf [sandu@bogon fdfs]$ sudo vim storage.conf # the base path to store data and log files #base_path=/home/yuqing/fastdfs base_path=/opt/fastdfs # store_path#, based 0, if store_path0 not exists, it's value is base_path # the paths must be exist #store_path0=/home/yuqing/fastdfs store_path0=/opt/fdfs_storage #store_path1=/home/yuqing/fastdfs2 #若是有多個掛載磁盤則定義多個store_path,以下 #store_path1=..... #store_path2=...... # tracker_server can ocur more than once, and tracker_server format is # "host:port", host can be hostname or ip address tracker_server=172.21.168.119:22122 # ip使用127.0.0.1則服務啓動不了 # the port of the web server on this storage server #http.server_port=8888 http.server_port=88
/opt/fdfs_storage/data下有256個1級目錄,每級目錄下又有256個2級子目錄,總共65536個文件,新寫的文件會以hash的方式被路由到其中某個子目錄下,而後將文件數據直接做爲一個本地文件存儲到該目錄中。
啓動,查看端口號
[sandu@bogon fdfs]$ sudo /usr/bin/fdfs_storaged /etc/fdfs/storage.conf start [sandu@bogon fdfs]$ sudo ps -ef | grep fdfs root 2397 1 0 10:23 ? 00:00:00 /usr/bin/fdfs_trackerd /etc/fdfs/tracker.conf start root 16694 1 99 10:51 ? 00:00:02 /usr/bin/fdfs_storaged /etc/fdfs/storage.conf start [sandu@bogon fdfs]$ sudo netstat -tulnp Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 0.0.0.0:22122 0.0.0.0:* LISTEN 2397/fdfs_trackerd tcp 0 0 0.0.0.0:23000 0.0.0.0:* LISTEN 16694/fdfs_storaged ...... # 命令行選項 Usage: /usr/bin/fdfs_trackerd <config_file> [start | stop | restart]
設置開機自啓動,新增以下一行內容
[sandu@bogon ~]$ sudo vim /etc/rc.d/rc.local /usr/bin/fdfs_storaged /etc/fdfs/storage.conf restart
要肯定一下,storage是否註冊到了tracker中去
成功後能夠看到: ip_addr = 172.21.168.119 (bogon) ACTIVE
[sandu@bogon src]$ sudo /usr/bin/fdfs_monitor /etc/fdfs/storage.conf [2019-07-31 15:37:00] DEBUG - base_path=/opt/fastdfs, connect_timeout=30, network_timeout=60, tracker_server_count=1, anti_steal_token=0, anti_steal_secret_key length=0, use_connection_pool=0, g_connection_pool_max_idle_time=3600s, use_storage_id=0, storage server id count: 0 server_count=1, server_index=0 tracker server is 172.21.168.119:22122 group count: 1 Group 1: group name = group1 disk total space = 48096 MB disk free space = 45996 MB trunk free space = 0 MB storage server count = 1 active server count = 1 storage server port = 23000 storage HTTP port = 88 store path count = 1 subdir count per path = 256 current write server index = 0 current trunk file id = 0 Storage 1: id = 172.21.168.119 ip_addr = 172.21.168.119 (bogon) ACTIVE http domain = version = 5.11 join time = 2019-07-31 14:33:43 up time = 2019-07-31 14:33:43 total storage = 48096 MB free storage = 45996 MB upload priority = 10 store_path_count = 1 subdir_count_per_path = 256 storage_port = 23000 storage_http_port = 88 current_write_path = 0 source storage id = if_trunk_server = 0 connection.alloc_count = 256 connection.current_count = 0 connection.max_count = 2 total_upload_count = 2 success_upload_count = 2 total_append_count = 0 success_append_count = 0 total_modify_count = 0 success_modify_count = 0 total_truncate_count = 0 success_truncate_count = 0 total_set_meta_count = 2 success_set_meta_count = 2 total_delete_count = 0 success_delete_count = 0 total_download_count = 0 success_download_count = 0 total_get_meta_count = 0 success_get_meta_count = 0 total_create_link_count = 0 success_create_link_count = 0 total_delete_link_count = 0 success_delete_link_count = 0 total_upload_bytes = 465092 success_upload_bytes = 465092 total_append_bytes = 0 success_append_bytes = 0 total_modify_bytes = 0 success_modify_bytes = 0 stotal_download_bytes = 0 success_download_bytes = 0 total_sync_in_bytes = 0 success_sync_in_bytes = 0 total_sync_out_bytes = 0 success_sync_out_bytes = 0 total_file_open_count = 2 success_file_open_count = 2 total_file_read_count = 0 success_file_read_count = 0 total_file_write_count = 2 success_file_write_count = 2 last_heart_beat_time = 2019-07-31 15:36:40 last_source_update = 2019-07-31 14:42:07 last_sync_update = 1970-01-01 08:00:00 last_synced_timestamp = 1970-01-01 08:00:00
切換目錄到 /etc/fdfs/ 目錄下,拷貝一份新的client配置文件
# 客戶端配置文件修改,主要用來本地測試使用的 [sandu@bogon fdfs]$ sudo cd /etc/fdfs [sandu@bogon fdfs]$ sudo cp client.conf.sample client.conf [sandu@bogon fdfs]$ sudo vim client.conf # the base path to store log files #base_path=/home/yuqing/fastdfs base_path=/opt/fastdfs # tracker_server can ocur more than once, and tracker_server format is # "host:port", host can be hostname or ip address #tracker_server=192.168.0.197:22122 tracker_server=172.21.168.119:22122
上傳一張圖片1.jpg 到Centos服務器上的 /tmp 目錄下,進行測試,命令以下:
[sandu@bogon fdfs]$ sudo /usr/bin/fdfs_test /etc/fdfs/client.conf upload /tmp/1.png This is FastDFS client test program v5.11 Copyright (C) 2008, Happy Fish / YuQing FastDFS may be copied only under the terms of the GNU General Public License V3, which may be found in the FastDFS source kit. Please visit the FastDFS Home Page http://www.csource.org/ for more detail. [2019-07-31 14:42:08] DEBUG - base_path=/opt/fastdfs, connect_timeout=30, network_timeout=60, tracker_server_count=1, anti_steal_token=0, anti_steal_secret_key length=0, use_connection_pool=0, g_connection_pool_max_idle_time=3600s, use_storage_id=0, storage server id count: 0 tracker_query_storage_store_list_without_group: server 1. group_name=, ip_addr=172.21.168.119, port=23000 group_name=group1, ip_addr=172.21.168.119, port=23000 storage_upload_by_filename group_name=group1, remote_filename=M00/00/00/rBWod11BOECAQjjjAAOMYl1argw387.png # 文件路徑 source ip address: 172.21.168.119 file timestamp=2019-07-31 14:42:08 file size=232546 file crc32=1566223884 example file url: http://172.21.168.119/group1/M00/00/00/rBWod11BOECAQjjjAAOMYl1argw387.png storage_upload_slave_by_filename group_name=group1, remote_filename=M00/00/00/rBWod11BOECAQjjjAAOMYl1argw387_big.png source ip address: 172.21.168.119 file timestamp=2019-07-31 14:42:08 file size=232546 file crc32=1566223884 example file url: http://172.21.168.119/group1/M00/00/00/rBWod11BOECAQjjjAAOMYl1argw387_big.png # 文件URL地址
以上圖中的文件地址:http://172.21.168.119/group1/M00/00/00/rBWod11BOECAQjjjAAOMYl1argw387_big.png 對應storage服務器上的/opt/fdfs_storage/data/00/00/wKisFFpBG9eAHaQvAAAWKd1hQR4158_big.jpg文件;
可是查看該目錄,會有四個圖片文件:
[sandu@bogon fdfs]$ tree /opt/fdfs_storage/data/00/00 /opt/fdfs_storage/data/00/00 ├── rBWod11BOECAQjjjAAOMYl1argw387_big.png ├── rBWod11BOECAQjjjAAOMYl1argw387_big.png-m ├── rBWod11BOECAQjjjAAOMYl1argw387.png └── rBWod11BOECAQjjjAAOMYl1argw387.png-m
因爲如今尚未和nginx整合沒法使用http下載。
在每一個tracker上安裝nginx的主要目的是作負載均衡及實現高可用。若是隻有一臺tracker服務器能夠不配置nginx。
一個tracker對應多個storage,經過nginx對storage負載均衡;
FastDFS版本與fastdfs-nginx-module模塊版本對應問題:
FastDFS Version 5.11對應的fastdfs-nginx-module的Version 1.20 FastDFS Version 5.10對應的fastdfs-nginx-module的Version 1.19
github地址:https://github.com/happyfish100/fastdfs-nginx-module
下載fastdfs-nginx-module模塊,並作相應的預處理修改
[sandu@bogon src]$ sudo wget https://github.com/happyfish100/fastdfs-nginx-module/archive/V1.20.tar.gz [sandu@bogon src]$ sudo tar -zxv -f V1.20.tar.gz [sandu@bogon src]$ sudo cd /usr/local/src/fastdfs-nginx-module-1.20/src [sandu@bogon src]$ sudo vim config 把以下這兩行的內容: ngx_module_incs="/usr/local/include" CORE_INCS="$CORE_INCS /usr/local/include" 換成: ngx_module_incs="/usr/include/fastdfs /usr/include/fastcommon/" CORE_INCS="$CORE_INCS /usr/include/fastdfs /usr/include/fastcommon/" # 備註 上面這一步若不操做的話,在編譯安裝openresty的時候會報錯: In file included from /usr/local/src/fastdfs-nginx-module-1.20/src/common.c:26:0, from /usr/local/src/fastdfs-nginx-module-1.20/src/ngx_http_fastdfs_module.c:6: /usr/include/fastdfs/fdfs_define.h:15:27: fatal error: common_define.h: No such file or directory #include "common_define.h" ^ compilation terminated. gmake[2]: *** [objs/addon/src/ngx_http_fastdfs_module.o] Error 1 gmake[2]: Leaving directory `/usr/local/src/openresty-1.15.8.1/build/nginx-1.15.8' gmake[1]: *** [build] Error 2 gmake[1]: Leaving directory `/usr/local/src/openresty-1.15.8.1/build/nginx-1.15.8' gmake: *** [all] Error 2 # 將同目錄下的mod_FastDFS.conf拷貝至/etc/fdfs/下,並作適當修改: [sandu@bogon src]$ sudo cd /usr/local/src/fastdfs-nginx-module-1.20/src [sandu@bogon src]$ sudo cp mod_fastdfs.conf /etc/fdfs/ [sandu@bogon fdfs]$ sudo cp mod_fastdfs.conf mod_fastdfs.conf.simple [sandu@bogon fdfs]$ sudo vim mod_fastdfs.conf # the base path to store log files #base_path=/tmp base_path=/opt/fastdfs # FastDFS tracker_server can ocur more than once, and tracker_server format is # "host:port", host can be hostname or ip address # valid only when load_fdfs_parameters_from_tracker is true tracker_server=172.21.168.119:22122 # if the url / uri including the group name # set to false when uri like /M00/00/00/xxx # set to true when uri like ${group_name}/M00/00/00/xxx, such as group1/M00/xxx # default value is false #url_have_group_name = false url_have_group_name = true # url中包含group名稱 # store_path#, based 0, if store_path0 not exists, it's value is base_path # the paths must be exist # must same as storage.conf #store_path0=/home/yuqing/fastdfs store_path0=/opt/fdfs_storage #store_path1=/home/yuqing/fastdfs1 # 將libfdfsclient.so拷貝至/usr/lib下,這個已經作過了 [sandu@bogon src]$ sudo cp /usr/lib64/libfdfsclient.so /usr/lib/ # 建立nginx/client目錄,做爲nginx使用的臨時目錄;若該目錄不建立的話則使用默認的,同時在下面編譯openresty的參數中也不指定這些目錄 [sandu@bogon src]$ sudo mkdir -p /var/temp/nginx/client
下載安裝openresty:
[sandu@bogon src]$ sudo wget https://openresty.org/download/openresty-1.15.8.1.tar.gz [sandu@bogon src]$ sudo yum -y install pcre-devel openssl openssl-devel [sandu@bogon src]$ sudo cd openresty-1.15.8.1 [sandu@bogon openresty-1.15.8.1]$ sudo ./configure \ --with-luajit \ --with-http_stub_status_module \ --with-http_ssl_module \ --with-http_realip_module \ --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/src/fastdfs-nginx-module-1.20/src nginx path prefix: "/usr/local/openresty/nginx" nginx binary file: "/usr/local/openresty/nginx/sbin/nginx" nginx modules path: "/usr/local/openresty/nginx/modules" nginx configuration prefix: "/usr/local/openresty/nginx/conf" nginx configuration file: "/usr/local/openresty/nginx/conf/nginx.conf" nginx pid file: "/usr/local/openresty/nginx/logs/nginx.pid" nginx error log file: "/usr/local/openresty/nginx/logs/error.log" nginx http access log file: "/usr/local/openresty/nginx/logs/access.log" nginx http client request body temporary files: "/var/temp/nginx/client" nginx http proxy temporary files: "/var/temp/nginx/proxy" nginx http fastcgi temporary files: "/var/temp/nginx/fastcgi" nginx http uwsgi temporary files: "/var/temp/nginx/uwsgi" nginx http scgi temporary files: "/var/temp/nginx/scgi" [sandu@bogon openresty-1.15.8.1]$ sudo gmake [sandu@bogon openresty-1.15.8.1]$ sudo gmake install
fastdfs-nginx-module模塊相關操做
# 拷貝fastdfs-nginx-module模塊相關文件 [sandu@bogon conf]$ sudo cd /usr/local/src/fastdfs-5.11/conf [sandu@bogon conf]$ sudo cp http.conf mime.types /etc/fdfs/ # 這一步若不錯的話nginx啓動會報錯: [2019-07-31 13:29:00] ERROR - file: ini_file_reader.c, line: 1029, include file "http.conf" not exists, line: "#include http.conf" [2019-07-31 13:29:00] ERROR - file: /usr/local/src/fastdfs-nginx-module-1.20/src/common.c, line: 163, load conf file "/etc/fdfs/mod_fastdfs.conf" fail, ret code: 2 2019/07/31 13:29:00 [alert] 43690#0: worker process 43691 exited with fatal code 2 and cannot be respawned
# 編輯nginx.conf配置文件 error_log logs/error.log; pid logs/nginx.pid; server{ server_name 172.21.168.119; # 指定本機ip # group1爲nginx 服務FastDFS的分組名稱,M00是FastDFS自動生成編號,對應store_path0=/home/fdfs_storage, # 若是FastDFS定義store_path1,這裏就是M01 # 後期能夠考慮使用正則表達式進行匹配 location /group1/M00/ { root /opt/fdfs_storage/data; ngx_fastdfs_module; } }
啓動nginx:
[sandu@bogon logs]$ sudo /usr/local/openresty/nginx/sbin/nginx [sandu@bogon logs]$ sudo /usr/local/openresty/nginx/sbin/nginx -s reload # 設置nginx開機啓動,增長以下內容 [sandu@bogon logs]$ sudo vim /etc/rc.d/rc.local # nginx start /usr/local/nginx/sbin/nginx
開機啓動綜合操做:
# 在centos7中, /etc/rc.d/rc.local 文件的權限被下降了,須要給rc.local 文件增長可執行的權限 [sandu@bogon logs]$ sudo chmod +x /etc/rc.d/rc.local [sandu@bogon logs]$ sudo vim /etc/rc.d/rc.local # fastdfs start /usr/bin/fdfs_trackerd /etc/fdfs/tracker.conf restart /usr/bin/fdfs_storaged /etc/fdfs/storage.conf restart # nginx start /usr/local/openresty/nginx/sbin/nginx
Centos系統有防火牆,須要先關閉掉,才能夠在瀏覽器中訪問
# CentOS 7.0默認使用的是firewall做爲防火牆;若沒有啓用iptables 做爲防火牆,則使用如下方式關閉防火牆 [sandu@bogon logs]$ sudo systemctl stop firewalld.service #中止firewall [sandu@bogon logs]$ sudo systemctl disable firewalld.service #禁止firewall開機啓動 [sandu@bogon logs]$ sudo firewall-cmd --state #查看默認防火牆狀態(關閉後顯示notrunning,開啓後顯示running) # 若已經啓用iptables做爲防火牆,則使用如下方式關閉 [sandu@bogon logs]$ sudo service iptables stop # 臨時關閉防火牆 [sandu@bogon logs]$ sudo chkconfig iptables off # 永久關閉防火牆 # 或者考慮防火牆放行80端口
# 使用瀏覽器訪問圖片地址:http://172.21.168.119/group1/M00/00/00/rBWod11BOECAQjjjAAOMYl1argw387_big.png
文件服務器與java整合是有對應的工具包的,本身能夠去下載 fastdfs-client-java.jar
本身建立一個maven web項目,maven的pom.xml,以下:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.zlh</groupId> <artifactId>fastdfs</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>war</packaging> <name>fastdfs</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> <dependency> <groupId>org.csource</groupId> <artifactId>fastdfs-client-java</artifactId> <version>5.0.5</version> </dependency> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.4</version> </dependency> <!-- spring 的基本依賴 開始 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>4.1.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-expression</artifactId> <version>4.1.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>4.1.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>4.1.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.1.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>4.1.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>4.1.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>4.1.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>4.1.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>4.1.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>4.1.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>4.1.2.RELEASE</version> </dependency> <!-- spring 的基本依賴 結束 --> <!-- json --> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.6</version> </dependency> <dependency> <groupId>com.sun.jersey.contribs</groupId> <artifactId>jersey-multipart</artifactId> <version>1.19.4</version> </dependency> <dependency> <groupId>com.sun.jersey</groupId> <artifactId>jersey-client</artifactId> <version>1.19.4</version> </dependency> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.3.3</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.5</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.6.4</version> </dependency> <dependency> <groupId>net.sf.json-lib</groupId> <artifactId>json-lib</artifactId> <version>2.2.3</version> </dependency> <dependency> <groupId>org.apache.ant</groupId> <artifactId>ant</artifactId> <version>1.6.5</version> </dependency> <dependency> <groupId>java.unrar</groupId> <artifactId>unrar</artifactId> <version>0.5</version> </dependency> <dependency> <groupId>commons-lang</groupId> <artifactId>commons-lang</artifactId> <version>2.6</version> </dependency> </dependencies> <build> <finalName>fastdfs</finalName> <!-- 配置工程編譯級別 --> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.7</source> <target>1.7</target> </configuration> </plugin> </plugins> </build> </project>
Controller類:
package com.zlh.fastdfs.controller; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.csource.common.NameValuePair; import org.csource.fastdfs.ClientGlobal; import org.csource.fastdfs.StorageClient; import org.csource.fastdfs.StorageServer; import org.csource.fastdfs.TrackerClient; import org.csource.fastdfs.TrackerServer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import com.zlh.fastdfs.common.BaseView; import com.zlh.fastdfs.common.FileView; import com.zlh.fastdfs.common.PropertitesUtil; /** * */ @RestController @RequestMapping("") public class FastdfsController { private Logger logger = LoggerFactory.getLogger(FastdfsController.class); private static StorageClient storageClient = null; static { try { ClientGlobal.init(PropertitesUtil.conf_filename); TrackerClient tracker = new TrackerClient(); TrackerServer trackerServer = tracker.getConnection(); StorageServer storageServer = null; storageClient = new StorageClient(trackerServer, storageServer); } catch (Exception e) { e.printStackTrace(); } } @RequestMapping(value = "upload", method = RequestMethod.POST) public Object upload(MultipartFile attach, HttpServletRequest request, HttpServletResponse response) { FileView fileView = new FileView(); try { NameValuePair nvp[] = new NameValuePair[] { new NameValuePair("fileName", attach.getOriginalFilename()), new NameValuePair("type", attach.getContentType()), new NameValuePair("ext", PropertitesUtil.getFilenameExt(attach.getOriginalFilename())), new NameValuePair("size", Long.valueOf(attach.getSize()).toString()) }; String fileIds[] = storageClient.upload_file(attach.getBytes(), PropertitesUtil.getFilenameExt(attach.getOriginalFilename()), nvp); fileView.setFileSize(Long.valueOf(attach.getSize()).toString()); fileView.setFileName(attach.getOriginalFilename()); fileView.setFilePath(fileIds[0] + "/" + fileIds[1]); logger.info(fileIds.length + ""); logger.info("組名:" + fileIds[0]); logger.info("路徑: " + fileIds[1]); } catch (Exception e) { e.printStackTrace(); return new BaseView(false, "上傳失敗!"); } return new BaseView(fileView); } }
服務器應答公共實體類:
package com.zlh.fastdfs.common; import java.io.Serializable; /** * 文件名稱: com.sdzkpt.common.utils.BaseView.java</br> * 功能說明: 封裝控制層返回給前端的狀態描述,實體數據等 <br/> */ public class BaseView implements Serializable { /** * 字段描述: [字段功能描述] */ private static final long serialVersionUID = -3312282922207239793L; /** * 請求是否成功,true:成功,false:失敗 */ private boolean isSuccess; /** * 狀態描述 */ private String msgCode; /** * 待返回數據視圖 */ private Object data; /** * 方法描述: 默認無參構造器 */ public BaseView() { isSuccess = true; msgCode = ""; } /** * 方法描述: 指定狀態與描述的構造器 * * @param isSuccess * 成功與否標誌,true:成功,false:失敗 * @param msgCode * 狀態碼 */ public BaseView(boolean isSuccess, String msgCode) { this.isSuccess = isSuccess; this.msgCode = msgCode; } /** * 方法描述: 指定特定類型數據視圖,因爲指定了數據,默認狀態爲成功,狀態碼爲空,如需指定自定義狀態碼,請使用其餘構造器 * * @param data * 待返回指定類型數據視圖 */ public BaseView(Object data) { isSuccess = true; msgCode = ""; this.data = data; } /** * 方法描述: 指定狀態,描述及指定數據視圖的構造器 * * @param isSuccess * 成功與否標誌,true:成功,false:失敗 * @param msgCode * 狀態碼 * @param obj * 待返回指定類型數據視圖 */ public BaseView(boolean isSuccess, String msgCode, Object data) { this.isSuccess = isSuccess; this.msgCode = msgCode; this.data = data; } /** * 方法描述: 獲取請求是否成功標誌,true:成功,false:失敗</br> * @return * boolean 請求是否成功,true:成功,false:失敗 */ public boolean getIsSuccess() { return isSuccess; } /** * 方法描述: 獲取狀態描述</br> * @return * String 狀態描述 */ public String getMsgCode() { return msgCode; } /** * 方法描述: 獲取待返回的數據視圖</br> * @return * Object 指定類型的數據視圖 */ public Object getData() { return data; } }
返回值實體類:
package com.zlh.fastdfs.common; import java.io.Serializable; /** * 文件名稱: com.zlh.fastdfs.common.FileView.java</br> */ public class FileView implements Serializable { /** * 字段描述: [字段功能描述] */ private static final long serialVersionUID = 1L; private String fileSize; private String fileName; private String filePath; public String getFileSize() { return fileSize; } public void setFileSize(String fileSize) { this.fileSize = fileSize; } public String getFileName() { return fileName; } public void setFileName(String fileName) { this.fileName = fileName; } public String getFilePath() { return filePath; } public void setFilePath(String filePath) { this.filePath = filePath; } }
讀取配置工具類:
package com.zlh.fastdfs.common; /** * 文件名稱: com.zlh.fastdfs.common.PropertitesUtil.java</br> */ public class PropertitesUtil extends ConfigurableContants { // 靜態初始化讀入framework.properties中的設置 static { init("/client.conf"); } public static final String conf_filename = PropertitesUtil.class.getResource("/client.conf").getPath(); // public String conf_filename =getProperty(key, defaultValue); public static String getFilenameExt(String fileName) { String fileExtName = ""; if (fileName == null || "".equals(fileName)) { return null; } int nPos = fileName.lastIndexOf('.'); if (nPos > 0 && fileName.length() - nPos <= 7) { fileExtName = fileName.substring(nPos + 1); } return fileExtName; } }
整合的配置文件client.conf:
connect_timeout = 2 network_timeout = 30 charset = UTF-8 http.tracker_http_port = 80 http.anti_steal_token = no tracker_server = 172.21.168.119:22122 #tracker_server = 192.168.0.119:22122
springmvc的dispatcher-servlet.xml:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:util="http://www.springframework.org/schema/util" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd"> <!-- 配置controller層掃描包 --> <context:component-scan base-package="com.zlh.fastdfs.controller" /> <!-- 支持上傳文件 --> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"/> <!-- 配置應用參數 --> <context:property-placeholder location="classpath:client.conf" ignore-unresolvable="true"/> <!-- 註解驅動 --> <mvc:annotation-driven> <mvc:message-converters register-defaults="true"> <!--避免IE執行AJAX時,返回JSON出現下載文件 --> <bean id="fastJsonHttpMessageConverter" class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter"> <property name="supportedMediaTypes"> <list> <value>application/json;charset=UTF-8</value> <value>text/plain;charset=UTF-8</value> <value>text/html;charset=UTF-8</value> </list> </property> <property name="features"> <list> <value>WriteDateUseDateFormat</value> </list> </property> </bean> </mvc:message-converters> </mvc:annotation-driven> <!-- 設置view resolver --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/jsp/" /> <property name="suffix" value=".jsp" /> </bean> <mvc:default-servlet-handler/> </beans>
web.xml:
<?xml version="1.0" encoding="UTF-8"?> <web-app id="WebApp_ID" version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"> <context-param> <param-name>fastdfs</param-name> <param-value>webapp</param-value> </context-param> <!-- 統一編碼過濾器 --> <filter> <filter-name>encodingFilter</filter-name> <filter-class> org.springframework.web.filter.CharacterEncodingFilter </filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>encodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- 配置Spring MVC DispatcherServlet --> <servlet> <servlet-name>springmvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!-- 初始化參數 --> <init-param> <!-- 加載SpringMVC的xml到 spring的上下文容器中 --> <param-name>contextConfigLocation</param-name> <param-value>classpath:dispatcher-servlet.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>springmvc</servlet-name> <url-pattern>/fdfs/*</url-pattern> </servlet-mapping> </web-app>
跨域訪問
最終的方式就是:本地的nginx代理 -代理請求-雲上的nginx-而後雲上的nginx代理請求最終的web項目-獲得了最終的解決辦法!
前端js 的url: http://127.0.0.1:8000/my-fdfs/ 本地的nginx配置我監聽的8000: location /my-fdfs/ { proxy_pass http://118.145.79.12/fastdfs/fdfs/upload/; } 雲上的nginx我監聽的是80端口,因此上面代理的沒寫端口, 雲上的nginx配置: location /fastdfs/fdfs/upload/{ proxy_pass http://118.145.79.12:8081/fastdfs/fdfs/upload/; } 這層代理是直接訪問web項目的ip+port訪問的
1 基本配置 disable #func:配置是否生效 #valu:true、false disable=false bind_addr #func:綁定IP #valu:IP地址 bind_addr=192.168.6.102 port #func:服務端口 #valu:端口整數值 port=22122 connect_timeout #func:鏈接超時 #valu:秒單位正整數值 connect_timeout=30 network_timeout #func:網絡超時 #valu:秒單位正整數值 network_timeout=60 base_path #func:Tracker數據/日誌目錄地址 #valu:路徑 base_path=/home/michael/fdfs/base4tracker max_connections #func:最大鏈接數 #valu:正整數值 max_connections=256 work_threads #func:線程數,一般設置CPU數 #valu:正整數值 work_threads=4 store_lookup #func:上傳文件的選組方式。 #valu:0、1或2。 # 0:表示輪詢 # 1:表示指定組 # 2:表示存儲負載均衡(選擇剩餘空間最大的組) store_lookup=2 store_group #func:指定上傳的組,若是在應用層指定了具體的組,那麼這個參數將不會起效。另外若是store_lookup若是是0或2,則此參數無效。 #valu:group1等 store_group=group1 store_server #func:上傳服務器的選擇方式。(一個文件被上傳後,這個storageserver就至關於這個文件的storage server源,會對同組的storage server推送這個文件達到同步效果) #valu:0、1或2 # 0: 輪詢方式(默認) # 1: 根據ip 地址進行排序選擇第一個服務器(IP地址最小者) # 2: 根據優先級進行排序(上傳優先級由storage server來設置,參數名爲upload_priority),優先級值越小優先級越高。 store_server=0 store_path #func:上傳路徑的選擇方式。storage server能夠有多個存放文件的basepath(能夠理解爲多個磁盤)。 #valu: # 0: 輪流方式,多個目錄依次存放文件 # 2: 存儲負載均衡。選擇剩餘空間最大的目錄存放文件(注意:剩餘磁盤空間是動態的,所以存儲到的目錄或磁盤可能也是變化的) store_path=0 download_server #func:下載服務器的選擇方式。 #valu: # 0:輪詢(默認) # 1:IP最小者 # 2:優先級排序(值最小的,優先級最高。) download_server=0 reserved_storage_space #func:保留空間值。若是某個組中的某個服務器的剩餘自由空間小於設定值,則文件不會被上傳到這個組。 #valu: # G or g for gigabyte # M or m for megabyte # K or k for kilobyte reserved_storage_space=1GB log_level #func:日誌級別 #valu: # emerg for emergency # alert # crit for critical # error # warn for warning # notice # info for information # debug for debugging log_level=info run_by_group / run_by_user #func:指定運行該程序的用戶組 #valu:用戶組名或空 run_by_group= #func: #valu: run_by_user= allow_hosts #func:能夠鏈接到tracker server的ip範圍。可設定多個值。 #valu allow_hosts= check_active_interval #func:檢測 storage server 存活的時間隔,單位爲秒。 # storage server按期向trackerserver 發心跳, # 若是tracker server在一個check_active_interval內尚未收到storageserver的一次心跳, # 那邊將認爲該storage server已經下線。因此本參數值必須大於storage server配置的心跳時間間隔。 # 一般配置爲storage server心跳時間間隔的2倍或3倍。 check_active_interval=120 thread_stack_size #func:設定線程棧的大小。 線程棧越大,一個線程佔用的系統資源就越多。 # 若是要啓動更多的線程(V1.x對應的參數爲max_connections,V2.0爲work_threads),能夠適當下降本參數值。 #valu:如64KB,默認值爲64,tracker server線程棧不該小於64KB thread_stack_size=64KB storage_ip_changed_auto_adjust #func:這個參數控制當storage server IP地址改變時,集羣是否自動調整。注:只有在storage server進程重啓時才完成自動調整。 #valu:true或false storage_ip_changed_auto_adjust=true 2 同步 storage_sync_file_max_delay #func:同組storage服務器之間同步的最大延遲時間。存儲服務器之間同步文件的最大延遲時間,根據實際狀況進行調整 #valu:秒爲單位,默認值爲1天(24*3600) #sinc:v2.0 storage_sync_file_max_delay=86400 storage_sync_file_max_time #func:存儲服務器同步一個文件須要消耗的最大時間,缺省爲300s,即5分鐘。 #sinc:v2.0 storage_sync_file_max_time=300 sync_log_buff_interval #func:同步或刷新日誌信息到硬盤的時間間隔。注意:tracker server 的日誌不是時時寫硬盤的,而是先寫內存。 #valu:以秒爲單位 sync_log_buff_interval=10 3 trunk 和 slot #func:是否使用trunk文件來存儲幾個小文件 #valu:true或false #sinc:v3.0 use_trunk_file=false #func:最小slot大小 #valu:<= 4KB,默認爲256字節 #sinc:v3.0 slot_min_size=256 #func:最大slot大小 #valu:>= slot_min_size,當小於這個值的時候就存儲到trunkfile中。默認爲16MB。 #sinc:v3.0 slot_max_size=16MB #func:trunk file的size #valu:>= 4MB,默認爲64MB #sinc:v3.0 trunk_file_size=64MB 4 HTTP 相關 是否啓用 HTTP #func:HTTP是否生效 #valu:true或false http.disabled=false HTTP 服務器端口號 #func:tracker server上的http port #valu: #note:只有http.disabled=false時才生效 http.server_port=7271 檢查Storage存活狀態的間隔時間(心跳檢測) #func:檢查storage http server存活的間隔時間 #valu:單位爲秒 #note:只有http.disabled=false時才生效 http.check_alive_interval=30 心跳檢測使用的協議方式 #func:檢查storage http server存活的方式 #valu: # tcp:鏈接到storage server的http端口,不進行request和response。 # http:storage check alive url must return http status 200. #note:只有http.disabled=false時才生效 http.check_alive_type=tcp 檢查 Storage 狀態的 URI #func:檢查storage http server是否alive的uri/url #note:只有http.disabled=false時才生效 http.check_alive_uri=/status.html