作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我需要调用上游服务(Azure Blob 服务)将数据推送到 OutputStream,然后我需要通过 akka 将其转回客户端。如果没有 akka(只有 servlet 代码),我只会获取 ServletOutputStream 并将其传递给 azure 服务的方法。
我可以尝试偶然发现的最接近的,显然这是错误的,是这样的
Source<ByteString, OutputStream> source = StreamConverters.asOutputStream().mapMaterializedValue(os -> {
blobClient.download(os);
return os;
});
ResponseEntity resposeEntity = HttpEntities.create(ContentTypes.APPLICATION_OCTET_STREAM, preAuthData.getFileSize(), source);
sender().tell(new RequestResult(resposeEntity, StatusCodes.OK), self());
最佳答案
这里真正的问题是 Azure API 不是为背压而设计的。输出流无法向 Azure 发回信号,表明它尚未准备好接收更多数据。换句话说:如果 Azure 推送数据的速度比您能够使用它的速度快,那么某处肯定会出现一些难看的缓冲区溢出故障。
接受这个事实,我们可以做的下一件最好的事情是:
Source.lazySource
仅在有下游需求时才开始下载数据(也就是正在运行源并且正在请求数据)。 download
调用其他线程,以便它继续执行而不会阻止返回源。一种方法是使用 Future
(我不确定 Java 最佳实践是什么,但应该可以正常工作)。尽管最初并不重要,但您可能需要选择 system.dispatcher
以外的执行上下文。 - 这完全取决于是否download
是否阻塞。 ResponseEntity responseEntity = HttpEntities.create(
ContentTypes.APPLICATION_OCTET_STREAM,
preAuthData.getFileSize(),
// Wait until there is downstream demand to intialize the source...
Source.lazySource(() -> {
// Pre-materialize the outputstream before the source starts running
Pair<OutputStream, Source<ByteString, NotUsed>> pair =
StreamConverters.asOutputStream().preMaterialize(system);
// Start writing into the download stream in a separate thread
Futures.future(() -> { blobClient.download(pair.first()); return pair.first(); }, system.getDispatcher());
// Return the source - it should start running since `lazySource` indicated demand
return pair.second();
})
);
sender().tell(new RequestResult(responseEntity, StatusCodes.OK), self());
关于java - 将 Akka 流传递给上游服务以进行填充,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61037458/
我是一名优秀的程序员,十分优秀!