首页 存档 技术 查看内容

美团线上真实流量压测工具构建

2018-3-30 13:00 |来自: 互联网 351 0

摘要: 编者按:高可用架构分享及传播在架构领域具有典型意义的文章,本文由杨硕在高可用架构群分享。点击上方蓝字订阅高可用架构可获取进群机会。 杨硕,现就职于美团,负责广告运营平台、美团点评广告系统对接等工作。曾 ...

编者按:高可用架构分享及传播在架构领域具有典型意义的文章,本文由杨硕在高可用架构群分享。点击上方蓝字订阅高可用架构可获取进群机会。


杨硕,现就职于美团,负责广告运营平台、美团点评广告系统对接等工作。曾就职于 Yahoo ! 北研,从事广告产品的研发工作。对于架构设计、性能调优、大数据、前端等领域均有所涉猎。业余时间除了 side project 外,还经常参加 Hackathon 比赛,并获得了美团第四届 Hackathon 优胜奖等奖项。


“目前美团压测项目接入的服务 40 ,打压的次数 1000 ,很好的完成了线上业务的打压需求。” 杨硕

为什么要搞一个通用的压测工具

美团内部的 RPC 服务大多构建在 Thrift 之上,在日常开发服务的过程中,需要针对这些服务进行压力测试(以下简称压测)来发现潜在问题。常用的方法有:

  1. 使用一些脚本语言如:Python、Ruby 等,读取线上日志构建请求,用多线程模拟用户请求进行压测;

  2. 使用开源工具进行压测。


然而,无论采取哪种方法,压测都是一个十分耗时而又繁琐的过程,主要痛点有:

  1. 需要写很多代码解析日志,还原请求,对于比较复杂的请求,解析很容易出错;

  2. 需要搭建脚本或者工具的运行环境,通常这一过程比较耗时;

  3. 由于打压方法没有统一,导致打压的结果指标比较混乱,有的结果甚至以终端输出的方式展示,非常不直观。


通常要让一个同学压测某一服务,很多时候需要耗费 2~3 天时间,并且很多同学的表情都是这样的:




为了解决这个问题提供一个简单好用的压测工具是十分有必要的。 有没有必要自己造轮子呢?如果有现成的解决方案,那再好不过了。

常见的压测工具

JMeter

JMeter 是一个比较老牌的压测工具,主要针对 HTTP 服务进行打压,该工具在以下方面并不满足美团内部的压测需求:

  1. 默认不支持 Thrift 的打压测试;

  2. 需要本地安装,并且配置复杂;

  3. 对于用户操作并不友好。




Twitter/iago

Twitter/iago是一个由 Twitter 开源的压测工具,支持对 HTTP、Thrift 等服务进行压测,其主要问题如下:

  1. 对每个压测应用都需要创建一个项目;

  2. 压测结果并不直观;

  3. 流量重放依赖本地文件;

  4. 项目依赖于一个较老版本的 Scala,搭建不便;

  5. 相关文档比较少 。


除此之外,当时还考察了 Gatling、Grinder、Locust 等一些常见的压测工具,都因为适用场景和美团的需求有些出入而排除了。综上,针对当前压测工具的一些现状,构建一个简单易用的压测工具还是很有必要的。


构建自己的压测工具

针对之前提到的痛点,新的压测工具主要提供以下功能:

  1. 简单易用的操作界面(服务接入压测的时间应该控制在 1 小时以内);

  2. 清晰的图表能反映压测服务的各项指标;

  3. 满足包括 Thrift、HTTP 等服务的压测需求。


其实很多复杂问题在实用性和灵活性权衡过后,都能用一个简单模型表示,压测问题也一样,我们将压测过程抽象,可以用这个图表示:



首先,在 init 方法里面,进行一些初始化的工作,比如连接数据库,创建客户端等。


其次,在 run 方法里面发出压测请求,为了保证能够对服务产生足够的压力,这里通常采用多线程并发访问,同时记录每次请求的发起时间和结束时间,这两个时间的简单相减就能够得到每次请求的响应时间,利用该结果就可以计算出 TP90、平均响应时间、最大响应时间等指标。


最后,等压测结束后,通过 destroy 方法进行资源回收等工作,比如关闭 RPC服务的连接,关闭数据库等。


如果用接口可以这样表示:




