前言
在Netty应用一 大文件传输那篇文章和之前的demo(https://gitee.com/bbstone101/pisces.git)能够传输单个几G的文件,但是,一旦遇到传输的文件数量多(比如,超过一万),就会出现服务器端卡死问题。主要原因是,使用FileRegion模式和ChunkedFile模式传输文件,server端会主动读取发送文件到网络管道,一旦client端接收和存储速度跟不上,就会导致server端数据堆积,占用服务器资源。
本篇基于Netty应用一存在的问题和文件备份实际情况,即,小文件多,且文件不过超过1G,超过10G的更是少。设计了pisces2-m基于LengthFieldBasedFrameDecoder自定义文件传输协议,程序由client端来触发和控制文件发送的频率,这样设计更切合实际。
服务器和客户端这两种通信控制模式,与MQ的消息的 推/拉 模式相像:
- Netty应用一,是由服务器主动推送文件数据,客户端接收;
- Netty应用二,是由客户端主动去服务器拉取文件信息和文件数据。
项目代码:https://gitee.com/bbstone101/pisces2-m.git
架构设计
ChunkSlicer: server端将文件切分成一个个chunk数据块发送给client。server直接从FileInputStream一个个chunk读取数据,然后构造响应buildRsp发送给client。
RecvBuffer: client端接收到chunk数据后,先缓存起来,默认缓存大小:32 * 1024 * 1024 = 32M
请求–响应处理流程
通信协议
请求协议
协议定义:
获取文件列表索引信息和数据:
- REQ_LIST_INFO:客户端请求获取fileNo=0的fli.idx文件信息(文件checksum,chunks数等)。
- REQ_LIST_DATA:客户端请求获取fileNo=0的fli.idx文件数据。
- REQ_LIST_INFO_ACK:客户端确认已经接收fli.idx文件信息。
- REQ_LIST_DATA_ACK:客户端确认已经接收fli.idx文件chunk的数据。
获取文件列表索引中文件的信息和数据:
- REQ_FILE_INFO:客户端请求获取fileNo=n的文件信息
- REQ_FILE_DATA客户端请求获取fileNo=n的文件数据。
- REQ_FILE_INFO_ACK:客户端确认已经接收文件信息。
- REQ_FILE_DATA_ACK:客户端确认已经接收文件chunk的数据。
LengthFieldBasedFrameDecoder参数和说明:
请求消息的最大帧长度是1MB,请求消息大多数没有请求体或请求体为空。
响应协议
协议定义:
服务器响应列表索引文件信息和数据:
- RSP_LIST_INFO:响应列表信息(包括chunks和文件checksum)
- RSP_LIST_DATA:响应列表文件数据,chunkNo,body的checksum,文件数据
服务器响应列表索引文件里的文件信息和数据:
- RSP_FILE_INFO:响应文件信息(包括chunks和文件checksum)
- RSP_FILE_DATA:响应文件数据,chunkNo,body的checksum,文件数据
LengthFieldBasedFrameDecoder参数和说明:
响应消息最大帧大小是12MB,响应消息主要是响应文件信息和数据,其中文件数据是body主要内容,为加快文件从server传给client,需要适当调整响应消息的最大帧大小。
后语
目前能够在局域网正确传输30万左右的文件,但是耗时也较长。
可以考虑开多个client来消费fli.idx中的文件列表传输任务来提高文件传输效率。
TODO:
1)同时启动多个客户端连服务器下载(请求)文件
2)客户端并发读取和消费fli.idx列表任务管理器设计和开发
补充:多客户端与单客户端性能对比
更新日期:20220621
结论:
- 以上测试两个版本皆为单服务端,其中单客户端接收40w+文件耗时,是同条件下10个客户端耗时的10倍多。
- 另外,从初步性能测试结果看,不能确定客户机启动10个客户端接收数据已触及到客户机的磁盘IO或CPU负载的极限。即,增大客户端个数,还有可能提升性能。
最早发布于 :2022.09.30 09:28:36