概述
最近看到一个在生产中运用的工具,用于同步不同来源的数据到hdfs,而且运用的较为广泛,但是业务反馈问题也颇多。所有的任务通过写脚本形式直接扔到特定的几台机子上,都是采用磁盘传输。存在几个问题:
- 使用难,维护和扩展难。没有输入控制,没有统一的日志打印机制。每个人员都必须记住自己配置的目录,文档没有维护好很容易漏。随着数据量的递增就需要考虑分盘,甚者分服务器。配置会更加眼花缭乱,容易出错。也容易影响到其他服务器目前配置的任务,容易引发新的异常。
- 对接新需求容易干扰现有业务。应对突发问题,内化问题能力不足。现在缓存目录都是各个业务自己配置上去,没有全局的视角去做资源的权衡,很难知道自己上线的同步任务会对现有传输造成什么影响。磁盘传输速度有限,发生异常,历史接连几个任务需要同时在同一磁盘上传输容易造成,互相干扰,导致传输速度急剧下降。
- 容错能力弱。filesync在同步的时候,会先去ping目标服务器,如果可以ping通,那么任务就会发往默认的第一台服务器,不论服务器的磁盘负载是否高。最坏的情况就是所有经过相同传输服务器的job都延迟。备用机的资源没法利用上。最坏情况是经过相同节点的传输的任务都延迟
RP不行,这个东西现在落在我手里进行维护。看到糟糕的设计心里就痒痒的,在看一下那一点美感的代码都没有,心里更是急痒难捱。有美感的代码是让自己保持对开发充满激情的原生动力之一,这种破坏原则的东西,不能容忍呀,遂开始构思
第一版
原先的设计定位为工具,看起来挺简单,用户需要需要配置相关参数,确保数据传输的机器之间是有权限进行数据拷贝传输的。就可以实现上传。 产生的问题入概述中所列
第二版
开始引入管理的意识,将配置统一放到数据库,由application进行读取。避免重复开发,提升整个工具的三性(可复用性,可扩展,可维护)。更确切地说他应该已经是一个系统,而不是工具。从这个角度来看,这也是我认为Sqoop1和Sqoop2最大的区别,一个是工具,一个是已经具备一定管理能力的系统。
第三版本
随着数据量的提升,一台机器肯定不够用,这时候会部署多台机器,client端随机ping下可用的机器,ping同则将任务提交到该台机器。这样的设计最直观的益处是通过人为指定ping的顺序,可以将原先一台服务器任务,分成多台机器共同承担,可以缓解一定的压力。同时坏处就是,客户端需要知道服务器地址,违背了组件通信最少知识设计法则。由客户端去控制传输的服务器显然也不可靠。依然可能产生作业相互干扰,提升的容错能力极为有限。这种情况最坏情况下回变成第二种版本。
第四版本
在这里我们引入控制中心,所有的server都会在控制中心注册,并定时上报系统目前的资源状况,当作业提交后,控制中心根据各台机器的资源状况选择一台或者若干台的机器,执行任务。到这个版本,可以实现在提升整个系统的三性的同时,引入资源管理这样一个层面的组件,实现对多台服务器的统筹管理,整个服务上升成为一种集群形式,提供系统容错性,降低了由于资源没有充分利用而造成的任务踩踏的问题。已经可以解决概述中提到的三个问题
第五版本
这个版本引入是出于内心的隐僻吧!控制中心集成了资源管理和作业管理,职责太多,代码耦合较为严重。所以从控制中心拆分成作业管理,资源管理俩个组件。资源管理负责收集各个server的存活状态和服务器资源状态。作业管理,对作业进行拆分,然后对拆分的子任务单独进行资源申请,申请到资源的子任务会被分发到相应的服务器。为了不影响其他作业,eg一个任务抛出异常导致整个服务异常,每个application执行任务采用container的形式,去执行每个子任务。application 将收集container信息执行状态,并反馈给作业管理。作业管理根据状态,信息用于判断是否进行重新调度。
下图是作业管理的基本类图设计
心得与总结
看过yarn的同学可能最后的设计有yarn设计的影子。但是说实话,yarn的源码和设计很早以前看过,但是在写本文的时候没有刻意去查找yarn的资料。我要说的其实,一句话循原则设计。这点可以借鉴面向对象的设计原则:
- 单一职责原则(Single Responsibility Principle) 每一个类应该专注于做一件事情。
- 里氏替换原则(Liskov Substitution Principle) 超类存在的地方,子类是可以替换的。
- 依赖倒置原则(Dependence Inversion Principle) 实现尽量依赖抽象,不依赖具体实现。
- 接口隔离原则(Interface Segregation Principle) 应当为客户端提供尽可能小的单独的接口,而不是提供大的总的接口。
- 迪米特法则(Law Of Demeter) 又叫最少知识原则,一个软件实体应当尽可能少的与其他实体发生相互作用。
- 开闭原则(Open Close Principle) 面向扩展开放,面向修改关闭。
- 组合/聚合复用原则(Composite/Aggregate Reuse Principle CARP) 尽量使用合成/聚合达到复用,尽量少用继承。原则: 一个类中有另一个类的对象。
遵循原则做事,其实他是超越粒度的一种设计法则,不管是在类级别,还是模块级别,甚者服务级别他都是可以适用的。eg:在遵循原则对类进行设计的时候,会不知觉发现你已经适用某个设计模式。在遵循原则对模块进行设计的时候,会不知觉发现对模块的边界切面很平整,有毛边的边界切面一般是糟糕的设计。