8月 122013
 

jstatd
启动jvm监控服务。它是一个基于rmi的应用,向远程机器提供本机jvm应用程序的信息。默认端口1099。
实例:jstatd -J-Djava.security.policy=my.policy

my.policy文件需要自己建立,内如如下:
grant codebase "file:$JAVA_HOME/lib/tools.jar" {
 permission java.security.AllPermission;
};
这是安全策略文件,因为jdk对jvm做了jaas的安全检测,所以我们必须设置一些策略,使得jstatd被允许作网络操作

jps
列出所有的jvm实例
实例:
jps
列出本机所有的jvm实例

jps 192.168.0.77
列出远程服务器192.168.0.77机器所有的jvm实例,采用rmi协议,默认连接端口为1099
(前提是远程服务器提供jstatd服务)

输出内容如下:
jones@jones:~/data/ebook/java/j2se/jdk_gc$ jps
6286 Jps
6174  Jstat

jconsole
一个图形化界面,可以观察到java进程的gc,class,内存等信息。虽然比较直观,但是个人还是比较倾向于使用jstat命令(在最后一部分会对jstat作详细的介绍)。

jinfo(linux下特有)
观察运行中的java程序的运行环境参数:参数包括Java System属性和JVM命令行参数
实例:jinfo 2083
其中2083就是java进程id号,可以用jps得到这个id号。
输出内容太多了,不在这里一一列举,大家可以自己尝试这个命令。

jstack(linux下特有)
可以观察到jvm中当前所有线程的运行情况和线程当前状态
jstack 2083
输出内容如下:


 

jmap(linux下特有,也是很常用的一个命令)
观察运行中的jvm物理内存的占用情况。
参数如下:
-heap:打印jvm heap的情况
-histo:打印jvm heap的直方图。其输出信息包括类名,对象数量,对象占用大小。
-histo:live :同上,但是只答应存活对象的情况
-permstat:打印permanent generation heap情况

命令使用:
jmap -heap 2083
可以观察到New Generation(Eden Space,From Space,To Space),tenured generation,Perm Generation的内存使用情况
输出内容:


 

jmap -histo 2083 | jmap -histo:live 2083
可以观察heap中所有对象的情况(heap中所有生存的对象的情况)。包括对象数量和所占空间大小。
输出内容:


 
写个脚本,可以很快把占用heap最大的对象找出来,对付内存泄漏特别有效。

jstat
最后要重点介绍下这个命令。
这是jdk命令中比较重要,也是相当实用的一个命令,可以观察到classloader,compiler,gc相关信息
具体参数如下:
-class:统计class loader行为信息
-compile:统计编译行为信息
-gc:统计jdk gc时heap信息
-gccapacity:统计不同的generations(不知道怎么翻译好,包括新生区,老年区,permanent区)相应的heap容量情况
-gccause:统计gc的情况,(同-gcutil)和引起gc的事件
-gcnew:统计gc时,新生代的情况
-gcnewcapacity:统计gc时,新生代heap容量
-gcold:统计gc时,老年区的情况
-gcoldcapacity:统计gc时,老年区heap容量
-gcpermcapacity:统计gc时,permanent区heap容量
-gcutil:统计gc时,heap情况
-printcompilation:不知道干什么的,一直没用过。

一般比较常用的几个参数是:
jstat -class 2083 1000 10 (每隔1秒监控一次,一共做10次)
输出内容含义如下:

Loaded Number of classes loaded.
Bytes Number of Kbytes loaded.
Unloaded Number of classes unloaded.
Bytes Number of Kbytes unloaded.
Time Time spent performing class load and unload operations.

 

 

 

jstat -gc 2083 2000 20(每隔2秒监控一次,共做10)
输出内容含义如下:

S0C Current survivor(存活的) space 0 capacity (KB).
EC Current eden space capacity (KB).
EU Eden space utilization (KB).
OC Current old space capacity (KB).
OU Old space utilization (KB).
PC Current permanent space capacity (KB).
PU Permanent space utilization (KB).
YGC Number of young generation GC Events.
YGCT Young generation garbage collection time.
FGC Number of full GC events.
FGCT Full garbage collection time.
GCT Total garbage collection time.

 

 

 

 

 

 

 

 

 

 

 

 

 

输出内容:


 

 

 监控内存使用情况 参数 (查看内存溢出相对有用)

jstat –gccause 2083 5000 (每隔5秒监控一次)
输出内容含义如下:

 

 

S0 Survivor space 0 utilization as a percentage of the space's current capacity.
S1 Survivor space 1 utilization as a percentage of the space's current capacity.
E Eden space utilization as a percentage of the space's current capacity.
O Old space utilization as a percentage of the space's current capacity.
P Permanent space utilization as a percentage of the space's current capacity.
YGC Number of young generation GC events.
YGCT Young generation garbage collection time.
FGC Number of full GC events.
FGCT Full garbage collection time.
GCT Total garbage collection time.
LGCC Cause of last Garbage Collection.
GCC Cause of current Garbage Collection.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


如果能熟练运用这些命令,尤其是在linux下,那么完全可以代替jprofile等监控工具了,谁让它收费呢。呵呵。
用命令的好处就是速度快,并且辅助于其他命令,比如grep gawk sed等,可以组装多种符合自己需求的工具。

转自: http://dolphin-ygj.iteye.com/blog/366216

4月 122013
 

概述

对于大型 JAVA 应用程序来说,再精细的测试也难以堵住所有的漏洞,即便我们在测试阶段进行了大量卓有成效的工作,很多问题还是会在生产环境下暴露出来,并且很难在测试环境中进行重现。JVM 能够记录下问题发生时系统的部分运行状态,并将其存储在堆转储 (Heap Dump) 文件中,从而为我们分析和诊断问题提供了重要的依据。

