生产环境监测
服务器性能日常监测
- 服务器平均负载是什么意思?
服务器平均负载指的是在单位时间内系统处于可运行状态或不可中断状态的进程的平均数,即活跃平均数,它与CPU和使用率没有直接关系。
(1)不可运行状态指的是 正在等待某些IO访问且不可以被打断的进程,例如等待对磁盘进行I/O进程访问
(2)可运行状态是指 正在使用CPU或者等待使用CPU的进程
- 如何通过负载衡量性能 ?
- 通过uptime命令可以看出 平均负载有3个值,最近一分钟的平均负载,最近5分钟的平均负载和最近15分钟的平均负载。从平均负载的定义中可以看出,系统平均负载是和CPU有关系的,所以最理想的情况下是每个CPU都运行着一个进程,这样CPU就得到了充分的利用。
- 获取CPU数量 cpuinfo
- 如何衡量
- 如果 3个时间段的平均负载值相差不是很大,则表达式当前系统比较稳定
- 如果最近1分钟的平均负载小于15分钟的平均负载值,则表示当前系统的负载正在下降。
- 如果最近1分钟的平均负载值要高于15分钟的平均负载值,则表示当前系统的负载正在升高,需要再次观察多个时间段。
- 平均负载与CPU使用率的区别
- 平均负载既包含正在使用CPU的进程,还包含等待CPU和等待进行I/O的访问进程。CPU使用率表示单位时间内CPU的繁忙程度,它和平均负载并不完全一致。
- CPU密集型进程会占用大量CPU资源,从而导致平均负载升高。
- 对于I/O密集型进程,等待I/O过程也会导致平均负载升高,但CPU使用率不一定升高。
- 大量等到CPU的进程调度,不仅会导致平均负载升高,也会导致CPU使用率升高。
- 为什么经常被问到 CPU上下文切换?
- 什么是CPU上下文切换?
- CPU上下文切换有三种
- 进程上下文切换 进程的执行是受操作系统管理的,当一个进程被从内核中移出,另一个进程开始执行时,在这2个进程当中会存在上下文切换
- 线程上下文切换 线程上下文是指某个时间段CPU寄存器和程序计数器的内容。CPU是通过时间片分配算法来循环执行任务的,而时间非常短,所以CPU会不停切换线程。
- 中断上下文切换 为了能快速响应硬件的事件,中断处理会打断正常的进程,进而去执行中断程序响应硬件的事件。
- 如何查看系统的上下文切换情况
- 使用 vmstat 指令: vmstat 5 采集数据并且查看
- 如何 快速分析CPU 的性能瓶颈?
- 影响CPU性能的指标有哪些?
- CPU使用率
- 用户CPU使用率,CPU在用户态运行时间占总CPU运行时间的百分比,这个值越代表应用程序繁忙
- 系统CPU使用率,CPU在系统态运行时间占总CPU运行时间的百分比,这个值越大代表内核越繁忙
- 等待I/O的CPU使用率 等待I/O时间占总CPU运行时间的百分比,这个值越大,代表系统与硬件设备的交互时间越长。
- 软中断CPU使用率, 内核调用软中断处理程序的时间占总CPU运行时间的百分比。这个值越大代表系统发生的中断越多。
- 硬中断CPU使用率,内核调用硬中断处理程序的时间占总CPU运行时间的百分比。
- 平均负载
- 上下文切换
- CPU缓存命中率 CPU的处理速度比内存处理速度块很多,CPU在访问内存时需要拜拜浪费等待内存响应的时间。CPU缓存用于解决CPU速度与内存速度不匹配的问题。
- CPU性能分析工具 top\vmstat\pidstat
优化服务器性能
CPU性能优化方法论?
应用程序优化:用吞吐量和请求延迟啦评估应用程序的性能
- 编译器优化
- 算法优化
- 异步处理
- 多线程代替多进程
- 利用好缓存
系统优化: 用CPU使用率来评估系统的CPU使用情况。
- CPU绑定
- CPU独占
- 调整优先级
- 为进程设置资源限制
- NUMA优化
- 中断负载均衡
定位和处理内存泄露问题
- 内存的分配和回收
- 只读内存段
- 数据内存段
- 栈内存段
- 堆内存段
- 文件映射段
- 内存泄露的定位和处理
- 通过vmstat工具查看内存是否变动异常
- 使用top工具查看占用内存空间不正常的进程
- 使用memleak工具监测内存泄露。
Java虚拟机的生产调优
- JVM内存模型分析 JVM内存共有5大内存区域,堆内存、程序计数器、方法区、虚拟机栈、本地方法栈。
- 方法区 方法区被称作 永久代,它是JVM中的一块内存区域,主要用来存放.class文件中加载进来的类。
- 程序计数器 开发人员编写的Java应用程序会被编译成字节码,字节码对应着各种指令。需要有一个东西来记录指令执行到哪里去了。
- 虚拟机栈 每个线程都有自己的虚拟机栈,用来存放它执行的方法中的局部变量等数据。
- 堆内存 我们构造出来的各种对象都会被放在Java堆中。
- 本地方法栈 虚拟机栈用来管理Java函数的调用,而本地方法栈用来管理本地方法。本地方法并不是用Java语言实现的,而是用C与语言实现的。比如在Java类库中好多是用native表示的本地方法。
JVM优化的思路
JVM GC垃圾回收原理
当新生代Edem区存放空间满了之后,则检查老年代可用内存空间是否大于Edem区所有对象的大小
- 如果大于 则直接进行新生代垃圾回收
- 垃圾回收之后的存活对象会被放到S区 包括 S1和S2
- 在复制之后,如果S区内存空间不够存储复制来的对象,则会利用担保规则直接进入老年代
- 当S区对象年龄超过设置的值,或S区同龄对象超过内存空间一半时,也直接进入老年代
- 如果小于 则根据HandlePromotionFailure查看老年代可用内存空间是否大于"历次进入老年代的平均对象大小"
- 如果大于 则尝试Minor垃圾回收;如果小于则直接进行Full回收,之后在进行Minor回收
- 如果在垃圾回收完毕后老年代依然没有足够的存储空间,则会发生内存溢出。
年轻代垃圾回收的调优思路
- 对于部署在大内存机器上的应用,推荐使用G1垃圾回收期。
老年代垃圾回收调优思路
- 什么对象能进入老年代?
- 对象年龄太大
- 在年轻代发生一次垃圾回收之后,发现S区域i中几个年龄的对象所占的内存空间加起来超过了Survivor区域的50%
- 在年轻代发生垃圾回收后,剩余的存活对象太多,Survivor区域无法承载。