我正在Quarkus中实现一个GET
方法,它应该向客户端发送大量数据。使用JPA/Hibernate从数据库中读取数据,序列化为JSON,然后发送到客户端。如果没有整个数据在内存中,如何有效地完成此操作?我尝试了以下三种可能性,但都没有成功:
所以我的问题是:用Quarkus通过JPA发送读取的大数据的诀窍是什么?
这里有一些资源可以帮助您做到这一点:
最后一篇文章是针对SpringBoot的,但这个想法也可以用Quakus实现。
------------编辑:
好的,我已经制定了一个示例,在其中我进行批量选择。我做得很华丽,但没有它你也可以很容易地做到。
我将返回一个ScrollableResult,然后在Rest资源中使用它,通过SSE(服务器发送事件)将其流式传输到客户端。
------------编辑2:
我已将setFetchSize添加到查询中。你应该使用这个数字,并将其设置在1-50之间。如果value=1,则db行将以1乘1的方式提取,这最像流。它将使用最少的内存,但db之间的I/O
在进行这样的批量操作时,强烈建议使用无状态会话。
@Entity
public class Fruit extends PanacheEntity {
public String name;
// I've removed the logic from here to the Rest resource,
// otherwise you cannot close the session
}
@Path("/fruits")
public class FruitResource {
@GET
@Produces(SERVER_SENT_EVENTS)
public void fruitsStream(@Context Sse sse, @Context SseEventSink sink) {
var sf = Fruit.getEntityManager().getEntityManagerFactory().unwrap(SessionFactory.class);
try (var session = sf.openStatelessSession();
var scrollableResults = session.createQuery("select f from Fruit f")
.scroll(ScrollMode.FORWARD_ONLY)
.setFetchSize(1) {
while (scrollableResults.next()) {
sink.send(sse.newEventBuilder().data(scrollableResults.get(0)).mediaType(APPLICATION_JSON_TYPE).build());
}
sink.close();
}
}
}
然后我这样调用这个Restendpoint(通过httpie):
> http :8080/fruits --stream
data: {"id":9996,"name":"applecfcdd592-1934-4f0e-a6a8-2f88fae5d14c"}
data: {"id":9997,"name":"apple7f5045a8-03bd-4bf5-9809-03b22069d9f3"}
data: {"id":9998,"name":"apple0982b65a-bc74-408f-a6e7-a165ec3250a1"}
data: {"id":9999,"name":"apple2f347c25-d0a1-46b7-bcb6-1f1fd5098402"}
data: {"id":10000,"name":"apple65d456b8-fb04-41da-bf07-73c962930629"}
希望这对你有帮助。
根据您的要求,您有两种选择:
选项1:采用HATEOAS方法(https://restfulapi.net/hateoas/)。通过REST标准交换大数据集的标准模式之一。因此,在这种方法中,服务器将在第一次响应中快速响应一组HATEOAS URI。其中每个HATEOAS URI代表一组元素。因此,您需要根据数据大小生成这些URI,并让客户端代码负责将这些URI作为REST API单独调用以获取实际数据。但在这个选项中,您也可以考虑Reactive风格,以获得具有小内存足迹的流处理的更多优势。
选项2:正如上面@Serkan所建议的,将结果集作为REST响应从数据库连续流式传输到客户端。在这里,您需要确保客户端和服务之间的网关用于超时设置。如果没有门户,你就是好的。因此,您可以利用所有层的反应式编程来实现连续流。“DAO/数据访问层”--
您的结果是否必须全部包含在一个响应中?让客户端请求下一个结果页,直到没有下一个结果页为止,这是一个典型的REST API分页练习,怎么样?此外,JPA后端将只从数据库中获取该页面,因此没有任何时候所有内容都会存储在内存中。
在我的设置中,我希望通过SSE通道(服务器发送的事件)转发某些状态更改。状态更改是通过调用RESTendpoint来启动的。因此,我需要将传入的状态更改转发到SSE流。 在Quarkus中实现这一点的最佳/最简单方法是什么。 我能想到的一个解决方案是使用EventBus(https://quarkus.io/guides/reactive-messaging)。SSEendpoint将订阅状态更改
问题内容: 我想使用elasticsearch-river-mysql以便将数据从MySQL数据库连续传输到ElasticSearch。我是ES和Rivers的初学者,所以希望您能为我的问题提供帮助。 据我所知,数据将从MySQL数据库流式传输到ES集群,后者将自动对其进行索引。那是对的吗?我需要了解任何超时或限制吗? 关系数据库表之间的外键关系将如何转换为ES?包含外键的表行是否将成为ES文档的
问题内容: 我正在尝试设置一个非常基本的html5页面,该页面会加载20MB的.mp4视频。看来,浏览器需要下载整个内容,而不仅仅是播放视频的第一部分并在其余部分进行流传输。 我在搜索时发现的最接近的内容…我尝试了“手刹”和“数据回合”,两者均未发挥作用: 关于如何执行此操作或是否可行的任何想法? 这是我正在使用的代码: 问题答案: 确保moov(元数据)在mdat(音频/视频数据)之前。这也称为
我试图从SQL数据库中获取一些数据,这时对我的Camel服务进行了REST调用。我可以以字节数组的形式获取数据,并将其设置为Camel的主体,然后将其作为原始字节返回给调用者(web浏览器、应用程序等)。 我现在想用流来做这件事,而不是保存内存中的所有字节。如果我使用,当方法完成时,我可以从结果集获得的连接和流都将关闭,即使我试图返回一个并将其设置为主体。这阻止了我从DB直接流式传输数据,通过Ca
问题内容: 我有10,000个地址和5,000人的大型数据库。 我想让用户在数据库中搜索地址或用户。在输入文本时,我想使用Twitter的提前提示功能来建议结果。 在此处查看NBA示例:http : //twitter.github.io/typeahead.js/examples。 我了解从速度和负载的角度来看,预取15,000个项目并不是最佳选择。尝试实现此目标的更好方法是什么? 问题答案:
问题内容: 使用MVC模型,我想编写一个JsonResult,它将Json字符串流式传输到客户端,而不是一次将所有数据转换成Json字符串,然后将其流回客户端。我有一些动作需要在Json传输时发送非常大的记录(超过300,000条记录),我认为基本的JsonResult实现是不可伸缩的。 我正在使用Json.net,我想知道是否有一种方法可以在转换Json字符串时流化它的块。 但是我不确定如何将这