我有两个端点以两种不同的json格式返回相同的数据。
第一个端点返回一个json数组,并立即开始响应。
@Get("/snapshots-all")
fun allSnapshots(
@Format("yyyy-MM-dd") cutoffDate: LocalDate
): Flux<PersonVm> = snapshotDao.getAllSnapshots(cutoffDate)
返回分页结果的下一个端点更加缓慢。当两个流都完成时,它开始响应。它还需要比前一个端点多得多的内存,即使前一个端点从BigQuery返回所有记录。
@Get("/snapshots")
fun snapshots(
@Format("yyyy-MM-dd") cutoffDate: LocalDate,
pageable: Pageable
): Mono<Page<PersonVm>> = Mono.zip(
snapshotDao.getSnapshotCount(cutoffDate),
snapshotDao.getSnapshots(
cutoffDate,
pageable.size,
pageable.offset
).collectList()
).map {
CustomPage(
items = it.t2,
totalNumberOfItems = it.t1,
pageable = pageable
)
}
(问题更新)BigQuery位于这个端点的底部。与Postgres相比,BigQuery的强大之处在于查询大型表。缺点是简单查询的延迟相对较高。因此,我并行运行查询,以便将端点的延迟降至最低。按顺序运行查询,将使总处理时间至少增加1秒。
问题是:是否有可能重写链以加速/snapshots
端点?
解决方案需求(建议方法后问题更新)
此端点的使用者是项目外部的,并且此项目中的每个端点都在详细级别上进行了记录。因此,在返回的JSON中,分页可能只发生一次。否则,请随意建议与PersonVm
集合一起返回分页的新类型。
如果结果证明另一个解决方案是不可能的,那也是一个答案。
SnapshotDao#getSnapshotCount
返回Mono<Long>
SnapshotDao#getSnapshots
返回Flux<PersonVm>
PersonVm
的定义如下:
@Introspected
data class PersonVm(
val volatilePersonId : UUID,
val cases: List<PublicCaseSnapshot>
)
CustomPage
的定义如下:
@Introspected
data class CustomPage<T>(
private val items: List<T> = listOf(),
private val totalNumberOfItems: Long,
private val pageable: Pageable
) : Page<T> {
override fun getContent(): MutableList<T> = items.toMutableList()
override fun getTotalSize(): Long = totalNumberOfItems
override fun getPageable(): Pageable = pageable
}
PublicCaseSnapshot
是一个复杂的结构,为简洁起见省略了。解决这个问题不应该需要它。
@Denis建议的方法测试期间使用的代码
在这种方法中,chain从SnapshotDao#getSnapshotCount
开始,并映射到HttpResponse
实例,响应体包含Flux<PersonVm>
,头中包含总项目计数。
查询现在将按顺序运行,下面的代码和现有代码之间的大量比较测试表明,原始代码执行得更好(大约比原来更好)。1秒)。在测试期间使用了不同的页面大小,并且通过多次运行相同的查询来预热BigQuery。
请注意,如果花费在总项目计数查询上的时间可以忽略不计(或总项目计数可缓存),并且不需要将分页作为JSON的一部分,则应将其视为可行的方法。
@Get("/snapshots-with-total-count-in-header")
fun snapshotsWithTotalCountInHeader(
@Format("yyyy-MM-dd") cutoffDate: LocalDate,
pageable: Pageable
): Mono<HttpResponse<Flux<PersonVm>>> = snapshotDao.getSnapshotCount(cutoffDate)
.map { totalItemCount ->
HttpResponse.ok(
snapshotDao.getSnapshots(
cutoffDate,
pageable.size,
pageable.offset
)
).apply {
headers.add("total-item-count", totalItemCount.toString())
}
}
您需要重写该方法以返回项的发布者。我可以在这里看到一些选项:
- 返回标题中的分页信息。你的方法将返回类型为
Mono<HttpResponse<Flux<PersonVm>>>
。 - 返回每个项目的分页信息:
Flux<Tuple<PageInfo, PersonVm>>