Java大量文件传输(Netty应用二)

前言

在Netty应用一 大文件传输那篇文章和之前的demohttps://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

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注