通常内存泄露分析被认为是一件很有难度的工作,一般由团队中的资深人士进行。不过,今天我们要介绍的 MAT(Eclipse Memory Analyzer)被认为是一个“傻瓜式“的堆转储文件分析工具,你只需要轻轻点击一下鼠标就可以生成一个专业的分析报告。和其他内存泄露分析工具相比,MAT 的使用非常容易,基本可以实现一键到位,即使是新手也能够很快上手使用。

MAT 的使用是如此容易,你是不是也很有兴趣来亲自感受下呢,那么第一步我们先来安装 MAT。

 

准备环境和测试数据

我们使用的是 Eclipse Memory Analyzer V0.8,Sun JDK 6

安装 MAT

和其他插件的安装非常类似,MAT 支持两种安装方式,一种是“单机版“的,也就是说用户不必安装 Eclipse IDE 环境,MAT 作为一个独立的 Eclipse RCP 应用运行;另一种是”集成版“的,也就是说 MAT 也可以作为 Eclipse IDE 的一部分,和现有的开发平台集成。

集成版的安装需要借助 Update Manager。

如图 1 所示,首先通过 Help -> Software Updates… 启动软件更新管理向导。



图 1. 安装插件第一步

图 1. 安装插件第一步 

选择“Available Software“然后按如图 2 所示的方式添加 MAT 的更新地址 http://download.eclipse.org/technology/mat/0.8/update-site/



图 2. 安装插件第二步

图 2. 安装插件第二步 

如图 3 所示,接下来选择你想要安装的 MAT 的功能点,需要注意的是 Memory Analyzer (Chart) 这个功能是一个可选的安装项目,它主要用来生成相关的报表,不过如果需要用到这个功能,你还需要额外的安装 BIRT Chart Engine。



图 3. 安装插件第三步

图 3. 安装插件第三步 

插件安装完毕,你还需要重新启动 Eclipse 的工作平台。

比较而言,单机版的安装方式非常简单,用户只需要下载相应的安装包,然后解压缩即可运行,这也是被普遍采用的一种安装方式。在下面的例子里,我们使用的也是单机版的 MAT。具体的下载要求和地址可参见其产品下载页面:http://www.eclipse.org/mat/downloads.php

另外,如果你需要用 MAT 来分析 IBM JVM 生成的 dump 文件的话,还需要额外安装 IBM Diagnostic Tool Framework ,具体的下载和安装配置步骤请参见:http://www.ibm.com/developerworks/java/jdk/tools/dtfj.html

配置环境参数

安装完成之后,为了更有效率的使用 MAT,我们还需要做一些配置工作。因为通常而言,分析一个堆转储文件需要消耗很多的堆空间,为了保证分析的效率和性能,在有条件的情况下,我们会建议分配给 MAT 尽可能多的内存资源。你可以采用如下两种方式来分配内存更多的内存资源给 MAT。

一种是修改启动参数 MemoryAnalyzer.exe -vmargs -Xmx4g

另一种是编辑文件 MemoryAnalyzer.ini,在里面添加类似信息 -vmargs – Xmx4g。

至此,MAT 就已经成功地安装配置好了,开始进入实战吧。

获得堆转储文件

巧妇难为无米之炊,我们首先需要获得一个堆转储文件。为了方便,本文采用的是 Sun JDK 6。通常来说,只要你设置了如下所示的 JVM 参数:

-XX:+HeapDumpOnOutOfMemoryError

JVM 就会在发生内存泄露时抓拍下当时的内存状态,也就是我们想要的堆转储文件。

如果你不想等到发生崩溃性的错误时才获得堆转储文件,也可以通过设置如下 JVM 参数来按需获取堆转储文件。

-XX:+HeapDumpOnCtrlBreak

除此之外,还有很多的工具,例如 JMap,JConsole 都可以帮助我们得到一个堆转储文件。本文实例就是使用 JMap 直接获取了 Eclipse Galileo 进程的堆转储文件。您可以使用如下命令:

JMap -dump:format=b,file=<dumpfile> <pid>

不过,您需要了解到,不同厂家的 JVM 所生成的堆转储文件在数据存储格式以及数据存储内容上有很多区别, MAT 不是一个万能工具,它并不能处理所有类型的堆存储文件。但是比较主流的厂家和格式,例如 Sun, HP, SAP 所采用的 HPROF 二进制堆存储文件,以及 IBM 的 PHD 堆存储文件等都能被很好的解析(您需要安装额外的插件,请参考 相关说明,本文不作详细解释)。

万事俱备,接下来,我们就可以开始体验一键式的堆存储分析功能了。

 

生成分析报告

首先,启动前面安装配置好的 Memory Analyzer tool , 然后选择菜单项 File- Open Heap Dump 来加载需要分析的堆转储文件。文件加载完成后,你可以看到如图 4 所示的界面:



图 4. 概览

图 4. 概览 

通过上面的概览,我们对内存占用情况有了一个总体的了解。先检查一下 MAT 生成的一系列文件。



图 5. 文件列表

图 5. 文件列表 

可以看到 MAT 工具提供了一个很贴心的功能,将报告的内容压缩打包到一个 zip 文件,并把它存放到原始堆转储文件的存放目录下,这样如果您需要和同事一起分析这个内存问题的话,只需要把这个小小的 zip 包发给他就可以了,不需要把整个堆文件发给他。并且整个报告是一个 HTML 格式的文件,用浏览器就可以轻松打开。

