Docker技术为软件开发、测试提供了非常便捷的功能,使用现成的镜像让我们的工作事半功倍。本文针对在项目中进行压力测试使用Docker进行说明,重点记录从手工搭建环境,到使用Docker提高测试效率,再对Docker脚本进行多次优化,最终达到测试效果的过程。
从中可以看到Docker带给我们的便利,学习到Docker在压力测试中的应用,同时也体现了技术精益求精、永不止步的趋势。
一、Docker简介
Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的?Linux?机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口。
对于目前项目的压力测试来说,看重是有很多现成的镜像供我们使用,还有就是在一个物理机上运行的多个容器可以实现隔离。
二、压力测试需求说明
需求说明:项目上需要对网络设备监管系统进行压力测试,测试的指标是系统能否完成1W设备的性能指标监控。
需求分析:实际网络运行时,需要对被管设备进行性能采集,指标包括设备的CPU、内存、温度、端口流量、带宽利用率等指标。采集周期分为5分钟、15分钟、24小时。
目前的测试需求是:验证系统能否完成1W设备的5分钟性能指标采集。
当然,如果可以采集5分钟,15分钟、24小时也不在话下了。
三、从刀耕火种到现代化
在明确了测试需求之后,紧接着需要完成的就是测试设计和环境搭建了。由于无法使用1W的真实设备进行测试,具体原因如下:
找不到。1W台设备需要非常大的精力去申请、借调,而且不是小数目。
不划算。任何研发事件都需要考虑性价比,进行本需求的测试,投入1W台实际的设备是不划算的。
没必要。从各种技术方案来看,都没必要使用实际设备进行测试。
所以肯定是需要使用模拟器进行测试。通过之前的技术积累,测试组对SNMP Simulator?非常熟悉,该工具可以根据需要进行SNMP MIB配置,响应需要的MIB节点。在本例中,通过监控指标的确认,在单台实际设备上抓包后,即可配置与实际设备回应一致的模拟器。
然而,在实施压力测试的过程中,并不是一开始就想到使用Docker的,使用Docker也不是一开始就非常顺利的。经历了从刀耕火种到最终实现现代化的过程。
3.1多台Windows PC的刀耕火种时代
当接收到该需求的时候,马上进行测试方案的设计和规划,核心的方法就是使用SNMP Simulator?模拟实际的设备。具体分为如下步骤。
1)安装Python环境。使用01-python-2.7.12.msi进行Python环境安装,完成后添加path环境变量,如C:\Python27;C:\Python27\Scripts。
2)安装pip工具。命令如下:cd /d xx\xx\pip-9.0.1,python setup.py install。
3)最后通过pip安装pysnmpsim。命令为:pip install snmpsim,需要确保网络畅通。
4)对实际设备进行抓包。使用Wireshark工具对实际设备采集过程进行抓包,对其中的SNMP交互进行提取记录。
5)根据抓包结果配置SNMP Simulator响应报文。SNMP Simulator?工具会遍历指定的文件夹,搜索“.snmprec”后缀的文件,作为响应报文。且文件名为其读写共同体。
上述文件就是一个参考实际抓包结果进行配置的示例。以第一条为例,当SNMP Simulator?接收到以“public”为共同体,且OID为“1.3.6.1.2.1.1.5.0”的SNMP报文时,会回应“7465737432”,其数据格式为“4”(表示OCTET STRING)。SNMP Simulator支持配置不同情况响应不同报文,本例不需要。
6)使用命令启动模拟器。由于需要启动非常多的模拟器,使用SNMP Simulator提供的文件命令格式,如下:
snmpsimd.py --v2c-arch --data-dir=xx\01-ResponseData --args-from-file=xx\Parm.txt
其中01-ResponseData目录中存放回应的SNMP报文数据,具体格式参考(5)步中的示例。Parm.txt中存放需要模拟的设备IP信息,示例如下:
上述命令意味着在一个SNMP模拟器实例中模拟Parm.txt指定的IP+端口的SNMP设备。
7)在多台PC上重复上述步骤。对于单PC模拟器的数目是一个非常重要的指标。实际发现,单进程中最多启动500模拟器。超过后会报如下错误。
这个有可能是SNMP Simulator的BUG,但也无暇去解决了。通过开启多个Python进程规避。
8)在待测系统中使用数据库存储过程创建资源和任务。1W设备和相关资源数据通过数据库脚本插入到库中,其中与资源对应的任务信息也一并插入库中。
9)执行测试分析结果。
最终在多个PC上完成了1W模拟设备的搭建,然而在实际的使用中有如下问题:
1)环境搭建太复杂。首先需要在10台PC上来回复制安装文件、响应报文文件,之后在10台PC上进行模拟器启动、查看。
2)环境不易维护。Windows只能通过远程桌面的方式进行管理,对各个PC进行安装、启动、调试、维护。一旦开启10个MSTSC,就是手忙脚乱,生怕出现一点错误。可以说是一边胆战心惊,如履薄冰,一边是任务繁重,急火攻心。真是冰火两重天!
3.2多台CentOS的原始社会
Windows下由于远程桌面带来的弊端,直接想到的解决方案就是通过远程批处理脚本完成。然而理想很丰满,现实太骨感:Windos下非常难以实现!或者用PowerShell,或者通过编写工具对多个PC进行管理,或者在各个机器上安装SSH。都是得不偿失的不归路。
既然想到了SSH,那为什么不直接用Linux呢?所以最终决定使用多个CentOS替换掉WindowsPC。
对于上述步骤,将操作系统换为CentOS。这样通过Linux远程工具(SecureCRT? XShell PuTTY等)可以很方便的对模拟器所在的PC进行管理。
事实上,这个方案并没有完全落地。因为一方面可以看到对于流程的改善并没有很多(只是方便了远程操作,装Python、pip等步骤都无法省略);另一方面,Docker也映入眼帘。
3.3 Docker带领逐步走进现代化
Docker进入视线是非常偶然的机会,其他项目组需要协助完成一个使用Docker的测试工具的改造,天然的就想到了编写Docker File,增加功能。在完成该项目组的工作后,忽然受到了启发。此时才想起来还有Docker这个利器。既然别人可以用镜像作为测试工具,为什么不写一个SNMP Simulator的镜像解决模拟环境搭建的痛点呢?
写一个自己的镜像,多么具有诱惑力的事情呀?然而在编写的过程中,忽然想到是不是有人已经做了?做技术的同学一定要经受住技术本身的诱惑,以效率、务实为出发点。
在Docker Hub上搜索结果如上。既然有10K+下载量的镜像,何必自己费劲呢?于是使用这个镜像开始工作。完整的步骤如下。
1)安装Docker。参考相关网页安装Docker,不在详述。
2)对实际设备进行抓包。与之前的步骤一致。
3)根据抓包结果配置SNMP Simulator响应报文。与之前的步骤一致,需要将文件拷贝到CentOS上。
4)使用命令启动模拟器(实际上是拉取、运行Docker的过程)。
docker run -d –v xx\01-ResponseData:/usr/local/snmpsim/data -p 25001:161/udp -e EXTRA_FLAGS="--v2c-arch" --name snmpsim_711 tandrup/snmpsim |
上述命令的含义是:使用tandrup/snmpsim的Docker镜像(如本地不存在,就在Docker HUB上拉取)启动一个名字为snmpsim_711的容器。该容器将本地的xx\01-ResponseData目录挂载到容器中的/usr/local/snmpsim/data目录。以本地25001端口映射为容器的UDP协议161端口。容器启动的SNMP模拟器仅支持V2C版本(--v2c-arch)。
启动后查看如下。
编写Shell脚本启动更多的容器,获得更多的模拟器。脚本如下。
5)在多台CentOS上重复上述步骤。
6)待测系统中使用数据库存储过程创建资源和任务。
7)执行测试分析结果。
总体步骤上节省了两步。不要小看这两步,带来如下的好处:
1、节省了两步,多台机器就是更多的节省。
2、避免了在多台机器安装Python、pip、SNMP Simulator,也就避免了由于环境问题带来的困扰。这是Docker自带的光环,由于使用了现成的Docker镜像, 使用的基础环境都是一样的,就免除了这个困扰。
3、CentOS通过远程工具更方便。无论是SCP拷贝文件,还是启动Docker,都可以通过Shell解决,提高了环境的维护能力。
紧接着,需要对能够模拟的模拟设备个数进行分析。可以查看容器占用的资源进行分析。
单个容器占用内存为近20M,通过限定容器内存的方式明确每台机器开启的容器数目。命令如下。
docker run -d -v xx/01_Response_Data:/usr/local/snmpsim/data -m 20M --memory-swap -1 -p $snmp_port:161/udp -e EXTRA_FLAGS="--v2c-arch" --name snmpsim_rax711_$snmp_port tandrup/snmpsim |
其他信息均一致,增加了-m 20M --memory-swap -1,含义是最多占用20M内存,不限制SWAP空间。
将启动批量容器的Shell修改为限定内容的脚本,运行后效果如下:
查看资源占用情况如下:
可见20M已经够了。
这样对于一台8GCentOS,以有6G可用内存为例,可以启动容器为307个。对于1W的需求明显是无法满足的。我们需要更进一步。
其实上面的容器启动有个误区,一个容器中仅开启了一个模拟器。而通过在Windows上的经验,我们知道可以启动500个。我们不需要500这么多,10个就可以解决问题了。所以在容器启动命令中增加多个端口映射。
docker run -d -v xx/01_Response_Data:/usr/local/snmpsim/data -m 20M --memory-swap -1 -p 25001:161/udp -p 25002:161/udp ………… -p 25010:161/udp -e EXTRA_FLAGS="--v2c-arch" --name snmpsim_rax711_$snmp_port tandrup/snmpsim |
其他内容都是一致的,增加了多个端口映射,意味着将25001-25010均开放给外部作为SNMP模拟器使用。相应的修改批量启动脚本,最终启动的效果如下。
这样一台CentOS上模拟上千台设备就成为可能。我们的压力测试也跟着Docker进入了现代化。之后再进行类似的测试,就不会像最开始那样大费周章,而且将会更稳定,更可靠,更易维护。
3.4测试结果
为了简单起见,我们以100设备的采集情况为例进行说明。通过数据记录的查询确定采集数目的正确。在19:05查看数据库记录:select COUNT(*) from device_performance;
数目为:596583。
5分钟后,在19:10会进行一次采集,期望的结果是增加100条记录,结果如下:
596683,符合期望。
我们还可以通过编写查询语句将结果进行直接汇总记数,语句如下;
select count(*),COLLECT_TIME from device _performance GROUP BY COLLECT_TIME ORDER BY COLLECT_TIME desc; |
可见在上述4个周期,均完成了采集。对于1W设备的情况也需要进行相同的验证。
四、总结
当问题得以解决的时候,回顾总是简单的。正如我们向别人介绍某次技术攻关的经历,往往得到的回应是:这很容易想到呀。本次压力测试使用Docker的过程也是一样的,实际的过程远比总结出来的困难、不可捉摸。特别是当你沉浸在某一种自认为较为先进的测试中时,对技术验证的渴望,对自身技术路线的自信,都会让你无暇顾及更优秀的方案。
虽然本次压力测试最终以一种看上去很好的方案解决了,留给我们的思考还在继续。对于走过的弯路、中间的收获,以及后续的计划,总结如下:
1)不要因为方案熟悉就直接上马。之所以在开始直接就上马Windows环境搭建,是因为在Windows上进行模拟器的搭建是轻车熟路,抓包、配MIB、开启SNMP 模拟器……都是非常熟悉的操作。所以非常容易掉进自己的技术温柔乡。
2)对即将解决的问题对比之前的问题进行估计。如何避免上述问题呢?需要对比熟悉方案解决问题和目前即将解决问题的异同。之前进行模拟器搭建是单台设备的模拟,进行SNMP接口的验证;而当前的问题是对大量设备的情况进行验证时,情况就复杂了。所以需要评估SNMP模拟器的适用性,对大量设备下的SNMP模拟器环境搭建难度进行合理评估。
3)不要懒惰。在单台PC到多台PC扩展的过程中已经意识到环境的费时费力,但由于没有时间,缺少尝新的意愿导致没能引入更先进的技术。这实际是两难的选择,一方面项目紧急需要测试结果,所以事急从权;一方面想想是不是应该先搞定搭建效率的问题,毕竟磨刀不误砍柴工。
4)拿来主义。从tandrup/snmpsim镜像的直接使用可以看到,如果有现成的就不要从零开始,毕竟站在巨人的肩膀上,起步会高一些。当然,在解决问题之后,可以去看一下tandrup/snmpsim镜像的Docker File,为后续扩展做好准备。这点上编写一个自己的Docker File具有太强的诱惑力了,一定要理性看待技术的诱惑和项目的需要,以项目的进度和务实的效果为出发点,抵抗技术对你的诱惑。
5)精益求精,永不止步。技术和人一样,一定要保持进步才能有竞争力。当前的方案确实能够解决当前的问题,但可以从自动化、易用性上继续优化。同时,通过扩展tandrup/snmpsim镜像的Docker File增加个性化的需求,更能体现项目的自身特点。也满足了编写一个自己的镜像的愿望!