Vertx Mongo客户端通过并发更新压倒了MongoDB

时间:2019-01-19 02:40:10

标签: multithreading mongodb rx-java rx-java2 vert.x

尝试使用akka, rx, vert.x and mongodb构建反应式系统,其中的流量(下游)看起来非常多:

publisher -> akka streams -> rx streams -> vert.x event bus -> vert.x mongo rx client -> mongo client

我遇到了这样一种情况:上游在mongo上调用了太多的更新收集操作,最终结果是:

com.mongodb.MongoWaitQueueFullException: Too many threads are already waiting for a connection. Max number of threads (maxWaitQueueSize) of 500 has been exceeded.

updateCollection

  • 由每个10 publishers

  • 的每个推送元素大约0.1 second同时触发
  • 对同一集合执行

  • 正在向文档中嵌入的数组中添加新元素

1):由于这是一个反应性系统,因此最好对源进行反压,使其执行一次HTTP请求的次数尽可能多,因为这样可以写到mongo-因此等待连接到mongo的线程队列不会增加,

是否有任何模式/示例(例如使用mongo的背压)可以遵循,还是我应该自己发明和实现它?

如何通过vertx mongo客户端访问并观察等待连接的线程数?

2)在研究vertx mongo客户端代码时,发现它并未保持与mongo的连接保持打开状态,并且每次更新操作都将打开新会话。 您可以在io.vertx.ext.mongo.impl.MongoClientImpl.updateCollection(...)的下面观察它,它在下面调用MongoCollection.updateOne(...),而无需传递ClientSession clientSession参数。

虽然每秒10个并发更新似乎很小,但问题是-可能是ClientSession的创建花费很长时间并因此导致线程排队的情况吗?

不在vertx mongo客户端中不缓存与mongo的连接的设计决定是什么?

mongostat是:

insert query update delete getmore command dirty  used flushes vsize   res qrw  arw net_in net_out conn                time
    *0    *0     32     *0       0   139|0  9.8% 10.8%       0 1.84G  666M 0|0 1|89  29.6k   62.9k  104 Jan 19 02:33:51.980
    *0    *0      6     *0       0     4|0 18.7% 18.7%       0 2.90G 1.50G 0|0 1|100  2.41k   9.59k  104 Jan 19 02:33:59.342
    *0    *0     *0     *0       0     2|0 15.7% 17.2%       0 3.52G 1.60G 0|0  1|97   493b   7.90k  104 Jan 19 02:34:07.480
    *0    *0      9     *0       0     3|0 14.7% 17.2%       0 3.52G 1.57G 0|0 1|100  3.10k   18.7k  104 Jan 19 02:34:10.955
    *0    *0      1     *0       0     1|0 21.4% 23.1%       0 3.52G 1.57G 0|0 1|100   749b   7.46k  104 Jan 19 02:34:19.579
    *0    *0     10     *0       0    16|0 36.7% 37.4%       0 3.57G 1.57G 0|0 1|100  4.79k   73.7k  104 Jan 19 02:34:20.443
    *0    *0     *0     *0       0     9|0 53.6% 54.0%       0 3.62G 1.56G 0|0 1|100  1.33k   47.6k  104 Jan 19 02:34:21.769
    *0    *0      1     *0       0    13|0 54.5% 55.2%       0 3.62G 1.57G 0|0 1|100  1.92k   70.6k  104 Jan 19 02:34:22.659
    *0    *0     *0     *0       0    23|0 70.5% 70.9%       0 3.62G 1.56G 0|0 1|100  2.75k    122k  104 Jan 19 02:34:23.173
    *0    *0     *0     *0       0    31|0 72.1% 72.5%       0 3.62G 1.58G 0|0 1|100  3.56k    153k  104 Jan 19 02:34:23.586

非常感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

我不认为您需要后援,因为如果您获得的收益始终超过处理量,它将分配所有内存和过程异常,但是我认为选择是创建en发射器,其中每个流都向此发射项目发射器并使用mongorepo.saveAll(emitter):

processor1->

processor2->

processor3->

处理器4->

processor5->发射到发射器-使用saveAll(emmiter)发射到MONGO

处理器6->

processor7->

processor8->

处理器9->

processor10->