接下来我们就可以来看看生成的报告都包括什么内容,能不能帮我们找到问题所在吧。您可以点击工具栏上的 Leak Suspects 菜单项来生成内存泄露分析报告,也可以直接点击饼图下方的 Reports->Leak Suspects 链接来生成报告。



图 6. 工具栏菜单

图 6. 工具栏菜单 

 

分析三步曲

通常我们都会采用下面的“三步曲”来分析内存泄露问题:

首先,对问题发生时刻的系统内存状态获取一个整体印象。

第二步,找到最有可能导致内存泄露的元凶,通常也就是消耗内存最多的对象

接下来,进一步去查看这个内存消耗大户的具体情况,看看是否有什么异常的行为。

下面将用一个基本的例子来展示如何采用“三步曲”来查看生产的分析报告。

查看报告之一:内存消耗的整体状况



图 7. 内存泄露分析报告

图 7. 内存泄露分析报告 

如图 7 所示,在报告上最醒目的就是一张简洁明了的饼图,从图上我们可以清晰地看到一个可疑对象消耗了系统 99% 的内存。

在图的下方还有对这个可疑对象的进一步描述。我们可以看到内存是由 java.util.Vector 的实例消耗的,com.ibm.oti.vm.BootstrapClassLoader 负责这个对象的加载。这段描述非常短,但我相信您已经可以从中找到很多线索了,比如是哪个类占用了绝大多数的内存,它属于哪个组件等等。

接下来,我们应该进一步去分析问题,为什么一个 Vector 会占据了系统 99% 的内存,谁阻止了垃圾回收机制对它的回收。

查看报告之二:分析问题的所在

首先我们简单回顾下 JAVA 的内存回收机制,内存空间中垃圾回收的工作由垃圾回收器 (Garbage Collector,GC) 完成的,它的核心思想是:对虚拟机可用内存空间,即堆空间中的对象进行识别,如果对象正在被引用,那么称其为存活对象,反之,如果对象不再被引用,则为垃圾对象,可以回收其占据的空间,用于再分配。

在垃圾回收机制中有一组元素被称为根元素集合,它们是一组被虚拟机直接引用的对象,比如,正在运行的线程对象,系统调用栈里面的对象以及被 system class loader 所加载的那些对象。堆空间中的每个对象都是由一个根元素为起点被层层调用的。因此,一个对象还被某一个存活的根元素所引用,就会被认为是存活对象,不能被回收,进行内存释放。因此,我们可以通过分析一个对象到根元素的引用路径来分析为什么该对象不能被顺利回收。如果说一个对象已经不被任何程序逻辑所需要但是还存在被根元素引用的情况,我们可以说这里存在内存泄露。

现在,让我们开始真正的寻找内存泄露之旅,点击“Details ”链接,可以看到如图 8 所示对可疑对象 1 的详细分析报告。



图 8. 可疑对象 1 的详细分析报告

图 8. 可疑对象 1 的详细分析报告 

  1. 我们查看下从 GC 根元素到内存消耗聚集点的最短路径:



图 9. 从根元素到内存消耗聚集点的最短路径

图 9. 从根元素到内存消耗聚集点的最短路径 

我们可以很清楚的看到整个引用链,内存聚集点是一个拥有大量对象的集合,如果你对代码比较熟悉的话,相信这些信息应该能给你提供一些找到内存泄露的思路了。

接下来,我们再继续看看,这个对象集合里到底存放了什么,为什么会消耗掉如此多的内存。



图 10. 内存消耗聚集对象信息

图 10. 内存消耗聚集对象信息 

在这张图上,我们可以清楚的看到,这个对象集合中保存了大量 Person 对象的引用,就是它导致的内存泄露。

至此,我们已经拥有了足够的信息去寻找泄露点,回到代码,我们发现,是下面的代码导致了内存泄露 :



清单 1. 内存泄漏的代码段


 while (1<2)
 {

	 Person person = new Person("name","address",i);
	 v.add(person);
	 person = null;
 }

 

 

总结

从上面的例子我们可以看到用 MAT 来进行堆转储文件分析,寻找内存泄露非常简单,尤其是对于新手而言,这是一个很好的辅助分析工具。但是,MAT 绝对不仅仅是一个“傻瓜式”内存分析工具,它还提供很多高级功能,比如 MAT 支持用 OQL(Object Query Language)对 heap dump 中的对象进行查询,支持对线程的分析等,有关这些功能的使用可以参考 MAT 的帮助文档。

Redis服务端状态与性能监控命令

 redis  Redis服务端状态与性能监控命令已关闭评论
4月 052013
 

1、redis-benchmark 

redis基准信息,redis服务器性能检测 



redis-benchmark -h localhost -p 6379 -c 100 -n 100000 

100个并发连接,100000个请求,检测host为localhost 端口为6379的redis服务器性能 

 

  1. [root@Architect redis-1.2.6]# redis-benchmark -h localhost -p 6379 -c 100 -n 100000  
  2. ====== PING ======  
  3.   10001 requests completed in 0.41 seconds  
  4.   50 parallel clients  
  5.   3 bytes payload  
  6.   keep alive: 1  
  7.   
  8. 0.01<= 0 milliseconds  
  9. 23.09<= 1 milliseconds  
  10. 85.82<= 2 milliseconds  
  11. 95.60<= 3 milliseconds  
  12. 97.20<= 4 milliseconds  
  13. 97.96<= 5 milliseconds  
  14. 98.83<= 6 milliseconds  
  15. 99.41<= 7 milliseconds  
  16. 99.70<= 8 milliseconds  
  17. 99.99<= 9 milliseconds  
  18. 100.00<= 12 milliseconds  
  19. 24274.27 requests per second  





2、redis-cli 



redis-cli -h localhost -p 6380 monitor 

