为什么要监控?
监控及时获得应用的运行状态信息,在问题出现时及时发现。
监控什么?
CPU、内存、磁盘I/O、应用程序(MongoDB)、进程监控(ps -aux)、错误日志监控
1.4.1 MongoDB集群监控方式
db.serverStatus()
查看实例运行状态(内存使用、锁、用户连接等信息)
通过比对前后快照进行性能分析
"connections" # 当前连接到本机处于活动状态的连接数
"activeClients" # 连接到当前实例处于活动状态的客户端数量
"locks" # 锁相关参数
"opcounters" # 启动之后的参数
"opcountersRepl" # 复制想关
"storageEngine" # 查看数据库的存储引擎
"mem" # 内存相关
状态:
db.stats()
显示信息说明:
# 统计数据库信息
db.stats()
{
"db" : "test", # 系统自带测试数据库
"collections" : 0, # 集合数量
"views" : 0, #
"objects" : 0, # 文档对象的个数, 所有集合的记录数之和
"avgObjSize" : 0, # 平均每个对象的大小, 通过 dataSize / Objects 得到
"dataSize" : 0, # 当前库所有集合的数据大小
"storageSize" : 0, # 磁盘存储大小
"numExtents" : 0, # 所有集合的扩展数据量统计数
"indexes" : 0, # 已建立索引数量
"indexSize" : 0, # 索引大小
"fileSize" : 0, #
"fsUsedSize" : 0, #
"fsTotalSize" : 0, #总大小
"ok" : 1
}
1.4.2 mongostat
mongostat是mongdb自带的状态检测工具,在命令行下使用。它会间隔固定时间获取mongodb的当前运行状态,并输出。如果你发现数据库突然变慢或者有其他问题的话,你第一手的操作就考虑采用mongostat来查看mongo的状态。
主要功能:
实时数据库状态,读写、加锁、索引命中、缺页中断、读写等待队列等情况。
每秒刷新一次状态值,并能提供良好的可读性,通过这些参数可以观察到MongoDB系统整体性能情况。
常用命令格式:
mongostat --host 192.168.1.100:27017 -uroot -p123456 --authenticationDatabase admin
虚拟内存使用量,单位MB (这是 在mongostat 最后一次调用的总数据)
物理内存使用量,单位MB (这是 在mongostat 最后一次调用的总数据)
1.4.3 mongotop
mongotop命令说明:
[mongod@MongoDB oplog]$ mongotop -h 127.0.0.1:27017
2018-01-08T17:32:56.623+0800 connected to: 127.0.0.1:27017 ns total read write 2018-01-08T17:32:57+08:00
admin.system.roles 0ms 0ms 0ms
admin.system.users 0ms 0ms 0ms
admin.system.version 0ms 0ms 0ms
app.user 0ms 0ms 0ms
automationcore.automation.job.status 0ms 0ms 0ms
automationcore.config.automation 0ms 0ms 0ms
automationcore.config.automationTemplates 0ms 0ms 0ms
automationcore.config.automationTemplates_archive 0ms 0ms 0ms
automationcore.config.automation_archive 0ms 0ms 0ms
automationstatus.lastAgentStatus 0ms 0ms 0ms
mongotop重要指标
ns:数据库命名空间,后者结合了数据库名称和集合。
total:mongod在这个命令空间上花费的总时间。
read:在这个命令空间上mongod执行读操作花费的时间。
write:在这个命名空间上mongod进行写操作花费的时间。
1.4.3 mongosniff
此工具可以从底层监控到底有哪些命令发送给了MongoDB 去执行,从中就可以进行分析:以root 身份执行:
$./mongosniff --source NET lo
然后其会监控位到本地以localhost 监听默认27017 端口的MongoDB 的所有包请求。
1.4.3 db级别命令
1、db.currentOp()
db.currentOp是个好东西,顾名思义,就是当前的操作。在mongodb中可以查看当前数据库上此刻的操作语句信息,包括insert/query/update/remove/getmore/command等多种操作。直接执行
db.currentOp()一般返回一个空的数组,我们可以指定一个参数true,这样就返回用户connections与系统cmmand相关的操作。下面看个列子:
db.currentOp(true) 会返回很多信息:
db.currentOp()
查看数据库当前执行什么操作。
用于查看长时间运行进程。
通过(执行时长、操作、锁、等待锁时长)等条件过滤。
重点关注以下几个字段:
字段 | 说明 |
---|---|
client | 请求是由哪个客户端发起的。 |
opid | 操作的opid,有需要的话,可以通过db.killOp(opid) 直接终止该操作。 |
secs_running/microsecs_running | 这个值重点关注,代表请求运行的时间,如果这个值特别大,请看看请求是否合理。 |
query/ns | 这个字段能看出是对哪个集合正在执行什么操作。 |
lock* | - 还有一些跟锁相关的参数,需要了解可以看官网文档,本文不做详细介绍。 - db.currentOp文档请参见:db.currentOp。 |
示例:
gechongrepl:PRIMARY> db.currentOp()
{
"inprog" : [
{
"opid" : ,
"active" : true,
"secs_running" : ,
"microsecs_running" : NumberLong(),
"op" : "getmore",
"ns" : "local.oplog.rs",
"query" : { },
"client" : "192.168.91.132:45745",
"desc" : "conn5",
"threadId" : "0x7f1370cb4700",
"connectionId" : ,
"waitingForLock" : false,
"numYields" : ,
"lockStats" : {
"timeLockedMicros" : {
"r" : NumberLong(),
"w" : NumberLong()
},
"timeAcquiringMicros" : {
"r" : NumberLong(),
"w" : NumberLong()
}
}
}
]
}
opid" : 6222,#进程号
"active" : true,#是否活动状态
"secs_running" : 3,#操作运行了多少秒
"microsecs_running" : NumberLong(3662328),
"op" : "getmore",#操作类型,包括(insert/query/update/remove/getmore/command)
"ns" : "local.oplog.rs",#命名空间
"query" : {},#如果op是查询操作,这里将显示查询内容;也有说这里显示具体的操作语句的
"client" : "192.168.91.132:45745",#连接的客户端信息
"desc" : "conn5",#数据库的连接信息
"threadId" : "0x7f1370cb4700",#线程ID
"connectionId" : 5,#数据库的连接ID
"waitingForLock" : false,#是否等待获取锁
"numYields" : 0,
"lockStats" : {
"timeLockedMicros" : {#持有的锁时间微秒
"r" : NumberLong(141),#整个MongoDB实例的全局读锁
"w" : NumberLong(0)},#整个MongoDB实例的全局写锁
"timeAcquiringMicros" : {#为了获得锁,等待的微秒时间
"r" : NumberLong(16),#整个MongoDB实例的全局读锁
"w" : NumberLong(0)}#整个MongoDB实例的全局写锁
2、db.killOp(opid)
kill当前的操作 opid为具体的操作id号,当然了,只能kill正在进行中的。opid是通过db.currentOp()查询返回的。如果发现一个操作太长,把数据库卡死的话,可以用这个命令杀死他:> db.killOp(608605)
示例:
{ "inprog" :
[
{
"opid" : 3434473,//操作的id
"active" : <boolean>,//是否处于活动状态
"secs_running" : 0,//操作运行了多少秒
"op" : "<operation>",//具体的操作行为,包括(insert/query/update/remove/getmore/command)
"ns" : "<database>.<collection>",//操作的命名空间,如:数据库名.集合名
"query" : {//具体的操作语句
},
"client" : "<host>:<outgoing>",//连接的客户端信息
"desc" : "conn57683",//数据库连接描述
"threadId" : "0x7f04a637b700",//线程id
"connectionId" : 57683,//数据库连接id
"locks" : {//锁的相关信息
"^" : "w",
"^local" : "W",
"^<database>" : "W"
},
"waitingForLock" : false,//是否在等待并获取锁,
"msg": "<string>"
"numYields" : 0,
"progress" : {
"done" : <number>,
"total" : <number>
}
"lockStats" : {
"timeLockedMicros" : {//此操作获得以下锁后,把持的微秒时间
"R" : NumberLong(),//整个mongodb服务实例的全局读锁
"W" : NumberLong(),//整个mongodb服务实例的全局写锁
"r" : NumberLong(),//某个数据库实例的读锁
"w" : NumberLong() //某个数据库实例的写锁
},
"timeAcquiringMicros" : {//此操作为了获得以下的锁,而耗费等待的微秒时间
"R" : NumberLong(),//整个mongodb服务实例的全局读锁
"W" : NumberLong(),//整个mongodb服务实例的全局写锁
"r" : NumberLong(),//某个数据库实例的读锁
"w" : NumberLong()//某个数据库实例的写锁
}
}
},
..... ]
}
1.4.3 MongoDB优化器profile
在MySQL 中,慢查询日志是经常作为我们优化数据库的依据,那在MongoDB 中是否有类似的功能呢?答案是肯定的,那就是MongoDB Database Profiler。
1.开启profiling功能
有两种方式可以控制 Profiling 的开关和级别,第一种是直接在启动参数里直接进行设置。启动MongoDB 时加上–profile=级别 即可。也可以在客户端调用db.setProfilingLevel(级别) 命令来实时配置,Profiler 信息保存在system.profile 中。我们可以通过db.getProfilingLevel()命令来获取当前的Profile 级别,类似如下操作:
db.setProfilingLevel(2);
上面profile 的级别可以取0,1,2 三个值,他们表示的意义如下:
0 – 不开启
1 – 记录慢命令 (默认为>100ms)
2 – 记录所有命令
Profile 记录在级别1 时会记录慢命令,那么这个慢的定义是什么?上面我们说到其默认为100ms,当然有默认就有设置,其设置方法和级别一样有两种,一种是通过添加 –slowms 启动参数配置。第二种是调用db.setProfilingLevel 时加上第二个参数:
db.setProfilingLevel( level , slowms )
db.setProfilingLevel( 1 , 10 );
2.查看 Profile的设置级别
db.getProfilingLevel()
> db.setProfilingLevel(1)
{ "was" : 2, "slowms" : 100, "sampleRate" : 1, "ok" : 1 }
> db.getProfilingLevel()
1
>
3.查询 Profiling 记录
与MySQL的慢查询日志不同,Mongo Profile 记录是直接存在系统db里的,记录位置 system.profile ,所以,我们只要查询这个Collection的记录就可以获取到我们的 Profile 记录了。
慢查询(system.profile)说明
详细信息见《MongoDB分析工具之二:MongoDB分析器Profile》
二、性能问题排查
2.1、mongodb client端报错,感觉像连接数配置小了
mongoDB server端定位方法:
查看总的连接数,因为mongoDB 默认的最大连接数为820.
netstat -nat | grep -i "27017" | wc -l
netstat -nt|grep 27017|wc -l
或者:
到/data/mongodb/mongos/log
查看mongoDB的日志文件:
mongos.diagnostic.data mongos.log
2.2、设置mongoDB server的最大连接数
修改mongodb最大连接数
在启动里边加参数 --maxConns=20000或者在 /etc/mongod.cnf (我自己见的配置文件添加 maxConns=20000)
重启mongodb
如果当前mongodb最大连接数没有变成20000,排查你service mongodb启动的脚本,如果脚本有 ulimit -n 12000,修改成30000,
如果修改成20000,貌似最大连接数也不到20000,这里具体原因没查,我的脚本是 /etc/init.d/mongod
还有一个地方可能影响到mongodb最大连接数,Linux系统默认一个进程最大打开文件数目是1024,修改rc.local
vi /etc/rc.local
很好我这里的一个进程最大打开文件数目远远大于20000
2.3、报错:because there was a socket exception raised by this connection.
回答1:
After few tries I've found out that it was a problem with the Azure's Load Balancer.
After 60s of inactivity it will disconnect any pending TCP connection.
After further digging I've found this post of the MongoDB diagnostics FAQ, and I've set the tcp keepalive to 120s:
sudo sysctl -w net.ipv4.tcp_keepalive_time=<value>
and I've also set the socketKeepAlive of the MongoClient to true:
MongoClientOptions.Builder options = MongoClientOptions.builder();
options.socketKeepAlive(true);
mongoClient = new MongoClient(mongoAddress, options.build());
After these fixes the issue seems gone!
回答2:
If you experience socket errors between clients and servers or between members of a sharded cluster or replica set that do not have other reasonable causes, check the TCP keepalive value (for example, the tcp_keepalive_time value on Linux systems). A common keepalive period is 7200 seconds (2 hours); however, different distributions and macOS may have different settings.
For MongoDB, you will have better results with shorter keepalive periods, on the order of 120 seconds (two minutes).
where u have installed mongodb u have to simply run this command on Linux
sudo sysctl -w net.ipv4.tcp_keepalive_time=120
mtop – 针对 MongoDB 的 top 命令
这是一个基于MongoDB Python 客户端 pymongo 的小程序,他使你可以像用操作系统的top命令一样,实时观察你的MongoDB 的状态。
1.安装 pymongo 及 mtop
下载安装pymongo:http://api.mongodb.org/python/1.9%2B/installation.html
如果有easy_install 那安装起来就比较easy了~只需要:
$ easy_install pymongo
下载安装mtop:https://github.com/beaufour/mtop
2.运行mtop
./mtop.py -s localhost:27017 -d 2000
3.参数说明
- -s:表示MongoDB 所在的机器及端口
- -d:刷新的间隔,以毫秒计所以上面表示每两秒一次。