服务器性能测试是一项非常重要而且必要的工作,本文是作者Micheal在对服务器进行性能测试的过程中不断摸索出来的一些实用策略,通过定位问题,分析原因以及解决问题,实现对服务器进行更有针对性的优化,提升服务器的性能。
1.服务器性能测试小结 讲到服务器性能大部分人会想到这个服务器的架构是什么样子的,用的什么epoll,select,spring,tornado之类的。其实从本质上来看的话目前大部分的服务器主要包括逻辑层以及DB层,我们采用的各种框架组件处于逻辑服务器中,如下图所示。
服务器架构本质
服务器性能测试是一项比较繁琐的事情,作为没有做过性能测试的同学可能需要理清楚以下几个事情。
1.1. 协议分析
首先是协议分析,性能测试本质上是我们用代码来模拟真实的用户请求,所以我们必须要知道发送出去的请求内容才能模拟。在典型的CS服务器中很多使用了protobuf,thrift,tdr(腾讯自研)来序列化以及反序列号请求内容。
序列化之后一方面可以对数据进行压缩处理,另一方面也避免请求内容明文传输造成被抓包·泄漏数据的危险。之前有过服务器传输数据的时候使用的是明文直接发送,而且这个数据是一些敏感的sql语句,这样首先暴露了数据库的表结构,同时不法分子可以通过模拟发包造成“脱裤”甚至是数据被清空。
谷歌出品,必属精品。Protobuf使用起来很方便,学习成本非常低,而且序列化和反序列号的接口很容易使用。同时它相对于xml以及json,极大的的减小了数据占用的空间,减少了传输成本。目前支持包括C++,java以及python等多个语言。Protobuf目前用的比较多,打解包也很方便,比较推荐使用。
Thrift是一个跨语言的轻量级rpc消息和数据交换框架。Thrift支持几乎绝大部分主流的语言,包括C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, Smalltalk, and OCaml,虽然大部分我都没有用过。相对于protobuf,thrift提供了全套RPC解决方案,包括序列化机制、传输层、并发处理框架等,也因为如此thrift的学习成本比较高。
在做服务器性能测试之前,我们需要了解它的协议是怎么定义的。
1.2. 机器人管理
本质上机器人管理就是一个调度控制器,在获取需要发送的请求协议之后,需要有一个框架来管理所有的机器人,控制机器人的启动,发送请求以及停止的动作。框架的选择需要根据服务器的实际情况来,不同的业务场景,使用不同的框架产生的压力上限也会不一样。
机器人管理框架
以一个简单的多线程框架为例,主线程负责控制逻辑,管理所有的机器人状态信息。子线程执行每个机器人的任务,包括连接服务器,发送数据,接收数据,断开连接等。
1.3. 结果统计
机器人发送请求包之后,一般是要等待服务器的响应回包。服务器那边可以计算本次压测过程中各项业务数据,包括TPS,总的收发包量等。
不可能在测试过程中一直盯着各个数据看,我们需要把每项数据记录下来,后续综合各项结果进行分析。这里的结果统计除了需要统计每个机器人收到回包的结果,还需要统计服务器在压测过程中的各项性能数据变化。一旦客户端的压力上到一定值时,服务器某项资源支撑不了的话,说明这个资源可能存在短板,存在可以优化的空间。
性能结果分析是一个比较复杂的过程。需要综合硬件、操作系统、应用程序等多方面来定位。
2.1. 硬件的影响
硬件对服务器性能影响还是蛮大的,如果是土豪的话,可以直接买最好的。我们分析硬件主要是希望选择合适的配置,节约资源,避免出现高射炮打蚊子的情况。
大部分的CPU在同一时间内只能运行一个线程,但是超线程的处理器可以在同一个时间运行多个线程,我们可以利用处理前超线程特性提高系统性能。虽然采用超线程技术能同时执行两个线程,但它并不象两个真正的CPU那样,每个CPU都具有独立的资源。当两个线程都同时需要某一个资源时,其中一个要暂时停止,并让出资源,直到这些资源闲置后才能继续。因此超线程的性能并不等于两颗CPU的性能。
内存的大小也是影响服务器性能的一个重要因素。内存太小,系统进程要被阻塞,应用程序会变得缓慢,甚至是失去响应;如果太大的话,也是造成一种浪费。Linux系统中采用物理内存和虚拟内存两种方式,使用虚拟内存可以缓解物理内存的不足,但是如果占用过多的虚拟内存的话,应用程序的性能会明显的下降。
网络带宽的大小限制了客户端与服务器交互的流量,相对其他硬件资源,网络带宽在价格上更贵。这需要我们合理预估服务器的可服务器能力,需要占用的带宽资源。
目前磁盘都是机械方式运作的,主要体现在磁盘读写前寻找磁道的过程。磁盘自带的读写缓存大小,对于磁盘读写速度至关重要。读写速度快的磁盘,通常都带有较大的读写缓存。磁盘的寻道过程是机械方式,决定了其随机读写速度将明显低于顺序读写。在我们做系统设计和实现时,需要考虑到磁盘的这一特性。
2.2. 操作系统及软件
2.2.1. 版本
笔者并没有做过分析不同操作系统对服务器性能的影响,因为只用过Linux开发服务器程序。Linux操作系统在这十几年发展的异常迅猛,目前大部分的服务器都是运行在Linux操作系统上的。Linux目前具有最好的生态系统,服务器端的各种软件都为它而设计,默认都认为你是在 Linux 上跑,你要是整一个非 Linux 的服务器,你得有足够的心理准备,因为出现任何问题,你可能未必能找到能帮你解决问题的人。
关于数据库参数的设置,比如mysql的配置文件my.cnf文件中,修改不同的配置(比如innodb_flush_log_at_trx_commit 设置为0,1还是2 )可能会对数据库的读写性能影响很大。
另外程序中的一些查询操作,采用不同的数据结构,可以实现时间和空间上的相互转化,从而影响服务器的性能。
3.1. Vmstat
Vmstat,virtual memmory statistics(虚拟内存统计),主要是对操作系统的内存信息、进程状态、cpu活动等进行监视,但是它不能对某个进程进行深入的分析。
Procs中b列表示当前等待资源的进程数,包括等待I/O,内存等。 Swpd列表示切换到内存交换区的KB数,一般si,so为0的话基本不影响系统的性能。 Cache是page cache的内存数量,Linux会把空闲的物理内存的一部分拿来做文件和目录的缓存,以便提高程序执行的性能。如果cache的值较大的话,说明缓存了太多的文件,如果bi值小的话,说明文件系统效率比较高。 Si是每秒从磁盘读入虚拟内存的大小,如果这个值一直大于0,表示物理内存不够用或者内存泄露了,需要查找耗内存进程解决掉。 Bi,bo是表示从块设备读入数据的总量以及写到块设备的数据总量。如果bi+bo值比较大,而且wa值也比较大的话,说明系统磁盘I/O可能有问题,性能不高。
In和cs是每秒钟的设备中断数以及上下文切换数。它们很大的话,表面内核消耗的CPU时间较多。
3.2. Top
Top是一个动态显示过程,即可以通过用户按键来不断刷新当前状态。它可以按照系统中当前进程的CPU利用率以及占用的内存大小进行排序,可以比较快速定位出系统响应迟钝的原因。如果在前台执行该命令,它将独占前台,直到用户终止该程序为止。
top是一个显示数据较多的工具,第一行显示的是系统的开机运行时间,机器的CPU负载信息;第二行显示当前系统任务的总数,以及各个状态的进程数;第三行显示的是CPU资源的使用情况总览;第四行显示内存的使用情况总览;第五行显示的是内存交换区的使用情况总览;后面开始是每个进程对资源使用的情况。
3.3. Nmon
Nmon提供对CPU、内存、网络、磁盘等系统资源占用情况分析,相比其他Linux命令获取到的数据,nmon的功能更为集中、配置性更强。通过nmon采集到数据之后可以在windows系统中使用nmon_analyser做数据的展示以及分析工作,可视化效果比较好。
由于一般Linux系统都不自带nmon,使用之前需要下载安装。
3.4. Uptime
Uptime命令显示系统已经运行了多长时间,它依次显示当前时间、系统已经运行了多长时间、目前有多少登陆用户、系统在过去的1分钟、5分钟和15分钟内的平均负载。
关于系统平均负载,它表示在特定时间间隔内运行队列中的平均进程数。如果一个进程满足以下条件则其就会位于运行队列中:没有在等待I/O操作的结果;没有主动进入等待状态;没有被停止。
3.5. Netstat
Netstat命令可以显示本机的网络连接情况,监听端口以及路由表等各种网络相关信息。Netstat用于显示与IP、TCP、UDP和ICMP协议相关的统计数据,一般用于检验本机各端口的网络连接情况。
3.6. Free
Free是监控Linux使用情况最常用的命令。 “Free -m”可以查看以M为单位的使用情况,这里主要观察free和cached两列。一般来说,如果应用程序可用内存/系统物理内存>70%时,表明目前系统内存资源比较充足,不影响系统性能;如果应用程序可用内存/系统物理内存<20%时,表明目前系统内存资源比较紧缺,需要释放其他程序内存或者增加内存;如果应用程序可用内存/系统物理内存在20%-70%之间,表明目前系统的内存资源基本满足应用需求,暂时不影响系统的性能。
3.7. Sar
Sar也是一个强大的分析系统性能的工具,它可以比较全面的获取系统的CPU,运行队列,磁盘IO,分页,内存,CPU中断,网络等多项数据。
上图是使用sar获取系统CPU的整体负责情况,每隔1秒统计一次,统计3次,最后会给出3次的平均值。需要查看其他的数据可以查看手册使用。
3.8. Iostat
Iostat是I/O statistics的缩写,主要功能是对系统的磁盘I/O操作进行监控。它的输出主要显示磁盘读写操作的统计信息,同时也会给出CPU的使用情况。
这里显示的是查看CPU和磁盘的信息,统计间隔2秒,共3次。
3.9. Valgrind
Valgrind是一款广泛用于监控程序运行过程进行内存调试、内存泄漏检测以及性能分析的工具。它会给出内存泄漏的统计,包括definitely lost,indirectly lost,possibly lost,still reachable ,suppressed等,我们可以使用valgrind来测试程序中内存不规范使用的部分。同时对于地址越界问题也可以通过valgrind扫出来,它会统计invalid write的情况。
在优化之前,先要搞清楚服务器的具体业务需求是什么,据此来优化其中的短板。
4.1. 存储的优化
IO相对来说比较耗时,我们都知道越靠近CPU的存储,其访问速度越快,但是其价格越贵。下图来展示了不同存储的容量以及访问时间。
目前很多同学在优化服务器性能的时候都会从存储这方面入手。
储存的容量以及访问时间
4.1.1. 用内存换时间
4.1.1.1. 增加缓存很多web应用是有大量的静态内容,这些静态内容主要都是一些小文件,并且会被频繁的读,采用Apache以及nginx作为web服务器。在web访问量不大的时候,这两个http服务器可以说是非常的迅速和高效,如果负载量很大的时候,我们可以采用在前端搭建cache服务器,将服务器中的静态资源文件缓存到操作系统内存中直接进行读操作,因为直接从内存读取数据的速度要远大于从硬盘读取。这个其实也是增加内存的成本来降低访问磁盘带来的时间消耗。
对于一些重要性不高但是又想要快速响应用户请求的部分数据可以考虑内存数据库来存储,同时可以定期把数据固化到磁盘。
这里图个新鲜,说说内存换时间在大数据云计算相关领域的一些应用。Spark最近很火,它的核心要数RDD了,RDD最早来源与Berkeley实验室的一篇论文《Resilient Distributed Datasets: A Fault-Tolerant Abstraction for In-Memory Cluster Computing》。现有的数据流系统对两种应用的处理并不高效:一是迭代式算法,这在图应用和机器学习领域很常见;二是交互式数据挖掘工具。这两种情况下,将数据保存在内存中能够极大地提高性能。这里不详细说RDD了,只是想说程序员一直是觊觎内存的读取速度的。
除了对内存方面的优化,还可以对磁盘这边进行优化。跟传统机械硬盘相比,固态硬盘具有快速读写、质量轻、能耗低以及体积小等特点。但是ssd的价格相比传统机械硬盘要贵,有条件的可以使用ssd来代替机械硬盘。
另外对于业务上查询请求,在建表的时候可以根据相关需求设置索引等,以提高查询速度。
4.3. 利用多核优势
现在运行服务器的主流机器配置都是多核CPU的,我们在设计服务器的时候可以利用多核心的特点,采用多进程或者多线程的框架。
对于多线程的使用,特别是使用线程池的时候可以通过测试不同线程池服务器的性能来设置合适的线程池。
4.4. 选择合适的IO模型
《UNIX网络编程卷1:套接字联网API》中有一幅图比较经典。
IO模型
非阻塞的I/O模型:和阻塞相反,只要不能得到结果的时候,I/O立刻返回。不会阻塞当前线程。 IO复用模型:也就是自己要学习的部分。多路复用的意思是,将多路信号合并到一路上进行处理,类似多个管道汇集到一个管道,与之相反的是多路分解。 IO复用模型主要是select,poll,epoll;对一个IO端口,两次调用,两次返回,比阻塞IO并没有什么优越性;关键是能实现同时对多个IO端口进行监听;函数也会使进程阻塞,但是和阻塞I/O所不同的的,这两个函数可以同时阻塞多个I/O操作。而且可以同时对多个读操作,多个写操作的I/O函数进行检测,直到有数据可读或可写时,才真正调用I/O操作函数。 信号驱动:首先开启套接口信号驱动I/O功能,并通过系统调用sigaction安装一个信号处理函数。当数据报准备好被读时,就为该进程生成一个SIGIO信号。随即可以在信号处理程序中调用recvfrom来读数据报,井通知主循环数据已准备好被处理中。也可以通知主循环,让它来读数据报。 异步的IO模型:告知内核启动某个操作,并让内核在整个操作完成后(包括将数据从内核拷贝到用户自己的缓冲区)通知我们。
这里并不是说一定要用某个模型,epoll也并不是在所有情况下都比select性能要好的,在选择的时候还是要结合业务需求来。
4.5. 分布式部署程序
当单机服务器已经找不到合适的优化点时,我们可以通过分布式部署来提高服务器的响应能力。优秀的服务器开发都会为自己的服务器的扩容,容灾提出一些解决方案。个人觉得服务器设计的时候简单点比较好,这样后期扩容的时候会很方便。
针对服务器性能测试,腾讯WeTest运用了沉淀十多年的内部实践经验总结,通过基于真实业务场景和用户行为进行压力测试,帮助游戏开发者发现服务器端的性能瓶颈,进行针对性的性能调优,降低服务器采购和维护成本,提高用户留存和转化率。
点击链接:http://wetest.qq.com/gaps 立即体验