web站点服务中,我们除了存在面向用户的服务功能外,往往也存在大量的后台离线的相关计算任务,如对前端的异步操作数据队列进行定期处理,对数据库中的数据进行汇总挖掘,监控,转储,对中间数据的进一步运算处理等等……一个web服务站点的背后,往往存在大量对应的后端处理任务的功能模块,用于支撑正常的业务功能系统。
在一个web站点的初始阶段,我们可能只需要有一台服务器,容纳部署所有的业务功能,包括了面向用户的前端web服务功能,数据存储,后端离线处理业务功能。随着站点的业务功能越来越多,用户访问数的增加以及数据量的增长,单台服务器的处理能力往往就面临瓶颈。这个时候简单的处理就是将前端web服务功能,数据库和后端业务模块分开部署在不同的机器上,但是可能过随着站点规模的逐渐庞大,单个服务器也无法支撑前端web服务,数据库服务或者后端离线业务功能。Web前端服务,数据库服务相对是通用的技术服务,相关业务都大同小异,其分布式化在业界有相对很成熟和典型的架构模式解决方案,但是不同系统的后端离线业务功能可能千差外别五花八门,不同开发者开发出来的功能架构也各不相同,本文介绍一种低代价的web站点离线任务分布式改造方案,其使用了glusterfs分布式文件系统以及gearman分布式运算框架。
我们知道,相关离线运算要能进行分布式化运算,做到单次执行在任意一台机器上执行都可以,其首先的要求就是程序依赖输入输出数据的非本地,我们要实现运算的分布式化,就必须实现所有存储数据的中心化存储以及分布式化。
一 存储的中心化和分布式化
我们知道一个web站点的业务功能必然要使用各种数据,需要存放各种数据,基本上是以关系型数据库,nosql数据服务,session数据,cache数据,原始的服务器文件数据存储。对于关系型数据库,nosql数据库,其本身就是中心化的数据存储,其分布式化也有成熟的解决方案,对于站点session,相关cache数据,也有成熟的memcached等利用而进行中心化存储,以及进行分布式的扩展。对于大多数后台离线业务功能来说,往往是开发人员逐渐开发堆积而来,这些功能程序往往会存在大量对本地文件的直接读写,如果改造使用其他存储方式,工作量巨大而且风险大,这些数据的中心化存储改造往往成了解决数据存储中心化的聚焦点,而且所幸,业界有大量成熟的分布式文件存储系统,能够帮我们解决本地文件存储的中心化和分布式化存储。我们介绍一种使用glusterfs进行对本地文件存储的分布式化处理方案。
分布式文件系统(Distributed File System)是指文件系统管理的物理存储资源不一定直接连接在本地节点上,而是通过计算机网络与节点相连。分布式文件系统的设计基于客户机/服务器模 式。一个典型的网络可能包括多个供多用户访问的服务器。另外,对等特性允许一些系统扮演客户机和服务器的双重角色。例如,用户可以“发表”一个允许其他客 户机访问的目录,一旦被访问,这个目录对客户机来说就象使用本地驱动器一样。
GlusterFS是 一个高层次的分布式文件系统解决方案。通过增加一个逻辑层,对上层使用者掩盖了下面的实现,使用者不用了解也不需知道,文件的存储形式、分布。
内部实现是整合了许多存储块(server) 通过Infiniband RDMA或者 Tcp/Ip方 式互联的一个并行的网络文件系统,这样的许多存储块可以通过许多廉价的x86主 机,通过网络搭建起来。
其相对于传统NAS 、SAN、Raid的 优点就是:
1.容量可以按比例的扩展,且性能却不会因此而降 低。
2.廉价且使用简单,完全抽象在已有的文件系统之上。
3.扩展和容错设计的比较合理,复杂度较低。扩展使用translator方 式,扩展调度使用scheduling接口,容错交给了本地的文件系统来处理。
4.适应性强,部署方便,对环境依赖低,使用,调试和维护便利。
支持主流的linux系统发行版,包括 fc,ubuntu,debian,suse等, 并已有若干成功应用。
对于一个站点的后端离线功能的文件存储来说,我们既希望能将这些文件数据存储中心化,又希望能够兼容已有的代码,基于这两种考虑,我们可以按照如下的方案图来进行本地文件迁移到glusterfs文件系统:
这样,我们就即能实现文件存储的分布式化,又能兼容已有业务程序,做到无缝迁移。
二运算任务分布式化
当我们的业务程序依赖的存储和数据都中心化,而不依赖于本地存储的时候,我们的运算任务就可以在任何一台部署环境和代码运算服务器上运行,我们唯一缺少的就是一个任务的队列调度处理模块。我们介绍一种基于gearman的分布式运算框架。
Gearman是一个用来把工作委派给其他机器、分布式的调用更适合做某项工作的机器、并发的做某项工作在多个调用间做负载均衡、或用来在调用其它语言的函数的系统。
一个Gearman请求的处理过程涉及三个角色:Client -> Job -> Worker。
Client:请求的发起者,可以是 C,PHP,Perl,MySQL UDF 等等。
Job:请求的调度者,用来负责协调把 Client 发出的请求转发给合适的 Work。
Worker:请求的处理者,可以是 C,PHP,Perl 等等。
因为 Client,Worker 并不限制用一样的语言,所以有利于多语言多系统之间的集成。甚至我们通过增加更多的 Worker,可以很方便的实现应用程序的分布式负载均衡架构。
另外,我们的离线运算任务往往会存在着针对一类任务一些并发控制,任务去重,防追赶等等功能要求,我们就可以利用gearman做任务队列,同时做二次开发,利用其他技术手段,如mysql存储介质下的任务数据存储更新和分析,来实现这些并发控制和去重。可以按照如下给出的一种架构来进行离线任务分布式改造:
其中发送端调用统一的api来发送任务到gearman任务队列,并且记录相关任务信息到任务状态记录模块,由部署在运算机上的worker来消费和执行任务。
任务发送端的处理逻辑如下图所示:
按照这个流程,任务发送端可以实现任务的去重功能。
Worker的任务消费流程如下:
这样的结构不仅能够实现任务的分布式化执行,而且可以执行一类任务的并发控制,同时通过任务执行前检查机器资源状况,实现对机器资源的基础保护,防止大量任务在集中个别机器上执行,使该服务器出现负荷过重,任务拥塞的情况。
至此,我们解决掉存储的中心化和分布式化,任务的分布式化,新的任务的添加也只要纳入该框架下运行即可,随着我们的站点规模的增大,我们可以方便的加机器进行扩容,透明的进行存储扩容和运算能力扩容,就不会再面临结构上的不可扩展性。
下面以一个简单的平台应用例子来举例,有一个平台,其存在大量后台cronjob定期任务,也存在各种需要对平台的全量数据等进行批处理运算处理的功能,我们在架构设计的时候,必须考虑到服务的水平可扩展性,也必须要有高可用性,具备强大的热容灾能力,同时,我们也需要大量面对cronjob任务的防追赶,加锁,批处理任务的并发执行度控制等问题,下面看看如何设计该平台系统后端架构。
首先,该平台的存储我们都使用非本地的存储,包括数据库服务器,相关cache存储,还有分布式文件存储系统以及相关网络访问。
采用上面介绍的方案采用gearman分布式框架进行部署,2台gearman服务器,6台运算服务器,以主备的模式来使用gearman-server,充当执行任务的队列调度器,在6台机器上各自部署消费worker程序,在另外一台机器上部署启用linux系统的crontab,向gearman中发送cronjob任务给gearman,然后,针对任务的去重和并发控制,我们设计如下的任务记录模块,简单用mysql表来存储相关的任务消息,用于实现防追赶去重和并发控制效果,其中一张关键的任务执行记录表的格式如下:
针对不同类型的执行任务,我们可以设置不同类型的参数
将任务发送端程序和消费并发控制逻辑封装到平台公用模块中,透明的进行调用和任务消费执行
针对cronjob类型的任务,平台crontab主发送机上添加发送端任务
*/10 * * * * /home/work/php5/bin/php /home/work/ala-service/bin/cronjob/client_cronjob.php -t $type_id &> /dev/null
($type_Id为在任务注册表中添加的任务的编号id字段)
那么注册的任务触发后就会随机分配到6台运算机上去执行。
而针对应用程序主动调用发送的任务执行方式,我们只需要在发送端内嵌封装好的发送端程序即可实现任务发送,下面图举一个简单的PHP简单封装的发送端程序调用方式
发送端只要如此调用即可以发送任务去执行,后端运算机获取任务后进行执行。
如此,运营前面所述架构思路,做2次扩展开发,就可以方便的实现该后端平台的需求,其可以方便的水平扩展,机高的可用性,调用方便,实现真正的离线任务分布式化。
将任务发送端程序和消费并发控制逻辑封装到平台公用模块中,透明的进行调用和任务消费执行
针对cronjob类型的任务,平台crontab主发送机上添加发送端任务
*/10 * * * * /home/work/php5/bin/php /home/work/ala-service/bin/cronjob/client_cronjob.php -t $type_id &> /dev/null
($type_Id为在任务注册表中添加的任务的编号id字段)
那么注册的任务触发后就会随机分配到6台运算机上去执行。
而针对应用程序主动调用发送的任务执行方式,我们只需要在发送端内嵌封装好的发送端程序即可实现任务发送,下面图举一个简单的PHP简单封装的发送端程序调用方式
发送端只要如此调用即可以发送任务去执行,后端运算机获取任务后进行执行。
如此,运营前面所述架构思路,做2次扩展开发,就可以方便的实现该后端平台的需求,其可以方便的水平扩展,机高的可用性,调用方便,实现真正的离线任务分布式化。
by makaiwen