我有一个服务器集群(可能彼此远离),它们都运行 Tomcat
并使用 Apache HttpClient
通过 HTTP 进行通信。这些服务器中有大量是数据存储,其中一台服务器是前置 Web 服务器,充当客户端和存储之间的中介。用户应该能够将文件上传到网络服务器,网络服务器会将该文件传递给给定数量的商店。
所以,问题是:是否可以将客户端上传的文件部分作为 InputStream
并写入多个 POST
请求到商店同时?如果我只是简单地写入本地文件,显而易见的解决方案就是将 InputStream
的 block 读取到 byte
数组缓冲区中,然后从缓冲区写入每个输出反过来,但我不知道如何说服 HttpClient 像这样“共享”流。
是的,我可以简单地将整个 InputStream
读取到网络服务器上的一个对象中,然后按顺序将它写到每个存储中,但是因为我可能会接受非常大文件我必须将数据写入磁盘,然后为每个存储服务器读回,磁盘操作的数量可能会很快变得令人望而却步。这是我希望避免的实现。
最佳答案
如果商店没有跟上网络带宽,它将如何“共享”流?
您可以拆分传入的文件并将其传递给商店而不将其写入磁盘,但是如果只有一个商店无法跟上,您必须将该文件数据保存在内存中直到它可以接受它.如果它是一个大文件,或者有很多用户,它可能会占用您的所有内存。
从技术上讲,我的意思是您可以创建 5 个线程,它们将尽可能快地将数据发送到存储并将文件数据保存在共享的 FIFO 结构中。当最后一个线程访问了一个部分并发送了该部分时,该数据可以从数据结构中删除,但之前不能。如果速度较慢,数据结构可能会变得庞大。
数据必须在某个地方,如果不是内存也不是硬盘,那么在哪里?
因此,将传入的数据保存在内存中,直到(如果?)内存不足(永远不会?),然后将其刷新到硬盘驱动器。通过将数据发送到商店然后删除,继续尝试用数据清空数据结构。
您可以相当轻松地编写一个 ExecutorService 来处理数据的重新传输和清理数据结构,但这并不能神奇地解决问题。 :)
我没有提供源代码,因为你似乎不需要这个解决方案。如果您接受不能神奇地传递数据而没有机会将其缓冲在硬盘驱动器上(或者更糟糕的解决方案是限制用户上传到 MinimumBandwidth(store1) , store2, store3, store4, store5)).
编辑/更改:
尽管我这么说了,但我不确定您是否真的想要 ExecutorService。我会创建自己的自定义线程来实际处理这个问题。我将从并发包创建一个 Collection,可能是一个包含字节数组(不是字节,字节数组)的 LinkedBlockingQueue。然后我将从 Thread->Integer 创建一个映射,它保存每个线程在传递数据时的进程的当前索引。当所有进度数字都高于 10 时(意味着所有线程都已发送前 10 个 block ),然后我删除前 10 个字节数组,并从所有线程的进度中减去 10 以重置它。
关于java - HttpClient - 从一个 InputStream 写入多个 POST 请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18189641/