我使用Spring Boot和WebFlux运行基于Netty的Kotlin应用程序。详细信息如下:
我在Web层上得到一个文件。 WebFlux用它创建一个Part
(org.springframework.http.codec.multipart
)。数据以大小为4Kb的Flux
块流的形式存储在Part
的Project Reactor的DataBuffer
中:
Flux<DataBuffer> content();
由于遵守框架的一致性,我将Flux
转换为Kotlin的Flow
。
然后,我使用同步Vault客户端的encrypt(...)
在flatMapMerge
方法中异步提交块(据我了解)(注意encrypt(...)
不是suspend
,并且是HTTP客户端到远程加密提供程序的包装):
public String encrypt(String keyName, String plaintext);
我检查了这个答案https://stackoverflow.com/a/58659423/6612401,发现flow { emit(...)}
应该使用基于流的方法。
我的问题是,我可以将这种基于流程的方法用于非suspend
函数吗?考虑到我正在使用runBlocking(Dispatchers.IO)
和suspend
fold(...)
函数,还是有更好的方法。
代码如下:
@FlowPreview
@ExperimentalCoroutinesApi
private fun getOpenByteArrayAndEncryptText(part: Part): Pair<ByteArray, String> = runBlocking(Dispatchers.IO) {
val pair = part.content().asFlow()
.flatMapMerge { dataBuffer ->
val openByteArray = dataBuffer.asInputStream().readBytes()
val opentextBase64 = Base64Utils.encodeToString(openByteArray)
flow { emit(Pair(openByteArray, vaultTransitTemplate.encrypt(KEY_NAME, opentextBase64))) }
}.fold(Pair(ByteArrayOutputStream(), StringBuilder())) { result, curPair ->
result.first.writeBytes(curPair.first)
result.second.append(curPair.second)
result
}
Pair(pair.first.toByteArray(), pair.second.toString())
}
P.S。 fold(...)
函数将打开的块收集到ByteArrayOutputStream
以便稍后计算哈希,然后将加密的块收集到StringBuilder
作为加密文件的结果。
P.P.S。我已经尝试过了。该方法平均在我的Core i5 8gen 4物理核心计算机上提交5-7个并行请求。它完成了工作,但没有那么快。如果不将Vault部署在本地,则每1 Mb加密大约可获得1秒的时间。我了解这取决于网络的延迟。我什至不考虑Vault侧面的加密速度,由于块的大小仅为4Kb,因此闪电般快。有什么方法可以提高并发速度吗?
P.P.P.S我尝试在concurrency = MAX_CONCURRENT_REQUESTS
中玩flatMapMerge{...}
。到目前为止,结果并不重要。最好保留默认值。