无论是 HTTP 还是 Thrift 服务的压测,本质都是 run 方法的不同。


有了基本模型后,我们要解决的另外一个痛点是,如何简单地拷贝线上真实流量用来构建打压请求,一些大型的 Thrift 服务数据结构非常复杂,写打压脚本的时候需要很多代码来解析日志,而且容易出错。


为了避免这种情况,我们提供了一个叫 VCR(录像机)的工具来拷贝流量。VCR 能够将线上的请求序列化后写到 Redis 里面。考虑到用户需要查看具体请求和易用性等需求,最终选取了 JSON 格式作为序列化和反序列化的协议。同时需要部署在生产环境的一台机器上,为了降低对线上服务的影响,这里采取了单线程异步写的方式来拷贝流量,如下图:




解决了流量拷贝问题后,我们接下来需要按照我们采集的指标进行数据聚合运算。常见的指标有:最大响应时间,平均响应时间,QPS,TP90,TP50,这些指标可以评估服务的性能。


这里我们采用了 InfluxDB 来完成数据的聚合工作,所有聚合指标都是一行 SQL 搞定,非常快速。以 TP90 为例子,仅需要一行查询就能实现需求。


SELECT PERCENTILE(response_time, 90) FROM test_series GROUP BY time(10s)


综上,压测工具的流程图如下:



这是第一期的实现,大概花了 1 周左右的业余时间,等项目上线后,应用的压测接入时间得到了明显的缩短。下图是每个步骤的平均耗时:




细心的同学可能已经发现了,VCR 是用虚线表示的,原因是对于新上线的服务,不需要拷贝流量,只需要在实现 runner 的过程中,通过代码构造请求数据即可。项目刚上线时,大家还不熟悉,第一次应用接入需要耗时 20 到 40min,等大家有经验后,下个应用的接入时间会缩短到 15min 左右。对于服务的 owner 来说,该压测工具更为灵活,他可以在 runner 接口中自由实现压测逻辑。如果二次打压的话或者修改参数的话,只需要在网页上点击鼠标即可完成。下图是其中某个服务的压测结果:




项目上线后,陆陆续续有各事业部的同学开始使用,大家普遍反应操作简单,但是也存在以下几个问题:

  1. 打压力度有时不够,这是由于一期项目开发时时间比较紧迫,只实现了单机的版本,单台机器自然难免有些”马力不足" ;

  2. 在接入 Thrift 应用的时候,需要用户提供 Thrift 生成的客户端代码,对于这种方式大家依然觉得繁琐,希望只上传一个 Thrift 文件就能够打压指定服务;

  3. 用户希望看到被打压机器的一些资源利用情况,比如 CPU 使用率,内存使用率等。


我们开始针对上述问题进行了解决,针对第一个问题,我们采用 Akka 来做一个分布式的扩展,将应用的角色分为 master、worker、counter。 Master 负责进行任务分发,worker 进行打压,然后将打压的的结果发给 counter 进行汇总写入 InfluxDB。


第二个问题,我们在简单模型的基础上进行更高级别的封装,用户上传 Thrift 文件后,我们将 Thrift 文件编译成为模板代码后,自动生成对应的接口。同时我们也有相应的 HTTP 服务适配模块。


针对最后一个问题,我们在压测机器上部署了 agent,压测期间机器的数据能够通过 agent 源源不断的提交上来,这样用户能够清晰的看到被打压服务所在机器的性能指标。


这是架构升级图,大家可以结合我刚刚说的三点看看:




整个项目的技术栈是 Ratpack InfluxDB ActiveJDBC AngularJS,主力开发语言是 Groovy。


最后说下项目的发展情况,项目接入的服务 40 ,打压的次数 1000 ,很好的完成了同学们的打压需求。在做压测工具的时候最大的感触是:很多复杂的问题都能用很简单的模型来解释,在简单模型的基础上按照用户的需求不断开发适配才能成为一个好的框架,Storm,Hadoop 都是如此。项目有些细节的部分大家可以参考我们美团的技术 Bloghttp://t.cn/R4KWHrA。


Q

声明:文章版权归原作者所有 部分文章转自互联网 如有侵权请联系 [邮箱地址] 删除

路过

雷人

握手

鲜花

鸡蛋

相关分类

返回顶部