Dump all the received requests in real time; 
监控host为localhost,端口为6380,redis的连接及读写操作
 

 

  1. [root@Architect redis-1.2.6]# redis-cli -h localhost -p 6380 monitor  
  2. +OK  
  3. +1289800615.808225 "monitor"  
  4. +1289800615.839079 "GET" "name"  
  5. +1289800615.853694 "PING"  
  6. +1289800615.853783 "PING"  
  7. +1289800615.854646 "PING"  
  8. +1289800615.854974 "PING"  
  9. +1289800615.857693 "PING"  
  10. +1289800615.866862 "PING"  
  11. +1289800615.871944 "PING"  





redis-cli -h localhost -p 6380 info 

Provide information and statistics about the server ; 
提供host为localhost,端口为6380,redis服务的统计信息
 

 

  1. [root@Architect redis-1.2.6]# redis-cli -h localhost -p 6380 info  
  2. redis_version:2.0.4  
  3. redis_git_sha1:00000000  
  4. redis_git_dirty:0  
  5. arch_bits:32  
  6. multiplexing_api:epoll  
  7. process_id:21990  
  8. uptime_in_seconds:490580  
  9. uptime_in_days:5  
  10. connected_clients:103  
  11. connected_slaves:0  
  12. blocked_clients:0  
  13. used_memory:4453240  
  14. used_memory_human:4.25M  
  15. changes_since_last_save:200  
  16. bgsave_in_progress:0  
  17. last_save_time:1290394640  
  18. bgrewriteaof_in_progress:0  
  19. total_connections_received:809  
  20. total_commands_processed:44094018  
  21. expired_keys:0  
  22. hash_max_zipmap_entries:64  
  23. hash_max_zipmap_value:512  
  24. pubsub_channels:0  
  25. pubsub_patterns:0  
  26. vm_enabled:0  
  27. role:slave  
  28. master_host:localhost  
  29. master_port:6379  
  30. master_link_status:up  
  31. master_last_io_seconds_ago:18  
  32. db0:keys=1319,expires=0  





3、redis-stat 



redis-stat host localhost port 6380 overview 

