任务是指实现单一功能的单元。对于"单一功能"的认定没有通用标准,单元的颗粒可大可小;可以是一个算法的实现、一个公共方法或者一个事务等。
一般的系统采用基于任务的架构,主要针对两个问题:1,并发执行的需要;2,定时执行;对于以上两种场景的分析这里不再赘述。我从解耦的角度再深挖一下这种架构模式的优点和适用场景。提到解耦,经历过分布式系统设计、开发的同仁都有体会;它是系统容量、性能、可扩展性、可维护性提升的重要基础。实现解耦的主要途径是分布式系统间的接口调用、引入消息中间件、利用DB持久化等方式;这是较大颗粒度的解耦,由于接口调用、消息、持久化等方式都是物理层面的解耦,所以从软件实现看:解耦地生硬。
我想更加精细的解耦-采取任务模式的系统架构,将任务间数据的传递采用分布式系统间接口调用、消息、持久化等;而任务间数据的传递通过任务执行引擎对任务屏蔽。同步方法调用如下图左侧所示,(分布式系统间的同步)接口调用也于此类似;过渡到任务模式的系统架构时,调用关系发生了变化:方法间不再直接调用,而通过任务执行引擎(配合事件或者工作流)组装了方法调用;任务的运行时可以利用多线程获得更好的执行效率,也可以利用执行引擎获得对稀缺资源的软同步控制。
基于任务的系统架构更容易实现分布式横向扩展,与面向接口相比,它是面向(任务执行所需的)数据的,不存在接口变动的重构问题,且将数据处理算法封装在一个独立执行的单元中。任务的执行有两种策略:1,由前一个任务执行完后,启动下一个任务;2,由守护线程根据通过状态机创建执行任务;这两种方案我比较倾向后者;本质上差不多,但是后者对于测试有更好的效果。
基于任务的系统在TDD、BDD、DDD都有比较好的使用效果;一般意义的TDD是面向API或者接口的,这里的TDD是面向任务的,明确了每个任务执行之前、执行之后数据的状态机;从而为业务级别的复用奠定了基础;在BDD的实践中,任务模式也可以获得很好的测试效果,因为BDD就是通过比对数据的值校验测试结果的。以上两类测试中,都不用启动任务引擎,通过任务间的方法调用,就可以实现测试过程。DDD是从业务级别的封装,也就是大粒度的任务或者任务组合。
有利就有弊,与单一应用相比,这样的系统架构比较复杂;与(接口调用式的)分布式系统相比,这样的系统架构也无法利用语言的静态检查。比任务架构更复杂的是基于事件的Actor架构,后者更加精致,并发性能更好。
该系统架构的关键在于控制任务的颗粒度。