图床项目总结
1. fastdfs 、nginx 文件管理模块1. 1 fastdfs 三大组件1.1.1 tracker server相当于一个调度器其内部不存储文件只存储storage 服务器相关的一些元信息(存在于内存中)通过连接storage后由storage汇报的信息生成的根据这些信息 组成一个group -- storage的关联信息。当需要上传文件的时候分配goup 客户端先访问trackertracker根据负载均衡的策略(比如某个剩余空间大的storage服务器)分配一个group分配storage然后再到group中选择一个storage 并给出path客户端访问storage客户端将向storage发送写文件请求storage将会为文件分配一个数据存储目录配置tracker 只需要配置data和logs路径1.1.2 storage server真正存储文件的服务器其中经过tracker的分配会有一个逻辑上的组group每个group中含有多个storage互为备份当上传文件的时候选择其中一个上传其余storage后续通过binlog日志进行同步。一般内部会有256*256个子目录去存储文件。比如 00/00/ 00/01等。当文件上传的时候记录Fileidstorage会为文件生成一个Fileid由storage server ip、文件创建时间、文件大小、文件crc32和一个随机数拼接而成然后将这个二进制串进行base64编码转换为可打印的字符串。存储到两级目录每个存储目录下有两级256*256的子目录storage会按文件fileid进行两次hash猜测路由到其中一个子目录然后将文件以fileid为文件名存储到该子目录下生成文件名当文件存储到某个子目录后即认为该文件存储成功接下来会为该文件生成一个文件名文件名由group、存储目录、两级子目录、fileid、文件后缀名由客户端指定主要用于区分文件类型拼接而成。配置storage① 需要设置好data的存储位置② 需要设置好M00的映射地址(真正的物理地址)1.1.3 client提供的一个客户端相当于需要往fastdfs中输入一些指令upload xx xx、download xx xx1.1.4 fastdfs-nginx-module 下载文件该模块是fastdfs中长期使用的稳定模块而且配置文件的路径和storage一致这个模块的作用如果没有此模块后端从数据库取出文件ID如 group1/M00/00/00/xxx.txt后端连接Tracker 调用指令获取文件所在的地址后端发送读取请求获取文件流调用指令读取文件后端返回文件流给前端如果有此模块后端只返回一个 HTTP URL 给前端http://10.0.0.1:80/group1/M00/00/00/xxx.txt前端直接使用URL下载前端直接使用这个 URL 下载a 标签或 window.open流量直接从 Nginx 流向客户端不经过业务后端1. 2 nginx 模块nginx-upload-module用于上传文件如果没有该模块则上传文件的二进制内容全都要放在请求体中数据解析困难。引入该模块之后便可以在nginx层面解析multipart/form-data将文件保存到临时目录然后生成包含文件信息的变量如$upload_tmp_path等再将请求转发到后端如/api/upload后端从变量或环境变量中获取文件路径来处理。2. 文件上传2.0 文件秒传其实就是根据MD5查看file_info中是否已经存在相同MD5的文件如果已经存在则再去查user_file_list中有没有如果没有则添加一条记录并且把file_info的引用计数 1。如果秒传失败则触发2.12.1 上传经过nginx-upload-file模块的recv的数据是和前端调用axios后发送的有所不同content解析其中content 以一个WebKitFormBoundaryjWE3qXXORSg2hZiB分割进行filename、filetype、md5等信息的解析文件名拼接在经过nginx模块上传后文件统一去掉了后缀名这里找到type和filename进行拼接即可fastdfs命令上传用到了进程间通信需要执行fdfs_upload_file(指令) /etc/fdfs/client.conf(配置文件路径) 123.txt(文件)此步骤完成后可以获取到group1/M00/00/00/xxx.txtpipe(int fd[2]): 创建一个无名管道其中fd[0] 表示读端fd[1] 表示写端pid_t pid fork(): 创建子进程子进程会完全复制父进程的地址空间但是区分pid子进程pid 0则说明是子进程关闭读端保留写端将标准输出重定向到写管道父进程pid 1则说明是父进程关闭写端保留读端设置读取数据的端read(fd[0], fileid, TEMP_BUF_MAX_LEN)读取数据到fileid中wait(NULL)/close(fd[0]): 等待子进程结束并关闭挥手完整路径依旧使用父子进程方式执行命令fdfs_file_info获取ip拼接 http:// ip group1/M00/00/00/xxx.txt数据库持久化将上传文件信息插入表做持久化file_info 插入一条user_file_list 插入一条父子间进程通信的原理可以使用popen()是在fork()、pipe()之上的封装在fork()创建子进程后共享父进程的数据(也就是说父子进程皆可以访问管道的读写端持有其fd)如果是在此之前创建了pipe()那么父子进程都会有pipe读端和写端的引用如果写端引用不为0则无法在读端读取数据因此需要关闭子进程的读和父进程的写2. 注册登录
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2441666.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!