异常请求参数,或其它原因引起程序访问不存在的map key导致panic
性能测试中,稳定性测试是必不可少的,最主要目的是为了发现程序崩溃问题,关键在测试设计过程中依据代码逻辑分析直接或间接使用的参数,构造各种异常case;例:
#server code
func handler(w http.ResponseWriter, r *http.Request) {
keys, ok := r.URL.Query()["key"]
log.Println(keys)
}
当get参数中没有key,则server panic所以golang中使用变量或参数前一定要判空
配置文件所需程序制定数据结构不同,导致程序panic
与上面的问题类似,一般常见于json.Unmarshal等操作,使用函数返回前,对err判空;
程序加载数据异常或数据过大,超过机器内存,导致panic
此问题任何语言均存在,程序运行状态中莫名崩溃,没有log和core文件,此时可以查看系统日志:/var/log/messages 最常见的问题linux系统杀死占用内存过高的进程
kernel: Out of memory: Kill process
cpu占满导致性能低
常见于密集运算型服务,此处又分正常逻辑占用和异常逻辑占用,正常逻辑是指由于正常逻辑包含大量检索,比较等操作导致的,这种问题应重点优化实现结构;对于非正常逻辑也就是bug,一般是有死循环、嵌套过多、算法效率低等问题,可以通过golang提供的pprof生成冰柱图分析问题所在;
带宽占满
数据中转服务和返回静态资源的服务比较常见带宽占满的情况,此问题线上是打压过程中qps上不去,但是cpu、内存都没那么大压力,使用nload查看本地网卡的in-out判断带宽是否占满,无法确定本机网卡大小时,可以使用iperf查看网卡极限带宽,再做对比;
io被占满
磁盘io在当前的服务设计中已经很少会变成瓶颈,但是也是一个需要排查的地方,可以使用iostat命令查看磁盘io状况;
后端服务为性能瓶颈
对微服务架构的服务常见的就是后端服务瓶颈,导致被测服务最大qps较低,此时可通过mock后端服务的方法排除依赖的影响;
依赖的数据库读写
传统的使用mysql等数据库进行数据查询的服务经常会遇到sql慢查询的问题
端口占满
对中转服务或微服务架构来捉端口资源也会成为瓶颈;可以使用ss -s 和netstat来初步定位本机端口占用情况;
网络框架性能问题
除去上述问题之外,搭建服务使用的web框架本身的性能也可能成为限制服务性能的原因,例如golang的web框架性能 fasthttp>gin>http标准库 ,所以可以排除代码逻辑单独对网络框架进行一波压测确认一下;也可以参考github上已有的性能测试结论:
https://github.com/smallnest/go-web-framework-benchmark
log库性能瓶颈
最近一次测试中,发现的问题就是log库的性能问题导致服务整体qps上不去,现象是cpu、内存、带宽、io、端口均无压力,但是qps峰值只到6k左右,通过pprof+火焰图分析,耗时主要在log记录上,最后把log库由logurs更换为zap解决问题,但是服务瓶颈仍然在记录log上;
网络参数及配置合理性问题
一般语言的http框架或web服务器都有各种参数可配,但是实际用到的不多,拿nginx举例,会影响到服务性能的配置有:worker进程数量、upstream中keepalive的配置、cache配置等;所以不恰当的配置也可能导致服务性能瓶颈;
最后简单总结了一下一般web服务的性能测试过程,供大家参考