分布式调度杂谈

  对于规模以上的应用来说,调度系统已经是必不可少的组成部分,尤其是在基于数据分析的后台应用大量增长的今天,健壮的调度任务管理已经是非常重要的一环,因此多花时间来分析研究调度系统的设计对于日常开发与运维具有比较重要的意义。

调度问题从何而来?

  当你的网站是一个简单的blog,并且不需要跟外部交互的时候,你大概不需要调度任务,因为此时网站需要处理的任务仅限于即时交互,即用户想要使用一个功能,你立即给他就是了,如同你在网络上编辑一篇文章,点击保存,这篇文章就保存到网站的后台服务器中去了,这也是互联网刚出现的时候最早的应用模式。

  之后因为网站发展的速度不错,用户多了起来,就发现需要大量处理一些非及时的任务,比如要定时将用户访问日志归档清理,这时候一般情况下会在服务器启动一个定时任务,在每天固定时间发起清理归档,如又想显示网站的访客浏览量,发表文章数,评论统计,由于并非每次用户或者管理员每次需要看的时候都去计算一遍,所以可能又需要启动另一个任务来处理这些数据。这样的任务多了,就需要思考一个问题,那些任务需要先处理,那些任务需要后处理,每个任务要占用多少资源,从而任务调度的问题开始出现。

调度什么时候变得复杂?

  在一个单机的系统,任务并不多的时候,生活依然是美好的。利用Liunx自带的定时器或者系统框架提供的定时任务,实现好任务执行器,配置好任务触发的时间和频率,然后每天等待他自动触发,数据生成,任务搞定,似乎调度也没有那么困难。

  然而好景不长,伴随着网站的发展,你发现任务处理的时间越来越慢,甚至偶尔会有任务超时的情况,原因是每天用户产生的数据量越来越大,每次任务捞起的数量已经超载,一次执行完每个任务,已经可能是最初执行时间的好几倍。

  这时稍微有点经验的你便会想到,任务没必要顺寻执行啊,所以弄个线程池,起多个线程同时来捞数据然后执行,同时配置动态调整每次数据捞取的数量,增大执行效率,一系列组合拳打出去之后,调度任务又恢复正常,由于增加了并发次数,甚至执行的比开始更快了,就这样业务高峰便顺利通过了。

调度什么时候变得更加复杂?

  之期所描述的情况基本上都在单机的情况下,网站的qps基本在500之下,通过一些类的参数调优,串行变并行,任务运行的很平稳,然而当任务变得规模更大,比如十倍于当前,一台机器已经不能处理所有任务,这时候需要增加更多的机器,将任务分配到不同的机器上,于是便有了所谓的分布式调度问题。

  分布式是目前稍大型网站不可避免的问题,这种处理方案有很多好处,比如可以利用廉价的机器,可以无限水平拓展,同时也带来了一系列棘手的问题,机器之间的网路通信,如何把流量均匀的分布于不同流量,如果有机器宕机如何处理,每个问题都已经是一个庞大的技术领域。

  对于调度的分布式问题,首先要解决的便是如何把任务分发到不同的机器上,这要求调度系统通常至少要分为两层,第一层决定一共要处理那些任务并把任务分发到哪些机器上处理,第二层接到任务后具体实行,虽然描述起来很简单,但是这个处理实际过程中需要大量支撑系统的支持,比如在任务分发时如何判断哪些机器还活着可以处理任务,这可能需要一个可以感知整个集群运行状态的配置中心,又比如任务如何分发,是采用消息还是实时服务接口,如果是用消息则派发则需要消息系统,如果是实时服务,又需要类似dubbo这样的分布式服务框架,当系统达到这个复杂度,已经不是将任务捞起并处理这么简单了,而是多个关联系统复杂的叠加。

  分布式调度的难题

  虽然分布式调度带来了复杂度的上升,但是他的水平拓展能力完美的适配了网站的规模发展,直到你有一天看见了类似这个错误

org.springframework.transaction.CannotCreateTransactionException。

数据库连接池已经打满,由于单个数据库的连接数是一定的,这意味着数据库变成了资源瓶颈,这时候给任务处理加机器已经不能提高系统的整体处理能力。这就如同你要运走一群人,给你提供的车辆是无限的,但是汽油是一定的,当然数据库也是可以拓展的,但是考虑到数据迁移的复杂性,这几乎将问的复杂度提高了一个等级,因此,一个分布式系统的吞吐量,在很大程度上是与数据库处理能力做权衡的结果。

你可能感兴趣的:(工作学习笔记)