我们要接触的性能测试跟互联网的不太一样。我们知道预测服务仍然还是访问密集型业务。但是模型调研的过程是属于计算密集型业务。我们要模拟的情况不再是高并发。而是不同的数据规模,数据分布和数据类型。我们日常的性能测试都是需要在各种不同的数据下跑各种不同的算子和参数。所以我们首先需要一种造数机制,能帮助我们按需求生成大规模的数据。我们选择的是spark,利用分布式计算在hadoop集群上生成大量的数据。
原理也很简单,接触过spark的同学肯定都知道在spark中生成一个RDD有两种方式, 一种是从文件中读取,另一种是从内存中的一个list种解析。第一种方式肯定不是我们想要的, 所以从内存中的list解析就是我们选择的方式。假如我们想生成一个10亿行的数据。就可以先使用python 的xrange造一个生成器以防止内存被撑爆。然后用这个生成器初始化一个有着10亿行的空的RDD,定义并操作RDD的每一行去生成我们想要的数据,然后设置RDD的分片以及消耗的container,内存,cpu等参数。提交到集群上利用集群庞大的计算资源帮助我们在段时间内生成我们需要的数据。 前两天我再一个3个节点的集群上造过一个1.5T的数据,大概用了5个小时。这样一开始的时候我们是写spark脚本来完成这些事。后来需求越来越多,我们发现可以造数做成一个工具。把表和字段都提取到配置文件中进行定义。就这样我们成立了shannon这个项目。慢慢的从造数脚本到造数工具再到造数平台。
它的架构特别简单,就是对原生spark的应用,这里我就不展示spark的架构是什么样了。就贴一下造数工具的设计图吧。
简单来说shannon分了3层。最底层是基本数据类型层。负责字段实例化,定义并实现了shannon支持的所有数据类型。例如,随机,枚举,主键,unique key,控制分布,大小,范围等等。
测试环境管理
常见的测试场景我们基本上都说完了。 我们再说一说测试环境管理的问题。 为了能够保证研发和测试效率,一个能够支撑大规模测试环境的基础设施是十分必要的。为什么这么说呢?
首先但凡是涉及到机器学习的业务,运行时间都非常慢。 有时候做测试的时候跑一个模型要几个小时甚至一天都是有的。也就是说,我们运行测试的成本比较高。如果在运行测试的途中环境出了什么问题那么损失还是很大的。多人共用一套环境难免会有互相踩踏的情况,例如一个RD在测试自己的模块,另一个人上来把服务重启了。这时候我们心里一般就是一万头某种动物飘过。所以我们一般希望每个人都能拥有一套独立的环境甚至一个人多套环境。这就增加了测试环境的数量。尤其是团队越来越大的时候,测试环境的数量已经到达了一个恐怖的量级。
其次如果各位所在的公司也像我们一样做TO B的业务,那么我们的测试环境就需要多版本管理,要有能力随时快速的搭建起特定版本的产品环境供开发,产品,测试,以及技术支持人员使用。所以这无疑又增加了环境管理设置的复杂度。
再有就是随着环境数量的扩张,我们的环境从单节点走向集群,这时候我们对环境调度能力的要求会比较高,例如我们要对环境的资源进行计算和限制,保证最大化利用资源的同时不会撑爆系统。例如我们要保证系统有足够的冗余,在某些环境出现故障的时候能够自动检测出来并在冗余节点进行恢复。例如我们需要能够实现多租户管理,执行资源管控,限制超售行为. 例如我们希望系统有一定能力的无人值守运维能力等等。
所以我们经过一段时间的讨论和实验,引入了k8s+docker来完成这个目标。docker的优势大家应该都知道,快速,标准化,隔离性,可迁移性都不错。 通过镜像我们可以迅速的将测试环境的数量提升一个量级,镜像的版本管理正适合TO B业务的多版本管理。 之所以选择k8s,是因为k8s相较于swarm和mesos 都拥有着更强大的功能和更简单的部署方式。刚才说的预测服务需要部署很多个agent,使用k8s的话只需要设置一下replica set的数量,k8s就会自动帮我们维护好这个数量的实例了,很方便 。k8s的调度机制能很轻松的满足我们刚才说的对于灾难恢复,冗余,多租户,高可用,负载均衡,资源管理等要求。所以我们当初怀揣着对google莫名的憧憬走上了k8s的踩坑之旅。