大规模小传输的Netty应用程序设计

3
我正在考虑如何设计一个有些不寻常的 Netty 应用程序。基本上,有一个客户端发起请求。这个请求翻译成英语就是“递归获取目录 /whatever/ 下的许多小文件,并且我能告诉你关于这些文件的唯一信息就是它们的名称在 AAAAAAA.bin 和 CCCCCCC.bin 之间。”因此,服务器需要接受请求,开始在服务器上扫描一些目录,并开始快速地流式传输所有这些小文件。性能至关重要,但确保收到 AAAAAAA.bin 和 CCCCCCC.bin 之间的所有文件也同等重要。
因此,将客户端和服务器本身作为异步的设计是否是一个好主意呢?换句话说,客户端启动对话,发送请求,仅接收确认 UUID 令牌或类似令牌,然后服务器开始收集文件(可能每个线程一个),联系客户端,并传递一个单个文件和 UUID。我认为客户端可以定期询问服务器“你已经完成了匹配 UUID 令牌 /sometoken/ 的请求吗?”
我不太确定如何配置,因为客户端和服务器都将启动对话。或者,也许还有其他更好的设计想法?再一次强调,性能(从请求启动到完成所有文件传输的总时间)至关重要。谢谢!
1个回答

1

假设您完全控制协议(即不受HTTP限制),那么可能会采用以下方式:

  1. 客户端连接到服务器并发送目录请求。如果客户端正在重新启动中止的传输,则发送带有第2个令牌的请求。
  2. 服务器响应此传输的唯一令牌。如果正在重新启动传输,则使用第1个令牌进行响应。
  3. 服务器识别此传输的所有文件,为每个文件分配唯一ID,并将文件集与第2个令牌相关联(可能需要在生成令牌之前确定文件)。
  4. 对于每个文件,服务器发送由文件长度、唯一文件ID、文件(以及任何其他信息,例如文件名)组成的消息。服务器尽快发送每个文件,并且不等待第5步的确认。
  5. 客户端使用唯一文件ID确认接收到的每个文件。
  6. 在发送最后一个文件后,服务器发送“传输完成”消息。

所有上述通信都在单个通道上进行。重要的是,您正在异步流式传输文件并接收确认,从而减轻了网络延迟。

如果您有很多文件,我不建议每个文件使用一个线程。也许可以使用线程池,将要发送的每个文件添加到作业队列中,或者将每个唯一的目录添加到作业队列中,然后一个线程一次处理一个目录。您可能需要同步调用channel.write(..)。我还假设客户端可以无序接收文件。
实际上,我最初会使用一个线程来读取文件。一旦它可靠地工作,再看看是否使用多个线程可以通过保持网络繁忙(即不等待读取下一个文件)来提高性能。
在写入通道时,我可能会编写包含文件详细信息(唯一标识符、文件数据(如果足够小)、必要时的文件名)的对象,然后具有可以将对象转换为/从通道缓冲区的编解码器。
根据您的确切情况,客户端可以打开多个连接到服务器,并且您可以将连接分配给特定的文件读取线程,从而避免任何通道同步问题。这样可能会提高一些性能,但最有可能的是,可用带宽将在连接之间共享。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接