banq
2013-10-13 09:48

基于异步消息传递提供了一个事件驱动系统的可扩展性Scalable基础。组件和子系统之间的松耦合和位置独立性使其能够向外扩展到多个节点,同时保持相同的编程模型具有相同的语义系统。添加一个组件的多个实例,提高了系统的容量来处理事件。在实施方面没有任何差别扩大利用多个内核,或利用数据中心或群集多个节点向外扩展。应用程序的拓扑结构变成一个通过配置和/或响应的应用程序使用的自适应运行算法进行部署的决定。这就是我们所说的位置透明性location transparency。

重要的是要明白我们的目标是不要使用分布式对象或RPC样式尝试实施透明的分布式计算,这些已经尝试过并且已经失败。相反,我们需要直接通过编程模型的异步消息传递,直接和网络拥抱。真正的可扩展性,自然涉及分布式计算和与节点间的通信,这意味着穿越网络,这在本质上是不可靠的。因此(我们要直接面对不可靠的因素),最重要的是在制约、权衡和故障情况下的进行网络编程,而不是隐藏网络,尝试以一种错误的“简化”方式编程。在分布式环境中类似消息的抽象机制已经达成共识,因为它提供了更高程度的可靠性。

banq
2013-10-13 10:01

应用程序停机时间是最具破坏性的可能发生的问题之一。通过简单的Stop操作,造成了营收漏洞。从长远来看,它也导致客户不满和声誉不佳,会更严重伤害企业。令人惊讶的是,应用弹性是一个在很大程度上被忽略的技术要求。这意味着,我们在解决问题是使用了错误的工具,因为我们站在一个太粗粒度的水平上解决问题。一种常用技术是使用应用服务器集群进行运行和服务器故障的恢复。不幸的是,服务器故障转移是极其昂贵的,危险可能导致了整个集群的级联故障。原因是,我们是站在一个错误的水平上进行故障管理,只有使用细粒度组件才能提高应变能力。

Merriam-Webster定义Resilient弹性:
1.物质或物体拥有形状上弹回的能力。
2.从困难中恢复的能力。

在一个reactive应用中,应变能力不是一个可有可无的东西,而是从一开始就成为设计的一部分。故障应对在编程模型中构建时就第一面对,这就导致应用程序是高度宽容失败并在运行时能够提供手段愈合修复自己。传统的故障处理是不能做到这一点,因为它是要么防御小,要么过于激进,你必须在系统的一个个地方去处理异常Exception(banq:将你的方法到处加上try{}catch)。



[该贴被banq于2013-10-13 10:04修改过]

banq
2013-10-13 10:47

为了管理失败,我们需要一种方法来隔离它,使它不会扩散到其他健康的部位,并能观察它,从失败的上下文以外的安全点对其进行管理。一种模式是bulkhead pattern,如下图,说明系统是建立了安全车厢,所以如果其中一个出现故障,不影响其他的。这可以防止级联故障的经典的问题,并允许隔离管理问题。

事件驱动的松散耦合提供了组件在失败下可以抓获完全隔离的上下文场景,作为消息封装,发送到其他组件时,在具体编程时可以检查错误比如是否接受到,接受的命令是否可执行等等,并决定如何应对。

这种方法创建了一个能让业务逻辑保持清洁的系统,显式的隔离分开处理Exception的有利于观察,管理和配置,并能让系统自行愈合,并自动恢复。这类似在一个大公司内,将一个问题逐步向上升级,直到达到有权力来处理它的水平。

这个模型的美妙之处在于它是纯粹的事件驱动,它是reactive组件和异步事件,意味着在分布式环境中具有在本地一台服务器范围内相同的语义。


banq
2013-10-13 11:00

Merriam-Webster定义Responsive为:迅速回应或作出适当的反应。
我们使用这个词在一般意义上不应该与响应的网页设计混淆,后者主要是指CSS媒体查询和渐进增强。

响应的应用程序是实时的,耐看的,丰富的和协作。企业与他们的客户建立一个开放的和持续的对话,欢迎他们通过响应的互动体验。这使得它们更有效率,建立连接,并配备解决问题和完成任务的感觉。一个例子是,在使用谷歌Docs 时,几个用户能够编辑文档协作,能实时地让他们看到彼此的编辑和注释的结果。

对事件作出响应的应用程序,需要及时去做(just do it),即使存在故障情况。如果应用程序在长时间不做出回应,称为延迟,这个系统实际是不可用的,因此不能被视为弹性。

当然并非所有应用如武器或医疗监控系统这样对实时要求如此高,但是通常他们在运行一段时间后出现迅速下降的性能,才可以从他们偏离了一点响应限制看出(banq: windows越用越慢),假如是金融交易应用程序可能会失去目前的交易没有及时回应。

banq
2013-10-13 11:14

reactive应用使用可观察模型,事件流和有状态的客户端。

