如何设计一个麻雀般的微型分布式架构? (2)

可扩展:在我们可能会随时增加模拟机器集群的肉鸡数量,或者更多的闲置代理服务器资源加入压测任务。所以系统在可用机器数据表随时加入新的机器。

img

图5 系统的动态可扩展

可恢复:分布式系统不同于单机模式。不能避免可能有各种故障,有时候系统部分节点出错了,我们更倾向于不用这个节点,而不是继续使用未处理完成的结果。即非0即1,无中间状态。还有分布式系统网络传输延迟不可控。所以压测系统设计了一套容错机制:包括心跳检测失败,自动在数据表剔除肉鸡服务端。接口异常容错。超时过期未完成任务去除。crontab定时拉取退出进程等。

简易搭建:使用ajs接口,和批处理安装脚本。自动化部署肉鸡和服务端。配置dns解析ip(日志服务器,任务池、回源率结果所在的数据库ip),tcp time_wait状态的复用,千万别忘了还有一些系统限制放开(放开ulimit fd limit,这里设置100000,永久设置需要编辑/etc/security/limits.conf)。如果肉鸡有依赖程序运行库需要同时下载。在肉鸡机器下载肉鸡客户端和配置、在服务端机器下载服务端和配置,下载定时拉起程序脚本,并添加到crontab定时执行。以上都用批处理脚本自动执行。

一些设计范式的思考 Single-productor and Multi-consumer

在肉鸡客户端的设计中:读日志文件一行一条记录,添加到消息管道,然后多个执行worker从消息管道取url,执行模拟请求。消息管道传送的是一条待执行的日志url。IO消耗型程序指的是如果consumer执行访问日志并瞬间完成结果,但是productor需要对日志进行复杂的字符串处理(例如正则之类的),那么它下次取不到数据,就会被管道block住。另外一种是CPU消耗型程序,如果日志url已经预先处理好了,productor只是简单的copy数据给消息管道。而consumer访问url,经过不可预知的网络延迟。那么多个consumer(因为是包括网络访问时间,consumer个数设计超过cpu核数,比如2倍)同时访问,读端速度慢于写端数度。在对一个日志文件进行实验,我们发现处理18w条记录日志的时间是0.3s,而执行完这些url的访问任务则需要3分钟。那么很显然这是一个CPU消耗性进程。如果是IO消耗型的程序。Golang有种叫fan out的消息模型。我们可以这样设计:多个读端去读取多个chan list的chan,一个写端写一个chan。Fanout则将写端的chan,循环写到chan list的chan中。

Map-reduce

我们有时会做一个地理位置一个运营商的机房日志分析。一个机房包含数台机器ip。合理的调度多个肉鸡客户端并行访问日志,可以更快速得到合并回源率数据。

并行机制,经典的map-reduce,日志文件按机房机器ip纬度切片分发任务,启动N个肉鸡同时并行访问,等最后一台肉鸡完成任务时,归并各个肉鸡数据按成功请求数量、成功请求流量、失败请求数量、失败请求流量等方式做统计。同时用于和线上日志做校样。这里的mapper就是肉鸡,产生的数据表,我们按照关注的类型去提取就是reducer。

简化的map-reducer(不基于分布式文件系统),map和reduce中间的数据传递用数据表实现。每个mapper产生的日志数据先放在本地,然后再上报给数据表。但是数据表大小的限制,我们只能上传头部访问url。所以如果用这个办法实现,数据是不完整的,或者不完全正确的数据。因为也许两台肉鸡合并的头部数据正好就包括了某肉鸡未上传的日志(该日志因为没有到达单机肉鸡访问量top的标准)。

那么如何解决这个问题呢,根本原因在于汇总数据所在的文件系统是本地的,不是分布式的(hadoop的hdfs大概就是基于这种需求发明的把)。如果是状态码纬度,这种思路是没问题的,因为http状态码总量就那么少。那么如果是url纬度,比如说某机房给单肉鸡的单次任务在10分钟的url总数据量达到18万条。只看日志重复数>100的肉鸡数据。这样误差最大值是100*肉鸡数,所以对于10台肉鸡的机房,只要是综合合并结果>1000。都是可信任的。如果是域名纬度,少数头部客户流量占比大多数带宽。 这也就是所谓的hot-key,少数的hot-key占据了大多数比例的流量。所以域名纬度时,这个时候可以把关注点缩放在指定域名的url列表。如果本地上报给数据表的数据量太大,url也可以考虑进行短地址压缩。当然如果不想弯道超车的话,需要硬解决这个问题,那可能得需要hdfs这种分布式文件系统。

Stream-Processing

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpsgsx.html