3

我正在尝试决定如何设计一个我认为有一些不寻常要求的 Netty 应用程序。基本上有一个客户端发起请求。该请求翻译成英文为“递归地在 /whatever/ 目录下获取一堆小文件,关于这些文件,我只能告诉你它们的名称在 AAAAAAA.bin 和 CCCCCCC.bin 之间”。

因此,服务器需要接受请求,并开始扫描服务器端的一些目录,并开始快速将所有这些小文件流回。性能很重要,但确保我收到了 AAAAAAA.bin 和 CCCCCCC.bin 之间的所有文件也很重要。

那么让客户端和服务器本身基本上异步是一个好的设计吗?换句话说,客户端发起对话,发送请求,并简单地接收一个确认 UUID 令牌或其他东西,然后服务器开始收集文件(可能每个线程一个),联系客户端,并将单个文件传递给它使用 UUID?我认为客户端可以定期询问服务器“您是否完成了流式传输与 UUID 令牌/sometoken/匹配的我的请求?

我不太确定这将如何配置,因为客户端和服务器都将启动对话。或者,也许其他人有更好的设计理念?同样,性能(从请求发起到完成所有文件传输的总时间)至关重要。

谢谢!

4

1 回答 1

1

假设您完全控制协议(即您不限于 HTTP),那么可能类似于

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

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

如果您有很多文件,我不会为每个文件使用一个线程。可能是一个线程池,每个要发送的文件都被添加到作业队列中,或者可能每个唯一的目录都被添加到作业队列中,并且一个线程一次处理一个目录。您可能需要同步对 channel.write(..) 的调用。我还假设客户端可以无序地接收文件。

实际上,我最初只使用一个线程来读取文件。一旦它可靠地工作,看看是否有多个线程可以让您通过保持网络繁忙来提高性能(即不等待读取下一个文件)。

当写入通道时,我可能会在包含文件详细信息的对象上写入(唯一的 id、文件数据(如果足够小)、文件名(如果需要)),然后有一个编解码器可以将对象转换为 / 来自通道缓冲区。

根据您的具体情况,客户端可以打开到服务器的多个连接,您可以将连接分配给特定的文件读取线程,从而避免任何通道同步问题。通过这种方式,您可能会获得一些性能提升,但最有可能的是,您只会看到连接之间共享的可用带宽。

于 2012-08-03T15:45:54.060 回答