由SEDA想起的

最近与一个以前的同事聊天,发现HW已经开始用asyncweb+mina做web应用的开发。想我不在深圳的这段时间,还是发生了不少事情嘛!

SEDA提出有些时日了。只是从一开始到现在,好象没有过特别受到追捧的情况发生。然而默默的跟随者却一直不少。mina,asyncweb,asyncobjects等的出现及其风行就是跟随的证明。

其实使用SEDA的思想做一个智能任务执行框架一直是我的一个想法。只是一直被别的事情给困住,加上对分阶段思想的犹豫,所以一直没有动手。今天终于看到异步应用的落地,便又重新拾起以前停掉的思路,看能不能有什么新的发现。

SEDA全名是Staged Event Driven Architecture。关键是Staged。因为What drives it其实并不是太重要。或者说,那其实只是一个完全技术层次上的问题(考虑性能)。

刚开始的想法是跟着作者的想法走,即分阶段的目的当然是为了异步。不对程序进行横切,如何异步?正如如果不对程序进行纵切,就做不了AOP。也就是说,分阶段的思想是基于异步而提出来的。

但是,时间一长,问题开始从大脑中跑出来!

异步当然是好事,所以分阶段也是好事。但异步的内容其实主要是指计算机的指令集中两种不一样的指令集:内存指令集与IO指令集。因为,在计算机内部,单从硬件的角度看,其实存在的也只有这两种操作。即一种内部操作,一种外部操作。有些计算机可能将IO与内存一起编址,但内外的区别其实仍然是无法抹杀的。

问题也正是从这里开始冒出来的。既然只有两种操作,也就意味着即使我们一定要对一个程序进行阶段划分,也并不能从中划分出太多的阶段。因为边界是非常清楚的---IO与非IO。这样一来,事情就没意思啦!但是直觉告诉我SEDA肯定是一个有意思的东东!所以,继续研究。。。

所谓的继续研究,其实是没有研究。没有思路,怎么继续。但是,福从祸中来!就在我几乎快要忘了这个东西的时候,突然冒出来了个函数式编程。

这东西很怪异,很象21世纪的改良基因恐龙(如果有的话)。到底好不好,还没有人知道。但有人用,肯定就有它的原因。于是,研究。。。结果发现其竟然不用栈,只用堆!难怪它从发明以后睡了50多年---电脑一直没有快到使一个只用堆的程序的运行效率能被人们所接受。

相较于基于栈的语言(使用栈作执行期存储),分支图固然是一个好思想,运行历史因而得到保留(这使得一切都成为可能)。即使是在基于client-server理论建立起来的栈执行架构中(比如,OO),被保留下来的历史也是一张藏宝图(延续可以是很多种方式。其中的一种就是转移到“服务”的调用者---非常功利,但却也非常实用。而大多数函数式编程语言中所允许的自由跳转看起来则更象是一个被好奇心冲昏了头脑的成人精神病患者---很难利用这些人完成任何社会意义上的工作---当然,这也不是说他们就一无是处。很多科学家都是这样的人。他们当然是有用的!)。

Anyway,Functional Programmers声称的一个最重要的优点就是在他们的语言环境中,方法调用的深度是不受限制的。比如,你可以写一个递归深度为10的10次方的程序用来计算10000000000的阶乘!

对于一个坚守OO阵营(在编程领域)的我来说,这样的牛皮让人有点受不了。但却又明明,的确是OO的一个软肋。OO使用栈作执行结构。每个人都知道栈是有深度限制的。所以,在站出去与人理论之前,还是先解决自己的问题吧(虽然到目前为止,我仍然不得不承认,FP比起OO的确是要优美很多---它充分了解硬件的特征,离硬件更近。而不是如OO一样,强调的是硬件要为人类服务---想法不同,自然结果就不同。结论)。

一个无止境的服务委派链可以让任何系统崩溃(如果FP这么干,FP一样要崩溃。但是它没有。FP的任务模型是接力),这在现实社会中一样存在。比如在一家公司中,如果每个人完成一件任务都需要别人帮忙,那么最终整个公司所有人力都将被拖入这一个任务中,并且使得接受新任务的资源本身也被耗尽而最终使得整个系统(公司---这个词也很有趣是吧)崩溃!

幸运的是,经过几百年的商业进化,我们早就已经不这么干了。我们这么干---给业务设计一个流程。流程中的指定部分由指定的团队完成。不同的流程之间由一个状态集进行交互。整个公司是一个状态机。业务的流入流出随时受到严格或不严格的监控。

这种思想完全可以被应用到程序的执行中。因为不管一个程序到底有多长(有限长还是无限长),我们都可以通过使用有限长的子程序去完成(或者尝试完成)它。比如,我们谁都不知道地球到底还要围着太阳转多少圈,但只要设计一个转圈的程序,我们可以让地球不停地转下去!

这在一些大型应用中非常有意义。因为一个大型应用的方法调用深度在不受控制的情况下很可能超出人们的想象。分层设计,库的应用,设计模式,一层又一层的标准接口,很容易就可以让一个大型系统陷入崩溃或者软崩溃(拒绝服务)。如果说良好的控制,大容量内存的确可以在某个程度上解决这个问题的话,那么面对一个分布式应用或者SOA架构的系统,或者存在大量进程依赖的本地系统,在一个延迟剧烈上升10倍乃至100倍,1000倍的情况下,你到底有多少内存呢?你还要不要并发?

其实,分阶段的本质除了异步,更重要的本质是以空间换空间。

软件业的从业者几乎都应该听过以时间换空间,或者以空间换时间这样的词。但是以空间换空间应该是第一次听说。不要惊讶,你还没有老!因为我自己也是第一次听说。我原来想到的当然不是这么酷的句子,但你要是把一件东西啄磨透了,到最后就总会说出一些很酷的句子---越酷的句子,归纳性越强,抽象性也越强。

还说上面的阶乘例子。用递归的办法算出10000000000的阶乘在OO中当然没办法做(这里忽略乘法溢出以及一些支持函数式编程的OO语言)。但如果能恰当地使用中间结果(小空间)来代替长长的栈(大空间),问题就可以得到完美的解决。实际上,循环就是这么干的(但是别高兴太早,因为你是没有办法在一个异构环境中或者分布式应用中使用循环的。再者,并不是所有的流程都可以转换成一个循环的。是循环利用了中间结果这个思想,而不是中间结果来自循环的思想。中间结果就是中间结果,它有完全独立的含义)。

也就是说,当你要做一个很长(时间与空间上。我后面会有文章讲到,内存开销=内存的大小*时间。这与物理学中的“W=Pt”是一样的道理)的任务时,应该根据调用逻辑将它划分成多个子任务。然后为每一对子任务之间设计一个合理大小的数据接口。子任务之间通过这些数据接口进行异步的任务执行。

记住:本文的目标不是SEDA所关注的异步。而是长栈导致的长时间等待所造成的空间浪费,和用中间结果来解决这个问题的能力,以及大型或分布式应用的高延迟所造成的等待问题(最终仍然是空间浪费)。

我要看电视了。。。这个也差不多了,以后有时间再补!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值