kotlin KMongo和协程

sy5wg1nm  于 2023-05-07  发布在  Kotlin
关注(0)|答案(1)|浏览(121)

I have a question related to coroutines and KMongo. I'm using KMongo CoroutineCollection to find some records in the database. On my local computer it takes <0.5sec but when I do the same thing on development environment it takes 10-25 seconds.
The app runs on Spring Boot Netty server with reactor to support coroutines. I'm using also DGS to set up GraphQL endpoints. The simplified callstack is:

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

It seems the default batchSize is 2 , so I can see multiple queries run under the hood. My suspicion is that the code operates on 1 thread that is used across the app and that's why it takes much longer on dev vs local (less clients and scheduled operations). This is how logs look like:

[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

This is how repository class look like:

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")
        return result
    }
}

Interesting part to me is that after calling the first KMongo .find() the thread changes to a different one and continues on that thread till the end. This doesn't sound right to me. Any thoughts?

mnemlml8

mnemlml81#

默认的batchSize似乎是2,所以我可以看到多个查询在后台运行。我的怀疑是,代码运行在一个线程上,该线程在整个应用程序中使用,这就是为什么它在dev上比在local上花费更长时间的原因
我认为多次往返费用是一个更可能的解释。如果您有n个文档,则所花费的时间为n/2*rtt。
我不认为想象你的开发环境的往返时间是你的本地机器的20倍是一个延伸。
因此,一个简单的解决方法是简单地增加batchSize
线程改变为不同的线程,并在该线程上继续直到结束。
当你记得协程几乎就是回调时,这就不那么令人惊讶了。例如,Dispatchers.Default有一个线程池来调度多个协程。这被称为M:N线程。

相关问题