副标题[/!--empirenews.page--]
1. 服务异常的处理流程
2. 负载
2.1 查看机器 cpu 的负载
top -b -n 1 |grep java|awk '{print "VIRT:"$5,"RES:"$6,"cpu:"$9"%","mem:"$10"%"}'
2.2 查找 cpu 占用率高的线程
- top -p 25603 -H
- printf 0x%x 25842
- jstack 25603 | grep 0x64f2
- cat /proc/interrupts
(1)CPU
(2)Memory
(3)IO
(4)Network
可以从以下几个方面监控CPU的信息:
(1)中断;
(2)上下文切换;
(3)可运行队列;
(4)CPU 利用率。
3. 内存
3.1 系统内存
free 命令
- [root@server ~]# free
- total used free shared buffers cached
- Mem: 3266180 3250000 10000 0 201000 3002000
- -/+ buffers/cache: 47000 3213000
- Swap: 2048276 80160 1968116
这里的默认显示单位是 kb。
各项指标解释
- total:总计物理内存的大小。
- used:已使用多大。
- free:可用有多少。
- Shared:多个进程共享的内存总额。
- buffers: 磁盘缓存的大小。
- cache:磁盘缓存的大小。
- -/+ buffers/cached): used:已使用多大,free:可用有多少。
- 已用内存 = 系统used memory - buffers - cached
- (47000 = 3250000-201000-3002000)
- 可用内存 = 系统free memory + buffers + cached
- (3213000 = 10000+201000+3002000)
什么是buffer/cache?
- buffer 指 Linux 内存的:Buffer cache,缓冲区缓
- cache 指 Linux内存中的:Page cache,页面缓存
page cache
page cache 主要用来作为文件系统上的文件数据的缓存来用,尤其是针对当进程对文件有 read/write 操作的时候。
如果你仔细想想的话,作为可以映射文件到内存的系统调用:mmap是不是很自然的也应该用到 page cache?在当前的系统实现里,page cache 也被作为其它文件类型的缓存设备来用,所以事实上 page cache 也负责了大部分的块设备文件的缓存工作。
buffer cache
buffer cache 主要用来在系统对块设备进行读写的时候,对块进行数据缓存的系统来使用。这意味着某些对块的操作会使用 buffer cache 进行缓存,比如我们在格式化文件系统的时候。
一般情况下两个缓存系统是一起配合使用的,比如当我们对一个文件进行写操作的时候,page cache 的内容会被改变,而 buffer cache 则可以用来将 page 标记为不同的缓冲区,并记录是哪一个缓冲区被修改了。这样,内核在后续执行脏数据的回写(writeback)时,就不用将整个 page 写回,而只需要写回修改的部分即可。
在当前的内核中,page cache 是针对内存页的缓存,说白了就是,如果有内存是以page进行分配管理的,都可以使用page cache作为其缓存来管理使用。
当然,不是所有的内存都是以页(page)进行管理的,也有很多是针对块(block)进行管理的,这部分内存使用如果要用到 cache 功能,则都集中到 buffer cache中来使用。(从这个角度出发,是不是buffer cache改名叫做block cache更好?)然而,也不是所有块(block)都有固定长度,系统上块的长度主要是根据所使用的块设备决定的,而页长度在X86 上无论是 32位还是 64位都是 4k。
3.2 进程内存
3.2.1 进程内存统计
/proc/[pid]/status
通过/proc//status可以查看进程的内存使用情况,包括虚拟内存大小(VmSize),物理内存大小(VmRSS),数据段大小(VmData),栈的大小(VmStk),代码段的大小(VmExe),共享库的代码段大小(VmLib)等等。
- Name: gedit /*进程的程序名*/
- State: S (sleeping) /*进程的状态信息,具体参见http://blog.chinaunix.net/u2/73528/showart_1106510.html*/
- Tgid: 9744 /*线程组号*/
- Pid: 9744 /*进程pid*/
- PPid: 7672 /*父进程的pid*/
- TracerPid: 0 /*跟踪进程的pid*/
- VmPeak: 60184 kB /*进程地址空间的大小*/
- VmSize: 60180 kB /*进程虚拟地址空间的大小reserved_vm:进程在预留或特殊的内存间的物理页*/
- VmLck: 0 kB /*进程已经锁住的物理内存的大小.锁住的物理内存不能交换到硬盘*/
- VmHWM: 18020 kB /*文件内存映射和匿名内存映射的大小*/
- VmRSS: 18020 kB /*应用程序正在使用的物理内存的大小,就是用ps命令的参数rss的值 (rss)*/
- VmData: 12240 kB /*程序数据段的大小(所占虚拟内存的大小),存放初始化了的数据*/
- VmStk: 84 kB /*进程在用户态的栈的大小*/
- VmExe: 576 kB /*程序所拥有的可执行虚拟内存的大小,代码段,不包括任务使用的库 */
- VmLib: 21072 kB /*被映像到任务的虚拟内存空间的库的大小*/
- VmPTE: 56 kB /*该进程的所有页表的大小*/
- Threads: 1 /*共享使用该信号描述符的任务的个数*/
3.2.2 JVM 内存分配
java内存组成介绍:堆(Heap)和非堆(Non-heap)内存
按照官方的说法:“Java 虚拟机具有一个堆,堆是运行时数据区域,所有类实例和数组的内存均从此处分配。堆是在 Java 虚拟机启动时创建的。” “在JVM中堆之外的内存称为非堆内存(Non-heap memory)”。
可以看出JVM主要管理两种类型的内存:堆和非堆。
简单来说堆就是Java代码可及的内存,是留给开发人员使用的;非堆就是JVM留给自己用的。
所以方法区、JVM内部处理或优化所需的内存(如JIT编译后的代码缓存)、每个类结构(如运行时常数池、字段和方法数据)以及方法和构造方法 的代码都在非堆内存中。
- JVM 本身需要的内存,包括其加载的第三方库以及这些库分配的内存
- NIO 的 DirectBuffer 是分配的 native memory
- 内存映射文件,包括 JVM 加载的一些 JAR 和第三方库,以及程序内部用到的。上面 pmap 输出的内容里,有一些静态文件所占用的大小不在 Java 的 heap 里,因此作为一个Web服务器,赶紧把静态文件从这个Web服务器中人移开吧,放到nginx或者CDN里去吧。
- JIT, JVM会将Class编译成native代码,这些内存也不会少,如果使用了Spring的AOP,CGLIB会生成更多的类,JIT的内存开销也会随之变大,而且Class本身JVM的GC会将其放到Perm Generation里去,很难被回收掉,面对这种情况,应该让JVM使用ConcurrentMarkSweep GC,并启用这个GC的相关参数允许将不使用的class从Perm Generation中移除, 参数配置:
- -XX:+UseConcMarkSweepGC -X:+CMSPermGenSweepingEnabled -X:+CMSClassUnloadingEnabled,如果不需要移除而Perm Generation空间不够,可以加大一点:-X:PermSize=256M -X:MaxPermSize=512M
- JNI,一些JNI接口调用的native库也会分配一些内存,如果遇到JNI库的内存泄露,可以使用valgrind等内存泄露工具来检测
- 线程栈,每个线程都会有自己的栈空间,如果线程一多,这个的开销就很明显了
- jmap/jstack 采样,频繁的采样也会增加内存占用,如果你有服务器健康监控,记得这个频率别太高,否则健康监控变成致病监控了。
(编辑:西双版纳站长网)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|