重要的内容
MongoDB的主备节点在运行过程中是不固定的,实例重启、升级、节点故障等都有可能导致主备切换,在生产环境应该使用副本集的方式来正确连接MongoDB来实现高可用。
连接问题
用户可通过DMS或mongo shell连接MongoDB云数据库,以下场景都基于用户使用mongo shell连接数据库。
Q: 连接实例提示网络超时?
# /u01/mongodb_current/bin/mongo --host dds-uf69ba5cf6e123442.mongodb.rds.aliyuncs.com:3717 --authenticationDatabase admin -u root -p xxx
MongoDB shell version: 3.2.3
DB Prefix:
connecting to: 10.1.2.8:3717/admin
2016-05-31T15:25:58.940+0800 W NETWORK Failed to connect to 10.1.2.8:3717 after 5000 milliseconds, giving up.
2016-05-31T15:25:58.943+0800 E QUERY Error: couldn't connect to server 10.1.2.8:3717 (10.1.2.8), connection attempt failed
at connect (src/mongo/shell/mongo.js:181:14)
at (connect):1:6 at src/mongo/shell/mongo.js:181
exception: connect failed
通过telnet来确认是否是网络不通导致的,例如
telnet dds-uf69ba5cf6e123442.mongodb.rds.aliyuncs.com 3717
网络不通可能的原因:
- ECS跟MongoDB节点不在同一个可用区
- ECS跟MongoDB节点不在同一个vpc环境
Q: 连接实例提示鉴权失败?
$mongo --host dds-uf69ba5cf6e123442.mongodb.rds.aliyuncs.com:3717 --authenticationDatabase admin -u root -p xxx
MongoDB shell version: 3.2.3
connecting to: 10.1.2.8:3717/test
2016-05-31T15:50:18.623+0800 E QUERY Error: 18 Authentication failed.
at DB._authOrThrow (src/mongo/shell/db.js:1271:32)
at (auth):6:8
at (auth):7:2 at src/mongo/shell/db.js:1271
exception: login failed
可能的原因
- 密码错误,可在控制台重置root密码
- 连接的用户跟数据库不匹配,比如root用户是admin数据库下的用户,则使用root连接时,必须指定鉴权数据库为admin
- 客户端版本过低,mongo shell版本必须是3.0+,其他语言客户端的版本要求参考Driver兼容性文档
Q: 连接Secondary执行执行命令时,提示slaveOk=false错误?
$mongo --host dds-uf69ba5cf6e123442.mongodb.rds.aliyuncs.com:3717 --authenticationDatabase admin -u root -p xxx
MongoDB shell version: 3.2.3
connecting to: 10.1.2.8:3717/test
mongo-9551:SECONDARY> show dbs
2016-05-31T15:54:13.527+0800 E QUERY Error: listDatabases failed:{ "ok" : 0, "errmsg" : "not master and slaveOk=false", "code" : 13435 }
at Error (<anonymous>)
at Mongo.getDBs (src/mongo/shell/mongo.js:47:15)
at shellHelper.show (src/mongo/shell/utils.js:630:33)
at shellHelper (src/mongo/shell/utils.js:524:36)
at (shellhelp2):1:1 at src/mongo/shell/mongo.js:47
默认情况下,MongoDB的读写请求都必须到Primary节点,Secondary默认是不可读的,除非客户端显式的指定Secondary节点可读(通过设置readPreference)。
mongoshell连接时,可以执行rs.slaveOk()来指定备可读
$mongo --host dds-uf69ba5cf6e123442.mongodb.rds.aliyuncs.com:3717 --authenticationDatabase admin -u system -p xxx
MongoDB shell version: 3.2.3
connecting to:10.1.2.8:3717/test
mongo-9551:SECONDARY> rs.slaveOk()
mongo-9551:SECONDARY> show dbs
admin 0.000GB
hello 0.000GB
local 0.000GB
test 0.000GB
如果想mongo shell一直连接到Priamry节点,可通过如下方式连接
mongo --host 副本集名称/节点1,节点2 --authenticationDatabase admin -u system -p xxx
例如
mongo --host mg-100101/dds-uf69ba5cf6e123442.mongodb.rds.aliyuncs.com:3717,dds-uf69ba5cf6e123441.mongodb.rds.aliyuncs.com:3717 --authenticationDatabase admin -u system -p xxx
注意:MongoDB的主备节点在运行过程中是不固定的,实例重启、升级、节点故障等都有可能导致主备切换,在生产环境应该使用副本集的方式来正确连接MongoDB来实现高可用。
Q: 连接时提示Connection reset by peers?
$mongo --host dds-uf69ba5cf6e123442.mongodb.rds.aliyuncs.com:3717 --authenticationDatabase admin -u root -p xxx
MongoDB shell version: 3.2.3
connecting to: 10.1.2.8:3717/test
2016-05-31T16:25:58.940+0800 I NETWORK Socket recv() errno:54 Connection reset by peer ç
2016-05-31T16:25:58.940+0800 I NETWORK SocketException: remote: 10.1.2.8:3717 error: 9001 socket exception [RECV_ERROR] server [10.1.2.8:3717]
2016-05-31T16:25:58.940+0800 I NETWORK DBClientCursor::init call() failed
上述错误通常是实例的连接数已经达到上限,无法再建立更多的网络连接,可在控制台查看实例连接数的使用情况确认。用户使用实例时应该合理的规划并控制实例的连接数,避免因为连接数耗尽而无法连接实例,如果业务上的确需要更多的网络连接,则需要升级实例的规格。连接数的管理请参考下面『连接数问题』部分。
连接数问题
Q: 如何查看当前连接数?
- 登录阿里云控制台查看
-
使用mongo shell连接实例,执行如下命令,其中current代表当前已建立连接数,available代表当前可用连接数,internal*的连接用于内部管理,用户可忽略。
mongo-test:PRIMARY> db.serverStatus().connections { "current" : 0, "available" : 2000, "internal_current" : 3, "internal_available" : 497, "totalCreated" : NumberLong(21) }
Q: 如何查看当前连接主要来自哪些ECS机器?
mongoshell或DMS(如果连接数已满,则只能通过DMS来登录查看)连接实例,执行db.runCommand({currentOp: 1, $all: true}),就能输出所有跟该实例建立的所有连接情况,其中client字段包含了ECS的ip地址信息。
> db.runCommand({currentOp: 1, $all: true})
{
"inprog" : [
{
"desc" : "conn20",
"threadId" : "140353731274496",
"connectionId" : 20,
"client" : "10.1.2.7:28788",
"active" : false
},
...
有了上述结果,用户就可以根据来源ip做进一步的分析,得出各个ECS跟实例分别建立了多少连接等信息。
Q: 生产环境连接数快满了,如何限制每个ECS到实例的连接数量?
MongoDB基本所有的driver都支持通过Connection String URI来连接实例,云数据库的连接URI已为用户在控制上生成好,加上密码信息就能直接使用。
如果采用URI来连接实例的,在URI末尾加上&maxPoolSize=xx
来限制到实例的连接数即可,比如你有10台ECS并发访问实例,实例的最大连接数为1000,那么每个ECS上的连接池的数量要控制在100以内。
不同语言的客户端可能封装了不通的连接方式,但也一定有方法指定连接池的数量限制,具体参考各语言客户端的api文档。
负载高问题
Q: CPU利用率很高,想看看实例正在执行什么操作?
mongo shell连接实例,执行db.currentOp()
mongo-test:PRIMARY> db.currentOp()
造成实例负载高的典型case
- 并发请求的量太大,超出当前规格的服务能力
- 查询集合时,没有合理的建索引,导致全表扫描或排序
- 正在跑一些计算量很大的mapreduce或者aggregation任务
正在执行的操作都包含一个opid字段,用户可以根据opid字段直接kill掉对应的操作
mongo-test:PRIMARY> db.killOp(opid)
仍然无法解决问题
请查看FAQ文档,或提交工单。