事件概念正在重塑分布式系统的未来

banq 18-03-24
                   

这是Akka的创始人和Lightbend的创始人Bonér博内尔在2018 Qcon伦敦大会上的演讲,他已经使用事件概念20多年,现在引起了越来越多人的兴趣,他认为这是因为下面四个原因:

(1)云和多核架构
(2)微服务和分布式系统
(3)以数据为中心的应用程序
(4)客户需求 - “我们需要更多,而且我们立即需要它”

Bonér博内尔首先阐述了事件的这个概念。事件是不变的发生过的事实。你只能添加事件或事实,这意味着关于事实的知识只能增长。事件也可以忽略不计,但一旦被接受,他们将无法被删除或退回。然而,一个事件可以被后来的新事件标记为无效。

事件驱动的服务是对他们收到的事实(事件)进行接收并进行响应。在服务中,我们可以有一个可变的状态,但是这个状态必须完全被封装且不可观察(无法被外界直接修改,只能通过事件修改)。该服务通过向外界发布新事实来对外界输入做出反应。

在事件驱动的世界中,所有事件都是最终一致性。没有传统意义上的事务或强一致性,Bonér认为这应该是默认的。对他而言,如果没有其他选择,否则选择强大一致性应该是一种罕见的事情(特例)。他强调我们必须依靠最终一致性,因为这才是现实世界的真正工作方式。

一旦我们走出服务的边界,我们就进入一个不确定的世界,我们称之为分布式系统或网络。在服务之间可能会出现意想不到的事情,消息会被丢弃或重新排序等等。但是,网络也为我们提供了解决方案; 我们只需要对不确定性进行建模,Bonér提到了Pat Helland及其论文“分布式事务之外的生命”:

在不能依靠传统分布式事务的系统中(banq注:如2PC 基于Weblogic的容器事务/JTA事务等,对业务无侵入性,但是对服务器环境要求高,问题定位从操作系统 防火墙到Weblogic容器内部机制非常宽泛,反而不如在业务范围这个有限边界内定位范围小),不确定性管理就必须在业务逻辑中实施(banq注:对业务有侵入性,需要业务从面向服务接口编程转变为面向事件消息数据编程)。


Bonér声称我们需要从根本上改变我们对失败的看法 - 他们是自然而且会发生的(banq:基于单机单个JVM的编程经验会让我们养成我们对方法调用比较稳定,抛Exception的概率是特例的习惯,但是在分布式网络,抛Exception是常态,不要试图扼杀在摇篮中,这个失败不是婴儿,而是洪水,宜疏不宜堵,应该首先直面承认它的存在,不要认为能够完全杜绝)。具有讽刺意味的是,我们在很多语言中将失败称为“例外”,即使他们没有任何例外,因为他们实际是可预期的。Bonér认为我们应该管理失败而不是阻止他们,我们可以利用事件来帮助我们。

在一个健全的失败模型中,失败需要是:

(1).失败必须被包装,以避免发生爆炸式级联故障,例如通过构建完全自治的服务可以实现封装。
(2).将失败通过事件具体化
(3).将失败通过异步发出
(4).失败可被观察,由一个或多个观察者关注
(5).失败必须是可管理的,这是指在失败发生的环境之外对其管理

这一切对于普通人来说看起来很难。他认为还是有可以帮助我们实现这一目标的途径的,比如基于事件第一的领域驱动设计。他指出,你不应该过早地关注业务的结构(banq注:拿到需求后,不是首先设计类图或数据库结构,这些都是代表业务内部的静态结构)。你应该首先关注行为、动词和事件。要做到这一点的方式就是使用意图和事实。所谓意图是也就是命令(command),命令表示意图做某事,而事件是代表已经发生的、我们不可改变的事实(这是Command和Event区别,命令通常代表一个服务中方法函数的输入参数VO,事件通常是代表服务中的方法函数的输出参数VO)。

在基于事件的不断新增的编程模型下,数据都是通过不断发生的新事件进行新增的,如何修改旧数据则是该模型面临的主要问题,因为这意味着您可以将数据从不可变转为可变的数据,这对事件驱动范式来说是错误的。吉姆格雷和他的1981年论文中关于事务概念阐述如下:

进行覆盖式更新数据是设计的主要罪恶:它违反了数百年来传统会计惯例。
(banq注:Updates-in-place覆盖式更新就是类似SQL语句update)

因此,Bonér认为我们应该学习传统会计的记账基本原理(banq注:区块链也是基于这种记账原则,就是记录流水账明细,而不是只记录账户的当前余额,每进出一笔明细账,对余额进行覆盖式修改,这样做在会计法律中是不允许的,因为抹除了账户变动的原因,假如你想查询一下支付宝余额为什么为什么剩余1元钱了,结果支付宝没有提供你进出明细,这种情况是不可能发生。这种进出账明细的记录实际是记录里每次操作支付宝的事件,消费事件或存入事件),我们需要将会记记账原理应用于我们今天建立的分布式系统。要做到这一点的方法是通过事件日志记录,而这也是许多关系数据库内部工作原理 - 数据库的事务日志就是事件日志记录。

事件溯源(EventSourcing 事件采购)是记录事件的一种模式,有助于我们将上述记账原则应用于我们的系统(banq注:事件溯源其实是区块链的一种模式)。我们按照事件到达的顺序存储所有事件,这使我们可以访问系统中发生的所有事件的完整历史记录。然后根据历史事件创建当前状态视图(有点类似物化视图),CQRS是您可以根据需要订阅事件并创建不同视图的一种方式。事件采购的一个缺点是它对大多数软件工程师来说是一个陌生的模型。事件的版本管理也可能是一个挑战。

Bonér最后强调,事件优先的设计可以帮助您:

1.朝着弹性架构快速前进
2.设计自主服务
3.平衡确定性和不确定性
4.在将应用程序现代化时降低风险

事件日志记录允许您:

1.避免CRUD和避免使用ORM(类似Hibernate这样的框架)
2.控制您的系统历史
3.通过回放事件回溯时间,回到过去任何一个时间点的状态
4.在强一致性和最终一致之间取得平衡


Events Are Reshaping the Future of Distributed Systems: Jonas Bonér at QCon London

[该贴被banq于2018-03-24 15:40修改过]

                   

5