第十二章:Akka构建扩展、分布式应用
¶主要内容:
- Akka背后哲学思想
- Actor并发、STM、代理以及数据流
- 构建一个大型的可扩展应用:Akkaoogle
本章介绍一个已有的Scala工具包:Akka,让你为JVM平台构建新一代的、事件驱动的、容错的、可伸缩的分布式应用。Akka提供了多并发的抽象,本章着重探索其内容。前面内容,仅介绍了Actor面向消息的(message-oriented)并发使用。这里将继续探索诸如 STM、Agent和Dataflow的并发抽象内容。
本章介绍一个已有的Scala工具包:Akka,让你为JVM平台构建新一代的、事件驱动的、容错的、可伸缩的分布式应用。Akka提供了多并发的抽象,本章着重探索其内容。前面内容,仅介绍了Actor面向消息的(message-oriented)并发使用。这里将继续探索诸如 STM、Agent和Dataflow的并发抽象内容。
最激动人心的事情是,Scala可以运行在JVM上。这带来的好处是你可以使用构建在JVM语言上的所有框架和工具。基于JVM,更有一些公司甚至不使用Java作为他们的首选编程语言。对于大多数企业软件项目,我坚信不支持JVM的语言,几乎不可能实现。
Scala的一个主要设计目的,是令其运行在JVM上,并提供对Java的相互协作。Scala被编译为Java字节码,所以你可以使用如javap(Java class file disassembler)工具,对有Scala编译器生成的字节码进行反编译。大部分情况下,Scala的特性被转换为Java的特性,因此Scala可以轻松和Java集成。例如,Scala使用类型擦除来兼容Java。类型擦除1 (Type erasure)也允许Scala对JVM的动态类型进行集成。一些Scala特性(如traits),不会直接地映射为Java,在这种情况下,你需要灵活变通地使用。
虽然对Java的大部分集成都可轻松实现,我仍然更推荐你使用 pure Scala。我尝试查找两者之间某些等价的部分,以及Scala不能实现的,则使用Java来解决。使用Java库的不好的方面是,你必须处理可变性、异常、空值这些Scala中绝对不会出现的问题。在Scala中,需要特别小心地选择Java的库或者框架。以一个编码良好的Java库Joda-Time为例。
Scala和Java最通常的集成,是指部分项目由Scala编写的。小节11.4将介绍Scala中使用Java框架,Hibernate、Spring等的web项目构建。
截至目前为止,所展示的代码都没有单元测试——为什么我们现在要关心这个问题?围绕代码写测试,而又不提及它做了什么,是希望你更专注于Scala语言本身。现在,本章的目标是希望编写自动化的Scala单元测试,用于更好地构建高质量的软件。
编写精良1的代码,从你编程单元测试开始。通常感性认识是很难编写单元测试,但这章要改变这种心态。我将为你展示,如测试驱动开发和持续集成的练习开始,如何在你的Scala项目中编写测试。测试驱动开发(test-driven development,TDD)就是指在你编写代码之前编写测试。我知道这有点落后,但我保证,这章结束后它将更有意义。你将学习的测试,更多的是设计一个测试,正如设计你的软件一样。你的设计工具将会是代码——更特别地,测试的代码。
我将由介绍自动化测试和开发者如何在真实环境中使用来开始。有两种自动化测试:一种是你自己写的,一种是从你的代码中生成的。首先要介绍的是代码生成的测试,使用ScalaCheck工具,因为它比较容易。Sala是一个强静态类型语言,利用这点,诸如ScalaCheck这样的工具可以为你构建在类型上的函数或类生成单元测试。ScalaCheck是自动化测试的一种很好实现。但要完全信服自动化测试带来的好处,你需要手动编写它们。
在本章将介绍Scala中最为激动人心的特性:actor库。可以把一个actor认为是一个对象,该对象处理一个消息(请求)并封装状态(actor间的状态是不共享的)。接收一个消息,并在相应中执行一个动作的能力,这样的对象称为一个actor。更高层面上讲,actors是你做面向对象编程(OOP)时应该实现的方式。要记得actor模型鼓励不共享状态的体系架构。在本章,我将解析为什么在任何并发编程里面,这是一个重要的性质。
Future 和 Promise以非阻塞(nonblocking)的方式提供了执行并发操作的抽象。这是一个很好的方式来创建多并发和平行计算,以此计算你的工作(job)。这和你如何组合函数很相似,但,在这里,函数被并发(concurrently)地或平行(parallel)地执行。Future可以认为是一个代理对象,你可以为一个以后会用到结果进行创建。你可以用Promise有提供的结果来完成一个Future。我们将在本章循序渐进得探索Promise 和 Future。首先,让我们先理解下我所理解的并发、并行编程。
我们有一段时间没有把专注力放在Scala的类型系统(type system)上。The type system is a tractable syntactic method for proving the absence of certain program behaviors by classifying phrases according to the kinds of values they compute1.(类型系统是一个易于处理的语法方法,它通过计算得出的分类词汇,为该方法提供正确的缺省的编程处理)。
本章学习类型系统的要点是 理解其背后理论。这对学习类型系统基础很有帮助,本章不会过多在练习上关于理论内容。这里,将探索Scala提供给我们的各种各样的类型,并带有例子让我们更好理解。为什么类型系统如此重要?它提供了一下几点特性:
本章的主要目的是告诉你,Scala类型系统是如何构建重用组件的。这里的 组件(component) 是一个 涵盖性术语(umbrella term),如重用的库、类、模组、框架、web service。
构建重用的组件并不简单。通过可装配组件(assembling components)来构建软件的目标仍然是梦一般的存在,甚至不能扩展成为我们想要的。构建可重用组件的挑战是,还要它所引用的上下文环境。典型地,修改组件以适应当前的需求,最终带来的是一个组件的多个版本。这导致了维护上的问题。在本章的第一小节,你会学习使用Scala类型系统来构建简单的、可重用的组件。