MongoS连接池问题学习笔记

2021-03-30 11:26:10 浏览数 (1)

MongoS连接池问题学习笔记

01

客户端到MongoS的连接

默认情况下,mongos对客户端的连接都是每个连接对应一个线程,每个线程1M的内存,所以连接数增多,对于MongoS的内存消耗还是很大的。

连接的创建和销毁是比较耗费资源的,为了较少这种消耗,在MongoDB3.6版本引入了adaptive线程池。默认情况下不开启,它有如下特点:

0、adaptive线程池中的线程会同时处理多个连接的IO请求。开启它之后,每个连接将不在对应一个线程。

1、默认情况下,MongoDB的adaptive线程池会为我们创建CPU个数/2个线程;

2、在线程池内部,有一个"线程池使用阈值",当我们对于线程池内部的线程使用值小于这个阈值时,线程池会自动销毁部分线程。

3、MongoDB3.6的线程池默认是不开启的,需要我们指定参数serviceExecuter来开启,如下:

net: serviceExecutor: adaptive

4、可以通过 mongo shell 执行db.serverStatus().network.serviceExecutorTaskStats查看线程池的使用情况

02

MongoS的连接池

MongoS内部两种类型的连接池,传统的连接池和ASIO连接池。

传统连接池:DBConnectionPool

大部分的command都是使用传统的连接池的,它的应用范围比较广泛。另外,mongos对于集群所有的shard和config,都会周期性的执行一个isMaster指令,并以此更新分片的主从信息,这个指令指定的过程,也是通过传统连接池实现的。

传统连接池内的连接执行命令不会创建新的线程,是在 mongos 接收的连接创建的线程上执行的,所以不会消耗额外的内存空间。

ASIO连接池:ConnectionPool

ASIO连接池设置了连接池的最大连接,最小连接,刷新时间,超时时间等限制。建立新的连接时,当前的连接数既要满足最小连接数和最大连接数的限制,同时也要满足最大连接数等硬性要求。

我们可以通过connPoolStats 与 shardConnPoolStats 命令查看mongos/mongod内部连接池的状态:

代码语言:javascript复制
mongos> db.runCommand({shardConnPoolStats:1})
{
        "totalInUse" : 0,
        "totalAvailable" : 0,
        "totalCreated" : 0,
        "totalRefreshing" : 0,
        "pools" : {

        },
        "hosts" : {

        },
        "threads" : [
                {
                        "hosts" : [ ],
                        "seenNS" : [ ]
                }
        ],
        "ok" : 1,
        "operationTime" : Timestamp(1615822847, 1),
        "$clusterTime" : {
                "clusterTime" : Timestamp(1615822847, 1),
                "signature" : {
                        "hash" : BinData(0,"4niRErK1XnD93zgXSyG5XD5P is="),
                        "keyId" : NumberLong("6894922308364795935")
                }
        }
}

4个重要的参数需要关注,如下:

"inUse" : 0 //正在使用的连接数 "available" : 0 //可用的连接数 "created" : 0 //历史创建过的连接数,包含已经回收的 "refreshing" : 0 // refresh 状态的连接数

通过 ASIO 连接池的连接执行的命令,每次会创建一个线程执行的,默认的栈空间大小是 8 M 。所以ASIO 连接池内 mongos 到 mongod 的连接消耗的最小内存是8M 。

MongoS一般情况下混用这俩,对于CRUD等基本操作,3.2版本和3.4版本通过ASIO连接池执行,3.6版本及以上,全部读写操作都使用ASIO连接池执行。

03

版本间的差异

3.2 / 3.4 版本传统连接池的连接回收策略不是很完善,大量的空闲连接不能及时回收,所以偶尔重启 mongos来回收连接还是很有必要的。

3.2 / 3.4 版本传统连接池不能限制同时到每个 host 的连接;3.6 及以上版本可以通过 connPoolMaxShardedInUseConnsPerHost 和connPoolMaxInUseConnsPerHost 控制到每个 host 的连接数。

客户端到mongos和mongos到mongod的连接数是什么关系?

在3.2和3.4版本,如果客户端到mongos的连接数很多,而且每个连接都执行常见的CRUD操作,那么客户端到mongos的连接数比较少,而mongos到mongod的连接数比较多,二者比值小于1:1;如果客户端只是持有连接而不做任何操作,那么结果相反;

3.6 及以上的版本,连接池的使用与回收策略都比较完善,并且查询、更新、删除、插入等操作都是通过ASIO 连接池执行的。所以如果 mongos 进来的连接都很繁忙,进来的连接和出去的连接基本保持 1:1 的关系,而且从mongos到mongod的连接消耗的内存比较多;当然如果进来连接不执行任何操作,那么 mongos 不会创建到 mongod 的连接,此时 mongos 进来的连接和出去的连接是大于 1:1 的。

0 人点赞