【发布时间】:2021-06-04 17:05:47
【问题描述】:
我们将 Micronaut 与 Mongo 结合使用,通过一些控制器公开数据。由于响应实体的大小正在增长,我们的应用程序有时会出现内存不足。因此,我们正在研究切换到异步 mongo 驱动程序并使用响应式响应将数据流式传输到客户端。很遗憾,我们无法更改 API 响应结构或内容类型(全部为 application/json)
我们的一个 API 返回的实体结构如下:
[
{ "field": "value" },
{ "field": "value" },
...
{ "field": "value" }
]
我们使用这个控制器来工作,dataStore 返回一个Publisher<Example>:
@Get("all")
Flowable<Example> getAllExamples() {
return Flowable.fromPublisher(dataStore.find()).map(SomeMapper::toPublic);
}
这很好用,庞大的示例列表在将其流式传输到客户端之前不必完全加载到内存中。
其他 API 返回(更明智的)结构:
{
"list": [
{ "field": "value" },
{ "field": "value" },
...
{ "field": "value" }
],
"meta": {
...
}
}
我们可以为这样的实体应用类似的发布者/可流动模式,还是在将此类响应发送出去之前将数据加载到内存中?
我们尝试了以下签名:
@Get("all/dev")
Single<ExamplesWrapper> getAllDev() {
Publisher<Example> dev = dataStore.find();
return Flowable.fromPublisher(dev)
.map(mapper::map)
.collect((Callable<ArrayList<Example>>) ArrayList::new, ArrayList::add)
.map(ExampleWrapper::new);
}
包装器将添加一些元数据的地方。但这再次将其全部加载到内存中,然后再发送出去,导致应用程序崩溃。
将 Flowable 添加到响应包装器中:
public class ExamplesWrapper {
private final Flowable<Example> examples;
@ConstructorProperties({"examples"})
public ExamplesWrapper(Flowable<Example> examples) {
this.examples = examples;
}
public Flowable<Example> getExamples() {
return examples;
}
}
也因一些不错的 Jackson 映射异常而失败。
元数据不依赖于实际的示例数据(它添加了一些静态公司信息)。我们能否以某种方式实现这样的端点,而不必将所有数据加载到内存中?
【问题讨论】:
标签: java json mongodb reactive-programming micronaut