Print general information about a Redis instance; 
实时打印出host为localhost,端口为6380,redis实例的总体信息
 

 

  1. [root@Architect redis-1.2.6]# redis-stat port 6380 overview  
  2.  ——- data —— ———— load —————————– – childs –  
  3.  keys      used-mem  clients   requests            connections  
  4.  1319      5.37M     103       44108021 (+44108021810                 
  5.  1319      5.38M     103       44108124 (+103    810                 
  6.  1319      5.38M     103       44108225 (+101    810                 
  7.  1319      5.39M     103       44108326 (+101    810                 
  8.  1319      5.40M     103       44108427 (+101    810                 
  9.  1319      5.41M     103       44108528 (+101    810                 





redis-stat host localhost port 6380 overview 

Measure Redis server latency; 
输出host为localhost,端口为6380,redis服务中每个请求的响应时长
 

 

  1. [root@Architect redis-1.2.6]# redis-stat port 6380 latency  
  2. 10.16 ms  
  3. 20.11 ms  
  4. 30.15 ms  
  5. 40.11 ms  
  6. 50.18 ms  
  7. 60.14 ms  

监控mongo 状态慢查询

 mongo  监控mongo 状态慢查询已关闭评论
3月 192013
 

mongostat详解

mongostat是mongdb自带的状态检测工具,在命令行下使用。它会间隔固定时间获取mongodb的当前运行状态,并输出。如果你发现数据库突然变慢或者有其他问题的话,你第一手的操作就考虑采用mongostat来查看mongo的状态。

它的输出有以下几列:

  • inserts/s 每秒插入次数
  • query/s 每秒查询次数
  • update/s 每秒更新次数
  • delete/s 每秒删除次数
  • getmore/s 每秒执行getmore次数
  • command/s 每秒的命令数,比以上插入、查找、更新、删除的综合还多,还统计了别的命令
  • flushs/s 每秒执行fsync将数据写入硬盘的次数。
  • mapped/s 所有的被mmap的数据量,单位是MB,
  • vsize 虚拟内存使用量,单位MB
  • res 物理内存使用量,单位MB
  • faults/s 每秒访问失败数(只有Linux有),数据被交换出物理内存,放到swap。不要超过100,否则就是机器内存太小,造成频繁swap写入。此时要升级内存或者扩展
  • locked % 被锁的时间百分比,尽量控制在50%以下吧
  • idx miss % 索引不命中所占百分比。如果太高的话就要考虑索引是不是少了
  • q t|r|w 当Mongodb接收到太多的命令而数据库被锁住无法执行完成,它会将命令加入队列。这一栏显示了总共、读、写3个队列的长度,都为0的话表示mongo毫无压力。高并发时,一般队列值会升高。
  • conn 当前连接数
  • time 时间戳

使用profiler

类似于MySQL的slow log, MongoDB可以监控所有慢的以及不慢的查询。

Profiler默认是关闭的,你可以选择全部开启,或者有慢查询的时候开启。

 
> use test
switched to db test
> db.setProfilingLevel(2);
{"was" : 0 , "slowms" : 100, "ok" : 1} // "was" is the old setting
> db.getProfilingLevel()

查看Profile日志

 
> db.system.profile.find().sort({$natural:-1})
{"ts" : "Thu Jan 29 2009 15:19:32 GMT-0500 (EST)" , "info" :
"query test.$cmd ntoreturn:1 reslen:66 nscanned:0 query: { profile: 2 } nreturned:1 bytes:50" ,
"millis" : 0} ...

3个字段的意义

  • ts:时间戳
  • info:具体的操作
  • millis:操作所花时间,毫秒

不多说,此处有官方文档。注意,造成满查询可能是索引的问题,也可能是数据不在内存造成因此磁盘读入造成。

使用Web控制台

Mongodb自带了Web控制台,默认和数据服务一同开启。他的端口在Mongodb数据库服务器端口的基础上加1000,如果是默认的Mongodb数据服务端口(Which is 27017),则相应的Web端口为28017

这个页面可以看到

  • 当前Mongodb的所有连接
  • 各个数据库和Collection的访问统计,包括:Reads, Writes, Queries, GetMores ,Inserts, Updates, Removes
  • 写锁的状态
  • 以及日志文件的最后几百行(CentOS+10gen yum 安装的mongodb默认的日志文件位于/var/log/mongo/mongod.log)

可以参考右边的截图

db.stat()

获取当前数据库的信息,比如Obj总数、数据库总大小、平均Obj大小等

 
> use test
switched to db test
> db.stats()
{
 "collections" : 9,
 "objects" : 4278845,
 "avgObjSize" : 224.56603031892953,
 "dataSize" : 960883236,
 "storageSize" : 1195438080,
 "numExtents" : 59,
 "indexes" : 13,
 "indexSize" : 801931264,
 "fileSize" : 6373244928,
 "ok" : 1
}

db.serverStatus()

获取服务器的状态

 
{
 "version" : "1.6.5",
 "uptime" : 7208469,
 "uptimeEstimate" : 7138829,
 "localTime" : "Wed Oct 26 2011 22:23:07 GMT+0800 (CST)",
 "globalLock" : {
  "totalTime" : 7208469556704,
  "lockTime" : 4959693717,
  "ratio" : 0.000688036992871448,
  "currentQueue" : {
   "total" : 0,
   "readers" : 0,
   "writers" : 0
  }
 },
 "mem" : {
  "bits" : 64,
  "resident" : 3131,
  "virtual" : 6172,
  "supported" : true,
  "mapped" : 4927
 },
 "connections" : {
  "current" : 402,
  "available" : 2599
 },
 "extra_info" : {
  "note" : "fields vary by platform",
  "heap_usage_bytes" : 832531920,
  "page_faults" : 8757
 },
 "indexCounters" : {
  "btree" : {
   "accesses" : 2821726,
   "hits" : 2821725,
   "misses" : 1,
   "resets" : 0,
   "missRatio" : 3.543930204420982e-7
  }
 },
 "backgroundFlushing" : {
  "flushes" : 120133,
  "total_ms" : 73235923,
  "average_ms" : 609.6236920746173,
  "last_ms" : 1332,
  "last_finished" : "Wed Oct 26 2011 22:22:23 GMT+0800 (CST)"
 },
 "cursors" : {
  "totalOpen" : 0,
  "clientCursors_size" : 0,
  "timedOut" : 238392
 },
 "repl" : {
  "ismaster" : true
 },
 "opcounters" : {
  "insert" : 269351,
  "query" : 19331151,
  "update" : 14199331,
  "delete" : 1,
  "getmore" : 145575,
  "command" : 55982302
 },
 "asserts" : {
  "regular" : 0,
  "warning" : 0,
  "msg" : 0,
  "user" : 27,
  "rollovers" : 0
 },
 "ok" : 1
} 

需要关心的地方:

  • connections 当前连接和可用连接数,听过一个同行介绍过,mongodb最大处理到2000个连接就不行了(要根据你的机器性能和业务来设定),所以设大了没意义。设个合理值的话,到达这个值mongodb就拒绝新的连接请求,避免被太多的连接拖垮。
  • indexCounters:btree:misses 索引的不命中数,和hits的比例高就要考虑索引是否正确建立。你看我的”missRatio” : 3.543930204420982e-7,很健康吧。所以miss率在mongostat里面也可以看
  • 其他的都能自解释,也不是查看mongo健康状况的关键,就不说明了。

db.currentOp()

Mongodb 的命令一般很快就完成,但是在一台繁忙的机器或者有比较慢的命令时,你可以通过db.currentOp()获取当前正在执行的操作。

在没有负载的机器上,该命令基本上都是返回空的

 
> db.currentOp()
{ "inprog" : [ ] } 

以下是一个有负载的机器上得到的返回值样例:

 
{ "opid" : "shard3:466404288", "active" : false, "waitingForLock" : false, "op" : "query", "ns" :
 "sd.usersEmails", "query" : { }, "client_s" : "10.121.13.8:34473", "desc" : "conn" }, 

字段名字都能自解释。如果你发现一个操作太长,把数据库卡死的话,可以用这个命令杀死他

 
> db.killOp("shard3:466404288") 

MongoDB Monitoring Service

MongoDB Monitoring Service(MMS)是Mongodb厂商提供的监控服务,可以在网页和Android客户端上监控你的MongoDB状况。

转自:http://www.uml.org.cn/sjjm/201207063.asp?artid=37

关于 Java 性能监控您不知道的 5 件事(JConsole),第 1 部分(转)

 java  关于 Java 性能监控您不知道的 5 件事(JConsole),第 1 部分(转)已关闭评论
2月 202013
 

当应用程序性能受到损害时,大多数开发人员都惊慌失措,这在情理之中。跟踪 Java 应用程序瓶颈来源一直以来都是很麻烦的,因为 Java 虚拟机有黑盒效应,而且 Java 平台分析工具一贯就有缺陷。

然而,随着 Java 5 中 JConsole 的引入,一切都发生了改变。JConsole 是一个内置 Java 性能分析器,可以从命令行或在 GUI shell 中运行。它不是完美的,但是当尖头老板来问你关于性能的问题时,用它来应对还是绰绰有余的 — 这比查询 Papa Google 要好得多。

在本期 5 件事 系列中,我将向您展示 5 个方法,使您可以轻松地使用 JConsole(或者,它更高端的 “近亲” VisualVM )来监控 Java 应用程序性能和跟踪 Java 中的代码。

1. JDK 附带分析器

许多开发人员没有意识到从 Java 5 开始 JDK 中包含了一个分析器。JConsole(或者 Java 平台最新版本,VisualVM)是一个内置分析器,它同 Java 编译器一样容易启动。如果是从命令行启动,使 JDK 在 PATH 上,运行 jconsole 即可。如果从 GUI shell 启动,找到 JDK 安装路径,打开 bin 文件夹,双击 jconsole

当分析工具弹出时(取决于正在运行的 Java 版本以及正在运行的 Java 程序数量),可能会出现一个对话框,要求输入一个进程的 URL 来连接,也可能列出许多不同的本地 Java 进程(有时包含 JConsole 进程本身)来连接。

JConsole 或 VisualVM?

JConsole 从 Java 5 开始就随着 Java 平台版本一起发布,而 VisualVM 是在 NetBeans 基础上升级的一个分析器,在 Java 6 的更新版 12 中第一次发布。多数商店还没有更新到 Java 6 ,因此这篇文章主要介绍 JConsole 。然而,多数技巧和这两个分析器都有关。(注意:除了包含在 Java 6 中之外,VisualVM 还有一个独立版下载。下载 VisualVM,参见 参考资料。)

使用 JConsole 进行工作

在 Java 5 中,Java 进程并不是被设置为默认分析的,而是通过一个命令行参数 — -Dcom.sun.management.jmxremote — 在启动时告诉 Java 5 VM 打开连接,以便分析器可以找到它们;当进程被 JConsole 捡起时,您只能双击它开始分析。

分析器有自己的开销,因此最好的办法就是花点时间来弄清是什么开销。发现 JConsole 开销最简单的办法是,首先独自运行一个应用程序,然后在分析器下运行,并测量差异。(应用程序不能太大或者太小;我最喜欢使用 JDK 附带的 SwingSet2 样本。)因此,我使用 -verbose:gc 尝试运行 SwingSet2 来查看垃圾收集清理,然后运行同一个应用程序并将 JConsole 分析器连接到它。当 JConsole 连接好了之后,一个稳定的 GC 清理流出现,否则不会出现。这就是分析器的性能开销。

2. 远程连接进程

因为 Web 应用程序分析工具假设通过一个套接字进行连通性分析,您只需要进行少许配置来设置 JConsole(或者是基于 JVMTI 的分析器,就这点而言),监控/分析远程运行的应用程序。

如果 Tomcat 运行在一个名为 “webserve” 的机器上,且 JVM 已经启动了 JMX 并监听端口 9004,从 JConsole(或者任何 JMX 客户端)连接它需要一个 JMX URL “service:jmx:rmi:///jndi/rmi://webserver:9004/jmxrmi”。

基本上,要分析一个运行在远程数据中心的应用程序服务器,您所需要的仅仅是一个 JMX URL。更多关于使用 JMX 和 JConsole 远程监控和管理的信息,参见 参考资料。)

3. 跟踪统计

不要成为典型

发现应用程序代码中性能问题的常用响应多种多样,但也是可预测的。早期的 Java 编程人员对旧的 IDE 可能十分生气,并开始进行代码库中主要部分的代码复查,在源代码中寻找熟悉的 “红色标志”,像异步块、对象配额等等。随着编程经验的增加,开发人员可能会仔细研究 JVM 支持的 -X 标志,寻找优化垃圾收集器的方法。当然,对于新手,直接去 Google 查询,希望有其他人发现了 JVM 的神奇的 “make it go fast” 转换,避免重写代码。

从本质上来说,这些方法没什么错,但都是有风险的。对于一个性能问题最有效的响应就是使用一个分析器 — 现在它们内置在 Java 平台 ,我们确实没有理由不这样做!

JConsole 有许多对收集统计数据有用的选项卡,包括:

  • Memory:在 JVM 垃圾收集器中针对各个堆跟踪活动。
  • Threads:在目标 JVM 中检查当前线程活动。
  • Classes:观察 VM 已加载类的总数。

这些选项卡(和相关的图表)都是由每个 Java 5 及更高版本 VM 在 JMX 服务器上注册的 JMX 对象提供的,是内置到 JVM 的。一个给定 JVM 中可用 bean 的完整清单在 MBeans 选项卡上列出,包括一些元数据和一个有限的用户界面来查看数据或执行操作。(然而,注册通知是在 JConsole 用户界面之外。)

使用统计数据

假设一个 Tomcat 进程死于 OutOfMemoryError。如果您想要弄清楚发生了什么,打开 JConsole,单击 Classes 选项卡,过一段时间查看一次类计数。如果数量稳定上升,您可以假设应用程序服务器或者您的代码某个地方有一个 ClassLoader 漏洞,不久之后将耗尽 PermGen 空间。如果需要更进一步的确认问题,请看 Memory 选项卡。

 

4. 为离线分析创建一个堆转储

生产环境中一切都在快速地进行着,您可能没有时间花费在您的应用程序分析器上,相反地,您可以为 Java 环境中的每个事件照一个快照保存下来过后再看。在 JConsole 中您也可以这样做,在 VisualVM 中甚至会做得更好。

先找到 MBeans 选项卡,在其中打开 com.sun.management 节点,接着是 HotSpotDiagnostic 节点。现在,选择Operations,注意右边面板中的 “dumpHeap” 按钮。如果您在第一个(“字符串”)输入框中向 dumpHeap 传递一个文件名来转储,它将为整个 JVM 堆照一个快照,并将其转储到那个文件。

稍后,您可以使用各种不同的商业分析器来分析文件,或者使用 VisualVM 分析快照。(记住,VisualVM 是在 Java 6 中可用的,且是单独下载的。)

 

5. JConsole 并不是高深莫测的

作为一个分析器实用工具,JConsole 是极好的,但是还有更好的工具。一些分析插件附带分析器或者灵巧的用户界面,默认情况下比 JConsole 跟踪更多的数据。

JConsole 真正吸引人的是整个程序是用 “普通旧式 Java ” 编写的,这意味着任何 Java 开发人员都可以编写这样一个实用工具。事实上,JDK 其中甚至包括如何通过创建一个插件来定制 JConsole 的示例(参见 参考资料)。建立在 NetBeans 顶部的 VisualVM 进一步延伸了插件概念。

如果 JConsole(或者 VisualVM,或者其他任何工具)不符合您的需求,或者不能跟踪您想要跟踪的,或者不能按照您的方式跟踪,您可以编写属于自己的工具。如果您觉得 Java 代码很麻烦,Groovy 或 JRuby 或很多其他 JVM 语言都可以帮助您更快完成。

您真正需要的是一个快速而粗糙(quick-and-dirty)的由 JVM 连接的命令行工具,可以以您想要的方式确切地跟踪您感兴趣的数据。

 

结束语

Java 性能监控不止于 JConsole 或 VisualVM — 在 JDK 中隐藏着一整套工具,只是大多数开发人员并不知道。 本系列 中的下一篇文章将深入探究一些实验性的命令行工具,可以帮助您挖掘更多的您所需要的性能数据。因为这些工具通常只关注特殊数据,比一个完整的分析器更小更轻巧,所以它们的性能开销要小一些。

 

转自: http://www.ibm.com/developerworks/cn/java/j-5things7.html

关于 Java 性能监控您不知道的 5 件事(1. jps 2. jstat 3. jstack 4. jmap 5. jha),第 2 部分(转)

 java  关于 Java 性能监控您不知道的 5 件事(1. jps 2. jstat 3. jstack 4. jmap 5. jha),第 2 部分(转)已关闭评论
2月 202013
 

全功能内置分析器,如 JConsole 和 VisualVM 的成本有时比它们的性能费用还要高 — 尤其是在生产软件上运行的系统中。因此,在聚焦 Java 性能监控的第 2 篇文章中,我将介绍 5 个命令行分析工具,使开发人员仅关注运行的 Java 进程的一个方面。

JDK 包括很多命令行实用程序,可以用于监控和管理 Java 应用程序性能。虽然大多数这类应用程序都被标注为 “实验型”,在技术上不受支持,但是它们很有用。有些甚至是特定用途工具的种子材料,可以使用 JVMTI 或 JDI(参见 参考资料)建立。

1. jps (sun.tools.jps)

很多命令行工具都要求您识别您希望监控的 Java 进程。这与监控本地操作系统进程、同样需要一个程序识别器的同类工具没有太大区别。

“VMID” 识别器与本地操作系统进程识别器(“pid”)并不总是相同的,这就是我们需要 JDK jps 实用程序的原因。

在 Java 进程中使用 jps

与配置 JDK 的大部分工具及本文中提及的所有工具一样,可执行 jps 通常是一个围绕 Java 类或执行大多数工作的类集的一个薄包装。在 Windows® 环境下,这些工具是 .exe 文件,使用 JNI Invocation API 直接调用上面提及的类;在 UNIX® 环境下,大多数工具是一个 shell 脚本的符号链接,该脚本采用指定的正确类名称开始一个普通启动程序。

如果您希望在 Java 进程中使用 jps(或者任何其他工具)的功能 — Ant 脚本 — 仅在每个工具的 “主” 类上调用main() 相对容易。为了简化引用,类名称出现在每个工具名称之后的括号内。

jps — 名称反映了在大多数 UNIX 系统上发现的 ps 实用程序 — 告诉我们运行 Java 应用程序的 JVMID。顾名思义,jps 返回指定机器上运行的所有已发现的 Java 进程的 VMID。如果 jps 没有发现进程,并不意味着无法附加或研究 Java 进程,而只是意味着它并未宣传自己的可用性。

如果发现 Java 进程,jps 将列出启用它的命令行。这种区分 Java 进程的方法非常重要,因为只要涉及操作系统,所有的 Java 进程都被统称为 “java”。在大多数情况下,VMID 是值得注意的重要数字。

使用分析器开始

使用分析实用程序开始的最简单方法是使用一个如在demo/jfc/SwingSet2 中发现的 SwingSet2 演示一样的演示程序。这样就可以避免程序作为背景/监控程序运行时出现挂起的可能性。当您了解工具及其费用后,就可以在实际程序中进行试用。

加载演示应用程序后,运行 jps 并注意返回的 vmid。为了获得更好的效果,采用 -Dcom.sun.management.jmxremote 属性集启动 Java 进程。如果没有使用该设置,部分下列工具收集的部分数据可能不可用。

2. jstat (sun.tools.jstat)

jstat 实用程序可以用于收集各种各样不同的统计数据。jstat 统计数据被分类到 “选项” 中,这些选项在命令行中被指定作为第一参数。对于 JDK 1.6 来说,您可以通过采用命令 -options 运行 jstat 查看可用的选项清单。清单 1 中显示了部分选项:
清单 1. jstat 选项

-class
-compiler
-gc
-gccapacity
-gccause
-gcnew
-gcnewcapacity
-gcold
-gcoldcapacity
-gcpermcapacity
-gcutil
-printcompilation

 

实用程序的 JDK 记录(参见 参考资料)将告诉您清单 1 中每个选项返回的内容,但是其中大多数用于收集垃圾的收集器或者其部件的性能信息。-class 选项显示了加载及未加载的类(使其成为检测应用程序服务器或代码中 ClassLoader 泄露的重要实用程序,且 -compiler 和 -printcompilation 都显示了有关 Hotspot JIT 编译程序的信息。

默认情况下,jstat 在您核对信息时显示信息。如果您希望每隔一定时间拍摄快照,请在 -options 指令后以毫秒为单位指定间隔时间。jstat 将持续显示监控进程信息的快照。如果您希望 jstat 在终止前进行特定数量的快照,在间隔时间/时间值后指定该数字。

如果 5756 是几分钟前开始的运行 SwingSet2 程序的 VMID,那么下列命令将告诉 jstat 每 250 毫秒为 10 个佚代执行一次 gc 快照转储,然后停止:

jstat -gc 5756 250 10

 

请注意 Sun(现在的 Oracle)保留了在不进行任何预先通知的情况下更改各种选项的输出甚至是选项本身的权利。这是使用不受支持实用程序的缺点。请参看 Javadocs 了解 jstat 输出中每一列的全部细节。

3. jstack (sun.tools.jstack)

了解 Java 进程及其对应的执行线程内部发生的情况是一种常见的诊断挑战。例如,当一个应用程序突然停止进程时,很明显出现了资源耗尽,但是仅通过查看代码无法明确知道何处出现资源耗尽,且为什么会发生。

jstack 是一个可以返回在应用程序上运行的各种各样线程的一个完整转储的实用程序,您可以使用它查明问题。

采用期望进程的 VMID 运行 jstack 会产生一个堆转储。就这一点而言,jstack 与在控制台窗口内按 Ctrl-Break 键起同样的作用,在控制台窗口中,Java 进程正在运行或调用 VM 内每个 Thread 对象上的 Thread.getAllStackTraces() 或Thread.dumpStack()jstack 调用也转储关于在 VM 内运行的非 Java 线程的信息,这些线程作为 Thread 对象并不总是可用的。

jstack 的 -l 参数提供了一个较长的转储,包括关于每个 Java 线程持有锁的更多详细信息,因此发现(和 squash)死锁或可伸缩性 bug 是极其重要的。

4. jmap (sun.tools.jmap)

有时,您正在处理的问题是一个对象泄露,如一个 ArrayList (可能持有成千上万个对象)该释放时没有释放。另一个更普遍的问题是,看似从不会压缩的扩展堆,却有活跃的垃圾收集。

当您努力寻找一个对象泄露时,在指定时刻对堆及时进行拍照,然后审查其中内容非常有用。jmap 通过对堆拍摄快照来提供该功能的第一部分。然后您可以采用下一部分中描述的 jhat 实用程序分析堆数据。

与这里描述的其他所有实用程序一样,使用 jmap 非常简单。将 jmap 指向您希望拍快照的 Java 进程的 VMID,然后给予它部分参数,用来描述产生的结果文件。您要传递给 jmap 的选项包括转储文件的名称以及是否使用一个文本文件或二进制文件。二进制文件是最有用的选项,但是只有当与某一种索引工具 结合使用时 — 通过十六进制值的文本手动操作数百兆字节不是最好的方法。

随意看一下 Java 堆的更多信息,jmap 同样支持 -histo 选项。-histo 产生一个对象文本柱状图,现在在堆中大量引用,由特定类型消耗的字节总数分类。它同样给出了特定类型的总示例数量,支持部分原始计算,并猜测每个实例的相对成本。

不幸的是,jmap 没有像 jstat 一样的 period-and-max-count 选项,但是将 jmap(或 jmap.main())调用放入 shell 脚本或其他类的循环,周期性地拍摄快照相对简单。(事实上,这是加入 jmap 的一个好的扩展,不管是作为 OpenJDK 本身的源补丁,还是作为其他实用程序的扩展。)

5. jhat (com.sun.tools.hat.Main)

将堆转储至一个二进制文件后,您就可以使用 jhat 分析二进制堆转储文件。jhat 创建一个 HTTP/HTML 服务器,该服务器可以在浏览器中被浏览,提供一个关于堆的 object-by-object 视图,及时冻结。根据对象引用草率处理堆可能会非常可笑,您可以通过对总体混乱进行某种自动分析而获得更好的服务。幸运的是,jhat 支持 OQL 语法进行这样的分析。

例如,对所有含有超过 100 个字符的 String 运行 OQL 查询看起来如下:

select s from java.lang.String s where s.count >= 100

 

结果作为对象链接显示,然后展示该对象的完整内容,字段引用作为可以解除引用的其他链接的其他对象。OQL 查询同样可以调用对象的方法,将正则表达式作为查询的一部分,并使用内置查询工具。一种查询工具,referrers() 函数,显示了引用指定类型对象的所有引用。下面是寻找所有参考 File 对象的查询:

select referrers(f) from java.io.File f

 

您可以查找 OQL 的完整语法及其在 jhat 浏览器环境内 “OQL Help” 页面上的特性。将 jhat 与 OQL 相结合是对行为不当的堆进行对象调查的有效方法。

 

结束语

当您需要近距离观察 Java 进程内发生的事情时,JDK 的分析扩展会非常有用。本文中介绍的所有工具都可以从命令行中由其自己使用。它们还可以与 JConsole 或 VisualVM 有力地结合使用。JConsole 和 VisualVM 提供 Java 虚拟机的总体视图,jstat 和 jmap等有针对性的工具支持您对研究进行微调。

转自: http://www.ibm.com/developerworks/cn/java/j-5things8.html