可观察的模型:状态变化时能激活系统接收事件。这可以提供一个用户和系统之间的实时连接。例如,当有多个用户同时操作同一模型,改变能够在它们之间双向同步,这样这个模型就不必通过锁的约束进行共享状态。(参考:http://www.jdon.com/45728)

事件流形成于建立连接后的基本抽象。保持他们的reactive是为了避免阻塞,当然允许异步和非阻塞的转换和通信。

Reactive应用积极拥抱算法顺序,通过使用设计模式和测试确保响应事件在O(1)或 O(log n)时间内返回,根本无需顾及系统负载。


考虑一个web应用程序,它具有丰富的客户端,基于浏览器或移动应用程序创建引人入胜的用户体验。此应用程序将在客户端执行逻辑和存储状态,这里有一个可观察的模型提供了一种机制,当实时数据更改时及时更新用户界面。

WebSockets or Server-Sent Events能让用户界面和后端推送的事件流直接连接,这就允许reactive应用能推送事件到浏览器或移动客户端,这是通过一种异步非堵塞的可扩展弹性的方式。

banq
2013-10-13 15:47

点评:

宣言中提到的传统同步架构是指JavaEE 6或Spring或.NET之类的SOA应用,这些应用虽然将软件进行了多层架构划分:Web层(SpringMVC/JSF)、应用服务器层(EJB或Spring)和持久层(Hibernate/JPA等),每层之间包括层内部调用都是同步的。

所谓同步调用,就是普通的方法调用,比如MVC里面的Action的方法调用一个服务的方法,这个服务的方法里面再调用Hibernate或JPA进行存储,返回结果,这种同步调用每个步骤都是在一个线程内发生,属于同一个流水线,如果其中一个环节发生堵塞等待,致使最后响应被延迟。

而reactive引入或者说异步的引入,将这些层之间调用放在不同线程之间实现,不是顺序执行,而可能是并行执行,见:关于Ebay的架构之一Asynchrony Everywhere

reactive实则是让原来被线程访问的每个对象,不管是业务对象还是实体等等,都能够自己发出自己的线程,而不是被动地加入访问的这个线程顺序中。

reactive架构是DDD以及CQRS的自然代码实现,有了reactive,CQRS能够方便实现,DDD的领域模型自己也能够发出事件,能够真正成为系统中指挥主角,而不是被动地被访问的线程激活。

有了reactive/EDA/Actor模型这些概念,我们只要直接基于组件模型编程,而不必有线程概念,屏蔽了底层线程的编程难度,比如在JdonFramework中有两个组件:模型和组件,模型和组件之间可以互发消息事件,在JF框架或其他reactive框架或语言平台上编程,可以回避线程,但是能编制出高并发高吞吐量高事务的应用,这些完全可以替代传统JEE或Spring或.NET。

如果你相信这样的架构代表未来,那么请去宣言网站投票支持,目前全球已有1800名投票。

banq
2013-10-13 19:49

2013-10-13 09:48 "@banq"的内容
重要的是要明白我们的目标是不要使用分布式对象或RPC样式尝试实施透明的分布式计算,这些已经尝试过并且已经失败。 ...

EJB作为分布式对象实现,是一种同步RPC,其实已经宣告失败,这可能对EJB规范是否有下一个版本的重大打击。

而JavaEE中的消息系统规范JMS反而可能被证明是成功的,其也是SOA的ESB一种实现,但是如果不能让程序员直接面对网络通讯编程,比如一个消息消费者可能在另外一台服务器上,也可能是本地的另外一个线程,反正别管消费者在哪里,你都要面对通讯问题,在别的节点服务器,你面对是基于socket的通讯,而如果在一个容器VM内,你面向是线程通讯问题,当然具体怎么通讯已经有现成的库包,关键是你编制业务代码时,你已经知道生产者和消费者是分离,你有这样一个预想场景,你就会提前设计防止可靠性等问题。

而分布式对象如EJB则告诉你,你别管对象在哪台服务器上,你只要闭眼编程即可,到时会自动给你分布式部署,但是网络本身并不是100%可靠,如果一旦出现问题,很难追查,因为你编程时,根本不让你知道可能会分布,粗粒度,你想追查只能请webshpere或oracle等服务器专家来。就是帮助你解决问题,下一次问题出现在分布式网络哪里谁也没有把握,整个系统的可靠性就大大降低。

这篇宣言还提到,不但要scale out 或in,这是指水平或横向扩展,还需要垂直或纵向扩展Scale up/down。我们以前谈分布式网络,总是狠批垂直扩展,水平扩展通过增加廉价服务器容易低成本,CAP定理和BASE原则都出来了,总是说垂直扩展是购买更高级的服务器,其实垂直扩展也可以是增加CPU核数,现在手机都是4核了,多核的垂直扩展看来也是比较廉价的,如何利用廉价多CPU,这就需要reactive的并发编程了,有可能节省好几台廉价服务器的投资,也是一种节约。

垂直扩展适合于结构化数据,比如在CQRS中对DDD聚合的写入操作(Command);而横向扩展适合非结构化数据。
[该贴被banq于2013-10-14 09:47修改过]

banq
2013-10-14 06:36

2013-10-13 11:14 "@banq"的内容
reactive应用使用可观察模型,事件流和有状态的客户端 ...

reactive特别适合有状态的客户端,而REST是一种状态转移接口,reactive + REST + 有态客户端 是未来一种趋势。

为什么要使用MVC+REST+CQRS架构: http://www.jdon.com/45602

基于任务的UI(Task-Based UI):
http://www.jdon.com/45385