You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

KMongo协程查询环境性能差异问题排查求助

KMongo协程查询在开发环境耗时过长的问题分析与建议

问题概述

使用KMongo的CoroutineCollection查询数据库时,本地环境耗时小于0.5秒,但在开发环境中耗时长达10-25秒,性能差异显著。

运行环境与调用栈

应用基于Spring Boot Netty(支持Reactor协程)运行,通过DGS框架搭建GraphQL端点,简化调用栈如下:

DGSQuery suspend fun -> suspend fun |
                                    | -> suspend fun KMongo first CoroutineCollection.find()
                                    | -> suspend fun KMongo second CoroutineCollection.find()

关键发现与怀疑点

  • KMongo默认batchSize为2,导致底层会执行多次查询拉取数据,增加网络交互开销
  • 怀疑代码在单线程上运行且该线程被整个应用共享,开发环境因客户端请求和定时任务更多,更容易出现线程拥堵,进而拉长耗时

日志分析

从日志可以看到:

[ctor-http-nio-1][][] c.x.d.a.wellreport.***Resolver           : wellReports run
[ctor-http-nio-1][][] c.x.d.d.wellreport.***Service            : all***Provider.invoke() start
[ctor-http-nio-1][][] d.m.w.Mongo***Repository                 : fetchAll started
[tter-2-thread-1][][] org.mongodb.driver.protocol.command      : Sending command '{"find": "***", "filter": {}, "batchSize": 100, "$db": "***", "lsid": {"id": {"$binary": {"base64": "hdGYjs3YSX6K5y2YJzUJkw==", "subType": "04"}}}}' with request id 56 to database *** on connection [connectionId{localValue:22, serverValue:1902}] to server localhost:27017
[ntLoopGroup-3-6][][] org.mongodb.driver.protocol.command      : Execution of command with request id 56 completed successfully in 13.32 ms on connection [connectionId{localValue:22, serverValue:1902}] to server localhost:27017
[ntLoopGroup-3-6][][] org.mongodb.driver.operation             : Received batch of 54 documents with cursorId 0 from server localhost:27017
[ntLoopGroup-3-6][][] d.m.w.Mongo***Repository                 : fetchAll finished
[ntLoopGroup-3-6][][] c.x.d.d.wellreport.***Service            : all***Provider.invoke() finished
[ntLoopGroup-3-6][][] c.x.d.d.wellreport.***Service            : positive***Provider.invoke() start
[ntLoopGroup-3-6][][] w.Mongo***Repository                     : fetchAllPositive start
[tter-2-thread-1][][] org.mongodb.driver.protocol.command      : Sending command '{"find": "***", "filter": {"score": {"$gt": 0.0}}, "batchSize": 2, "$db": "***", "lsid": {"id": {"$binary": {"base64": "hdGYjs3YSX6K5y2YJzUJkw==", "subType": "04"}}}}' with request id 57 to database *** on connection [connectionId{localValue:22, serverValue:1902}] to server localhost:27017
[ntLoopGroup-3-6][][] org.mongodb.driver.protocol.command      : Execution of command with request id 57 completed successfully in 5.26 ms on connection [connectionId{localValue:22, serverValue:1902}] to server localhost:27017
[ntLoopGroup-3-6][][] org.mongodb.driver.operation             : Received batch of 2 documents with cursorId 6831622277590159417 from server localhost:27017
  • 首次调用KMongo的find()后,线程从ctor-http-nio-1切换到ntLoopGroup-3-6,后续所有操作都在该线程上执行
  • 第二次查询的batchSize为2,仅拉取到2条数据,且返回了非0的cursorId,说明还需要多次请求拉取剩余数据,这会显著增加总耗时

相关代码片段

Repository实现类代码:

class MongoXXXScoreRepository(private val collection: CoroutineCollection<MongoXXXScore>) : XXXScoreRepository {
    private val logger by logger()
    override suspend fun fetchAllPositive(): List<XXXScore> {
        logger.info("fetchAllPositive start")
        val result = collection.find(MongoXXXScore::score gt 0.0).toList().map { it.toXXXScore() }
        logger.info("fetchAllPositive start") // 注:此处日志重复,建议改为finished
        return result
    }
}

优化建议

  • 调整batchSize:显式设置更大的batchSize(如100或根据实际数据量调整),减少网络请求次数,例如:
    collection.find(MongoXXXScore::score gt 0.0).batchSize(100).toList()
    
  • 协程调度器优化:确保KMongo使用合适的协程调度器(如Dispatchers.IO)执行IO操作,避免阻塞Netty的事件循环线程。可通过配置KMongo的客户端参数指定调度器,或在调用时用withContext(Dispatchers.IO)包裹查询逻辑
  • 并行查询优化:如果两个find查询无依赖关系,可使用async/await并行发起,减少总耗时:
    val allData = async { firstCollection.find().toList() }
    val positiveData = async { secondCollection.find(MongoXXXScore::score gt 0.0).batchSize(100).toList() }
    val result = allData.await() + positiveData.await()
    
  • 数据库连接池配置:检查MongoDB连接池的最大连接数设置,确保开发环境有足够的连接资源,避免请求等待连接
  • 索引优化:为score字段创建索引,提升查询过滤效率:
    collection.createIndex(Indexes.ascending(MongoXXXScore::score.name))
    
  • 线程调度监控:使用协程监控工具(如Kotlinx Coroutines Debug Agent)追踪线程调度情况,确认是否存在线程阻塞或资源竞争问题

内容的提问来源于stack exchange,提问作者bemol

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 17:03:14