本文主要介绍fastdfs客户端的上传下载原理以及以及服务端的网络io模型;主要介绍storage,不涉及tracker;storage和tracker使用的网络io模型是一样的。
1.协议格式
FastDFS采用二进制TCP通信协议。一个数据包由 包头(header)和包体(body)组成。client、tacker、storage之间通信的消息格式,都是这样的。
包头只有10个字节,格式如下:
@ pkg_len:8字节整数,body长度,不包含header,只是body的长度
@ cmd:1字节整数,命令码; 比如上传,下载等;不同的命令,对应的body内容不同
@ status:1字节整数,状态码,0表示成功,非0失败(UNIX错误码)
// tracker\tracker_proto.h TrackerHeadertypedef struct{ char pkg_len[FDFS_PROTO_PKG_LEN_SIZE]; //body length, not including header char cmd; //command code char status; //status code for response} TrackerHeader;
以STORAGE_PROTO_CMD_UPLOAD_FILE,上传普通文件为例,数据包定义如下:
2.客户端上传原理
fastdfs提供命令进行上传文件操作:
fdfs_upload_file <config_file> <local_filename> [storage_ip:port] [store_path_index]
客户端上传文件流程如下:
stat获取文件的状态、大小等
上传文件,肯定是要判断是否是一个常规文件;并且需要获取文件的大小的。通过linux系统提供的stat函数就可以得到,跟使用stat命令是一样的。
storage_do_upload_file
发送静态资源文件的时候,需要先将文件读入内存,再将内存中的数据send到相应的网络fd。通过使用sendfile完成文件的发送,不再需要两步操作。
sendfile使用mmap,实现零拷贝;
零拷贝,使用的是mmap方式,本质是DMA的方式,不需要CPU参与。普通copy,从磁盘copy数据到内存,需要CPU的move指令。
在进程中有一块区域叫内存分配区,当调用mmap的时候,会把文件映射到对应的区域,操作文件就跟操作内存一样。
fastdfs提供的客户端fdfs_upload_file是通过文件的方式上传,其实fastdfs也可以支持内存方式上传;我们在云盘项目中,就自己参考fastdfs的协议,实现了内存方式上传,减少了保存本地磁盘文件的过程。
发送完文件后,等待服务端返回响应;包含group_name, remote_file_name。
3.断点续传
fastdfs支持断点续传
先使用命令操作
echo hello > test1.txtecho world > test2.txtecho cong > test3.txt# 先使用fdfs_upload_appender上传 test1.txtfdfs_upload_appender /etc/fdfs/client.conf test1.txt得到:group1/M00/00/00/CqgWMGIgcUiEPsHJAAAAADY6MCA314.txt ,在fdfs_append_file的时候需要# 接着续传 test2.txtfdfs_append_file /etc/fdfs/client.conf group1/M00/00/00/CqgWMGIgcUiEPsHJAAAAADY6MCA314.txt test2.txt# 接着续传 test3.txtfdfs_append_file /etc/fdfs/client.conf group1/M00/00/00/CqgWMGIgcUiEPsHJAAAAADY6MCA314.txt test3.txt# 在服务器相应的目录下查找对应的文件,用cat读取文件内容。root@4af22fda6f4b:/home/fastdfs/storage/data/00/00# cat CqgWMGIgcUiEPsHJAAAAADY6MCA314.txthelloworldcong
断点续传文件分为两个阶段:
- fdfs_upload_appender 上传第一部分文件,STORAGE_PROTO_CMD_UPLOAD_APPENDER_FILE命令;
- fdfs_append_file 上传其他部分的文件,以STORAGE_PROTO_CMD_APPEND_FILE命令。
需要注意:
- 注意断点续传的顺序性;
- 支持断点续传,但fastdfs并不支持多线程分片上传同一个文件。
4.客户端下载原理
fastdfs下载协议如下:
客户端下载流程如下:
下载的时候也支持三种接收方式:
- FDFS_DOWNLOAD_TO_FILE:storage_do_download_file1_ex
- FDFS_DOWNLOAD_TO_BUFF:storage_download_file1
- FDFS_DOWNLOAD_TO_CALLBACK:storage_download_file_ex
fastdfs支持多线程下载, 因为协议支持file_offset和download_bytes; 可以指定每一个线程现在的起始位置和大小。
如果服务端是对单个连接进行限速,那么客户端使用多线程下载可以提升下载速度;如果服务端是对用户名或者ip进行限速,客户端多线程下载效果也不明显。
5.网络io模型
fastdfs网络io使用的是多reactor的模型;分为accept线程,work线程,dio线程;这样设计的优点:
- 将网络io和磁盘io解耦;
- 扩充磁盘的时候,方便定义文件读写线程数量
accept线程接收网络连接,并将连接分配给work线程处理;通过pipe将连接发送给work线程;
work线程处理io请求;每个work线程都有一个epoll;如果需要进行磁盘io操作,则将任务push到队列中,交给dio线程处理;
dio线程进行磁盘io操作,从队列里面取任务;并通过pipe向work线程发送消息。
网络io简单处理流程如下图:
fastdfs具体的io处理如下:
线程进行磁盘io操作,从队列里面取任务;并通过pipe向work线程发送消息。
网络io简单处理流程如下图:
[外链图片转存中…(img-25s6udTD-1647335339614)]
fastdfs具体的io处理如下:
[外链图片转存中…(img-HST0uKy0-1647335339615)]
————————————————
版权声明:本文为CSDN博主「congchp」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/congchp/article/details/123507184