由于 FastDFS 分布式文件存储在上传文件时不保留原文件名,当上传完文件后会返回如下面格式的文件 ID。在文件 ID 中包含了文件所在的组,二级目录,以及由客户端 IP 、时间戳、文件大小生成的 base64 编码文件名。客户端数据库里存储这个着文件 ID ,且只能通过文件 ID 来访问获取文件。如果其他系统想要访问 FastDFS 文件存储就必须从上传客户端保存的数据库中获取该文件的文件 ID 。这样增加了系统的耦合程度,也不利于后续文件存储的迁移和运维。由于 FastDFS 是将文件直接存放在本地磁盘,并不对文件进行分块、合并操作,所以我们可以直接让 nginx 去请求获取本地磁盘上的文件,不经过查询客户端数据库获取文件 ID,无需经过 FastDFS 也可以获取到文件。
# 编译安装 luajit wget http://luajit.org/download/LuaJIT-2.1.0-beta2.tar.gz tar zxf LuaJIT-2.1.0-beta2.tar.gz cd LuaJIT-2.1.0-beta2 make PREFIX=/usr/local/luajit make install PREFIX=/usr/local/luajit
3.1.3 下载 ngx_devel_kit(NDK)模块
1 2
wget https://github.com/simpl/ngx_devel_kit/archive/v0.2.19.tar.gz tar -xzvf v0.2.19.tar.gz
3.1.4 下载 lua-nginx-module 模块
1 2
wget https://github.com/openresty/lua-nginx-module/archive/v0.10.2.tar.gz tar -xzvf v0.10.2.tar.gz
3.1.5 编译 nginx
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
tar zxvf nginx-1.15.1.tar.gz cd nginx-1.15.1/
# tell nginx's build system where to find LuaJIT 2.1: export LUAJIT_LIB=/usr/local/luajit/lib export LUAJIT_INC=/usr/local/luajit/include/luajit-2.1
location = /Redis { internal; set_unescape_uri $key $arg_key; Redis2_query get $key; Redis2_pass 127.0.0.1:6379; } # 此处根据业务的需求来写正则表达式,一定要个 redis 里的 KEY 对应上 location ~/[0-9].*\.(gif|jpg|jpeg|png)$ { set $target ''; access_by_lua ' # 使用 nginx 的内部参数 ngx.var.uri 来获取请求的 uri 地址,如 /000001.jpg local key = ngx.var.uri # 根据正则匹配到 KEY ,从 redis 数据库里获取文件 ID (路径和文件名) local res = ngx.location.capture( "/Redis", { args = { key = key } } ) if res.status ~= 200 then ngx.log(ngx.ERR, "Redis server returned bad status: ", res.status) ngx.exit(res.status) end if not res.body then ngx.log(ngx.ERR, "Redis returned empty body") ngx.exit(500) end local parser = require "Redis.parser" local filename, typ = parser.parse_reply(res.body) if typ ~= parser.BULK_REPLY or not server then ngx.log(ngx.ERR, "bad Redis response: ", res.body) ngx.exit(500) end
typedefstruct { bool if_gen_filename; //if upload generate filename char file_type; //regular or link file bool if_sub_path_alloced; //if sub path alloced since V3.0 char master_filename[128]; char file_ext_name[FDFS_FILE_EXT_NAME_MAX_LEN + 1]; char formatted_ext_name[FDFS_FILE_EXT_NAME_MAX_LEN + 2]; char prefix_name[FDFS_FILE_PREFIX_MAX_LEN + 1]; char group_name[FDFS_GROUP_NAME_MAX_LEN + 1]; //the upload group name int start_time; //upload start timestamp FDFSTrunkFullInfo trunk_info; FileBeforeOpenCallback before_open_callback; FileBeforeCloseCallback before_close_callback; } StorageUploadInfo;
typedefstruct { char op_flag; char *meta_buff; int meta_bytes; } StorageSetMetaInfo;
typedefstruct { char filename[MAX_PATH_SIZE + 128]; //full filename /* FDFS logic filename to log not including group name */ char fname2log[128+sizeof(FDFS_STORAGE_META_FILE_EXT)]; char op; //w for writing, r for reading, d for deleting etc. char sync_flag; //sync flag log to binlog bool calc_crc32; //if calculate file content hash code bool calc_file_hash; //if calculate file content hash code int open_flags; //open file flags int file_hash_codes[4]; //file hash code int64_t crc32; //file content crc32 signature MD5_CTX md5_context; union { StorageUploadInfo upload; StorageSetMetaInfo setmeta; } extra_info; int dio_thread_index; //dio thread index int timestamp2log; //timestamp to log int delete_flag; //delete file flag int create_flag; //create file flag int buff_offset; //buffer offset after recv to write to file int fd; //file description no int64_t start; //the start offset of file int64_tend; //the end offset of file int64_t offset; //the current offset of file FileDealDoneCallback done_callback; DeleteFileLogCallback log_callback;
structtimevaltv_deal_start;//task deal start tv for access log } StorageFileContext;