3

我正在阅读非阻塞 I/O,因为我正在使用 Akka 和 Play,如果在这种情况下可以避免的话,阻塞是一个坏主意,但我不能让它与我的用例:

  1. 通过网络获取文件(这里存在使用 nio 的替代方案,但现在我使用的是 URL.openStream)
  2. 使用 BouncyCastle 解密文件(PGP)(这里我仅限于 InputStream)
  3. 使用标准 Java GZIP 解压文件(仅限 InputStream)
  4. 读取文件中的每一行,这是一个基于位置的平面文件,并转换为案例类(这里我对读取方法没有限制,现在是 scalax.io.Resource)
  5. 坚持使用 Slick/JDBC(不确定 JDBC 是否阻塞)

它现在基本上一直在使用 InputStreams。但是,为了学习和提高我的理解,我正在研究是否可以使用非阻塞 IO 来做到这一点。

我基本上想通过管道流式传输文件,在管道中应用上面的每个步骤,最后在不阻塞的情况下持久化数据。

如果需要代码,我可以轻松提供,但我正在寻找一般级别的解决方案:当我依赖使用 java.io 的库时该怎么办?

4

3 回答 3

2

我希望这对您的一些观点有所帮助:

1/2/3/4) Akka 可以很好地与使用java.io.InputStreamjava.io.OutputStream. 请参阅此页面,特别是此部分:http ://doc.akka.io/docs/akka/snapshot/scala/io.html

可以通过 asOutputStream 方法将 ByteStringBuilder 包装在 java.io.OutputStream 中。同样,我们可以通过 asInputStream 将 ByteIterator 包装在 java.io.InputStream 中。使用这些,akka.io 应用程序可以集成基于 java.io 流的遗留代码。

1)你说通过网络获取文件。我猜是通过HTTP?您可以查看异步 HTTP 库。那里有许多相当成熟的异步 HTTP 库。我喜欢在 scala 中使用Spray Client,因为它建立在 akka 之上,因此在 akka 环境中运行良好。它支持 GZIP,但不支持 PGP。

4)另一种选择:文件是否足够小以存储在内存中?如果是这样,您不必担心异步,因为您不会执行任何 IO。在等待 IO 时您不会阻塞,而是会不断地使用 CPU,因为内存很快。

5) JDBC 阻塞。您以 SQL 查询作为参数调用方法,返回类型是包含数据的结果集。该方法必须在执行 IO 时阻塞才能返回此数据。

有一些Java 异步数据库驱动程序,但我看到的所有驱动程序似乎都没有维护,所以我没有使用它们。

不要害怕。阅读 akka 文档的这一部分,了解如何在 akka 环境中处理阻塞库:http: //doc.akka.io/docs/akka/snapshot/general/actor-systems.html#Blocking_Needs_Careful_Management

于 2012-12-07T00:07:40.137 回答
1

使用 BouncyCastle 解密文件(PGP)(这里我仅限于 InputStream)

由于您在此步骤中仅限于 InputStream,因此您已经回答了自己的问题。您可以使用 NIO 完成涉及网络的部分,但您的步骤 (2) 需要一个 InputStream。您可以使用 NIO 将文件从网络假脱机到磁盘,然后从那时起使用流来解压缩和解密 ( CipherInputStream) ...在理论上仍然是阻塞的,但在实践中是连续的。

于 2012-12-06T23:15:59.453 回答
1

我知道这并不完全是非阻塞 IO,但我认为你应该看看用在 Playframework 意义上的非阻塞的 map 组合 Futures(或 Promsies)。

def getFile(location: String): File = { //blocking code} 

def decrypt(file: File): File = ..

def unzip(file: File): PromiseFile = ..

def store(file: File): String = ..

def result(status: String): SimpleResult[Json] = ..

AsyncResult{ 
  Promise.pure(getFile("someloc")) map decrypt map unzip map store map result 
}
于 2012-12-07T03:58:41.703 回答