【发布时间】:2021-12-15 18:34:15
【问题描述】:
我有一个微服务,我正在使用 Kotlin 协程异步执行一堆 db 查询,我想监控每个查询的执行时间,以实现潜在的性能优化。
我的实现是这样的:
val requestSemaphore = Semaphore(5)
val baseProductsNos = productRepository.getAllBaseProductsNos()
runBlocking {
baseProductsNos
.chunked(500)
.map { batchOfProductNos ->
launch {
requestSemaphore.withPermit {
val rawBaseProducts = async {
productRepository.getBaseProducts(batchOfProductNos)
}
val mediaCall = async {
productRepository.getProductMedia(batchOfProductNos)
}
val productDimensions = async {
productRepository.getProductDimensions(batchOfProductNos)
}
val allowedCountries = async {
productRepository.getProductNosInCountries(batchOfProductNos, countriesList)
}
val variants = async {
productRepository.getProductVariants(batchOfProductNos)
}
// here I wait for all the results and then some processing on thm
}
}
}.joinAll()
}
如您所见,我使用 Semaphore 来限制并行作业的数量,并且所有存储库方法都是可挂起的,而这些是我想要测量其执行时间的方法。下面是 ProductRepository 中的一个实现示例:
suspend fun getBaseProducts(baseProductNos: List<String>): List<RawBaseProduct> =
withContext(Dispatchers.IO) {
namedParameterJdbcTemplateMercator.query(
getSqlFromResource(baseProductSql),
getNamedParametersForBaseProductNos(baseProductNos),
RawBaseProductRowMapper()
)
}
为此,我尝试了这个:
val rawBaseProductsCall = async {
val startTime = System.currentTimeMillis()
val result = productRepository.getBaseProducts(productNos)
val endTime = System.currentTimeMillis()
logger.info("${TemporaryLog("call-duration", "rawBaseProductsCall", endTime - startTime)}")
result
}
但是与顺序实现(没有协程)相比,这个测量总是返回不一致的平均值结果,我能想出的唯一解释是这个测量包括暂停时间,显然我只对查询在没有暂停时间的情况下执行所花费的时间(如果有的话)。
我不知道在 Kotlin 中我想要做的事情是否可行,但看起来 python 支持这一点。因此,我将不胜感激在 Kotlin 中做类似事情的任何帮助。
更新:
在我的例子中,我使用常规的 java 库来查询数据库,所以我的数据库查询只是常规的阻塞调用,这意味着我现在测量时间的方式是正确的。
如果我使用R2DBC 的某些实现来查询我的数据库,我在问题中所做的假设将是有效的。
【问题讨论】:
-
你的代码except在这里暂停了什么?只需创建 RPC 并解析结果?
-
@LouisWasserman 是的,这就是它的作用,我等待查询的结果,然后对它们进行一些处理。我不确定我是否回答了您的问题?
-
那么你只是想测量创建 RPC 并解析结果的时间吗?服务器响应您的 RPC 所花费的时间?
-
是的,这正是我想要做的。
-
但是......您正在客户端上进行测量(您的微服务充当数据库协程的客户端)。除非您对服务器有更深入的了解,否则您还会选择什么?
标签: java kotlin kotlin-coroutines coroutine