使用InputStream的Java库的非阻塞IO

3
我正在研究非阻塞I/O,因为我在使用Akka和Play,如果可能的话,在这种情况下,避免阻塞是一个不好的主意,但我无法将其与我的用例结合起来:
  1. 从网络获取文件(这里有使用nio的替代方案,但现在我正在使用URL.openStream)
  2. 使用BouncyCastle解密文件(这里我只能使用InputStream)
  3. 使用标准Java GZIP解压文件(仅限于InputStream)
  4. 读取文件中的每一行,它是一个基于位置的平面文件,并转换为Case类(这里我对读取方法没有限制,现在是scalax.io.Resource)
  5. 使用Slick / JDBC进行持久化(不确定JDBC是否是阻塞的)
目前,使用InputStreams基本上可以正常工作。然而,为了学习和提高我的理解,我正在调查是否可以使用非阻塞IO完成此操作。
我想通过管道流式传输文件,在其中应用上述每个步骤,并最终在不阻塞的情况下持久化数据。
如果需要代码,我可以轻松提供,但我希望找到一个通用级别的解决方案:当我依赖使用java.io的库时该怎么办?
3个回答

2
我希望这能帮助你解决一些问题:
1/2/3/4) Akka 可以很好地与使用 java.io.InputStream 和 java.io.OutputStream 的库配合使用。请参阅此页面,特别是此部分:http://doc.akka.io/docs/akka/snapshot/scala/io.html

通过 asOutputStream 方法,可以将 ByteStringBuilder 包装在 java.io.OutputStream 中。同样,ByteIterator 可以通过 asInputStream 方法包装在 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 文档中关于如何处理阻塞库的部分: http://doc.akka.io/docs/akka/snapshot/general/actor-systems.html#Blocking_Needs_Careful_Management

不知道Spray。看起来很有趣! - Magnus

1

我知道这不是完全的非阻塞IO,但我认为你应该看一下在Play框架中意义上的使用非阻塞的map来组合Futures(或Promises)。

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 
}

1
使用BouncyCastle解密文件(PGP)(在此我仅限于InputStream)
由于您在此步骤中仅限于InputStream,因此您已经回答了自己的问题。您可以使用NIO处理涉及网络的部分,但是您的步骤(2)需要InputStream。您可以使用NIO将文件从网络缓存到磁盘上,然后从那时起使用流进行解压缩和解密(CipherInputStream)...理论上仍然会阻塞,但实际上是连续的。

"理论上仍然是阻塞的,但在实践中是连续的。" 我对这个声明感到好奇。因为我也有同样的想法。如果我开始使用一个非阻塞源包装/转换成InputStream,那么在实践中它会是非阻塞的,因为源是非阻塞的吗?像使用这种方法:http://openjdk.java.net/projects/nio/javadoc/java/nio/channels/Channels.html#newInputStream(java.nio.channels.ReadableByteChannel) - Magnus
@Magnus 我特意没有说“实际上非阻塞”,我说的是“连续的”。我的意思是,你不会因为等待本地文件的FileInputStream的下一次读取而被阻塞数秒钟。 - user207421
我看到我没有仔细阅读你的答案。我猜我可以使用nio将文件存储在磁盘上,然后从那里开始,但是同样,我也可以将其缓存在内存中以达到相同的效果? - Magnus

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