设为首页收藏本站

LUPA开源社区

 找回密码
 注册
文章 帖子 博客
LUPA开源社区 首页 业界资讯 技术文摘 查看内容

快速了解Scala技术栈

2014-9-10 10:46| 发布者: joejoe0332| 查看: 5082| 评论: 0|原作者: 张逸|来自: InfoQ

摘要: 我无可救药地成为了Scala的超级粉丝。在我使用Scala开发项目以及编写框架后,它就仿佛凝聚成为一个巨大的黑洞,吸引力使我不得不飞向它,以至于开始背离Java。固然Java 8为Java阵营增添了一丝亮色,却是望眼欲穿,千 ...



分布式系统

  我放弃介绍诸如模块化管理以及依赖注入,是因为它们在Scala社区的价值不如Java社区大。例如,我们可以灵活地运用trait结合cake pattern就可以实现依赖注入的特性。因此,我直接跳过这些内容,来介绍影响更大的支持分布式系统的框架。

  Finagle的血统高贵,来自过去的寒门,现在的高门大族Twitter。Twitter是较早使用Scala作为服务端开发的互联网公司,因而积累了非常多的Scala经验,并基于这些经验推出了一些颇有影响力的框架。由于Twitter对可伸缩性、性能、并发的高要求,这些框架也极为关注这些质量属性。Finagle就是其中之一。它是一个扩展的RPC系统,以支持高并发服务器的搭建。我并没有真正在项目中使用过Finagle,大家可以到它的官方网站获得更多消息。

  对于分布式的支持,绝对绕不开的框架还是AKKA。它产生的影响力如此之大,甚至使得Scala语言从2.10开始,就放弃了自己的Actor模型,转而将AKKA Actor收编为2.10版本的语言特性。许多框架在分布式处理方面也选择了使用AKKA,例如Spark、Spray。AKKA的Actor模型参考了Erlang语言,为每个Actor提供了一个专有的Mailbox,并将消息处理的实现细节做了良好的封装,使得并发编程变得更加容易。AKKA很好地统一了本地Actor与远程Actor,提供了几乎一致的API接口。AKKA也能够很好地支持消息的容错,除了提供一套完整的Monitoring机制外,还提供了对Dead Letter的处理。

  AKKA天生支持EDA(Event-Driven Architecture)。当我们针对领域建模时,可以考虑针对事件进行建模。在AKKA中,这些事件模型可以被定义为Scala的case class,并作为消息传递给Actor。借用Vaughn Vernon在《实现领域驱动设计》中的例子,针对如下的事件流:



  我们可以利用Akka简单地实现:

case class AllPhoneNumberListed(phoneNumbers: List[Int])case class PhoneNumberMatched(phoneNumbers: List[Int])case class AllPhoneNumberRead(fileName: String)class PhoneNumbersPublisher(actor: ActorRef) extends ActorRef {	def receive = {		case ReadPhoneNumbers =>		//list phone numbers		actor ! AllPhoneNumberListed(List(1110, ))	}}class PhoneNumberFinder(actor: ActorRef) extends ActorRef {	def receive = {		case AllPhoneNumberListed(numbers) => 			//match			actor ! PhoneNumberMatched()	}}val finder = system.actorOf(Prop(new PhoneNumberFinder(...)))val publisher = system.actorOf(Prop(new PhoneNumbersPublisher(finder)))publisher ! ReadPhoneNumbers("callinfo.txt")


  若需要处理的电话号码数据量大,我们可以很容易地将诸如PhoneNumbersPublisher、PhoneNumberFinder等Actors部署为Remote Actor。此时,仅仅需要更改客户端获得Actor的方式即可。


  Twitter实现的Finagle是针对RPC通信,Akka则提供了内部的消息队列(MailBox),而由LinkedIn主持开发的Kafka则提供了支持高吞吐量的分布式消息队列中间件。这个顶着文学家帽子的消息队列,能够支持高效的Publisher-Subscriber模式进行消息处理,并以快速、稳定、可伸缩的特性很快引起了开发者的关注,并在一些框架中被列入候选的消息队列而提供支持,例如,Spark Streaming就支持Kafka作为流数据的Input Source。


HTTP

  严格意义上讲,Spray并非单纯的HTTP框架,它还支持REST、JSON、Caching、Routing、IO等功能。Spray的模块及其之间的关系如下图所示:


  我在项目中主要将Spray作为REST框架来使用,并结合AKKA来处理领域逻辑。Spray处理HTTP请求的架构如下图所示:



  Spray提供了一套DSL风格的path语法,能够非常容易地编写支持各种HTTP动词的请求,例如:

trait HttpServiceBase extends Directives with Json4sSupport {     implicit val system: ActorSystem     implicit def json4sFormats: Formats = DefaultFormats     def route: Route}trait CustomerService extends HttpServiceBase {     val route =           path("customer" / "groups") {               get {                    parameters('groupids.?) {                         (groupids) =>                              complete {                                   groupids match {                                        case Some(groupIds) =>                     ViewUserGroup.queryUserGroup(groupIds.split(",").toList)                                        case None => ViewUserGroup.queryUserGroup()                                   }                              }                    }               }          } ~          path("customers" / "vip" / "failureinfo") {               post {                    entity(as[FailureVipCustomerRequest]) {                         request =>                               complete {                                   VipCustomer.failureInfo(request)                               }                    }               }          }}


  我个人认为,在进行Web开发时,完全可以放弃Web框架,直接选择AngularJS结合Spray和AKKA,同样能够很好地满足Web开发需要。


  Spray支持REST,且Spray自身提供了服务容器spray-can,因而允许Standalone的部署(当然也支持部署到Jetty和tomcat等应用服务器)。Spray对HTTP请求的内部处理机制实则是基于Akka-IO,通过IO这个Actor发出对HTTP的bind消息。例如:

 IO(Http) ! Http.Bind(service, interface = "0.0.0.0", port = 8889)


  我们可以编写不同的Boot对象去绑定不同的主机Host以及端口。这些特性都使得Spray能够很好地支持当下较为流行的Micro Service架构风格。



酷毙

雷人

鲜花

鸡蛋

漂亮
  • 快毕业了,没工作经验,
    找份工作好难啊?
    赶紧去人才芯片公司磨练吧!!

最新评论

关于LUPA|人才芯片工程|人才招聘|LUPA认证|LUPA教育|LUPA开源社区 ( 浙B2-20090187 浙公网安备 33010602006705号   

返回顶部