akka设计模式系列-消息模型
通过前面的文章我们总结了几个常见的actor设计模式,但此处不得不提前介绍一下在Akka中消息的设计模式。随着对Akka的使用,我们会发现,使用Akka设计系统其实就是面向消息编程。actor之间消息设计的是否合理,往往意味着Akka应用设计的是否合理。那么actor之间的消息该如何设计呢?
命令和事件
actor之间都是通过“消息”进行通信的,对各种各样的“消息”进行分析,我们可以把它简单的分为命令和事件两类。命令,是指一个actor给另外一个actor发送指令做相关的业务逻辑;事件,则是actor对某个命令的响应结果,或者对其他事件的响应结果。简单来说,命令是主动让actor做出某种响应,例如发送Stop命令让其他actor销毁自己;事件,往往意味着某种通知,例如actor销毁之前发送Stopped事件给它的supervisor。
我们在用Akka开发应用时候,一定要仔细认真的把系统间的消息按照定义划分为命令和事件。具体如何划分可以参考这两种消息的具体定义或DDD(领域驱动设计)相关概念。此处我们只介绍在代码结构上如何设计它们。
trait Message{
// 消息创建的时间
final val at:Long = System.currentTimeMillis()
}
trait Command extends Message
trait Event extends Message trait MasterCommand extends Command{
// 定义MasterCommand公有的方法或字段
} object MasterCommand{
case class StartWork(message:String) extends MasterCommand
}
trait MasterEvent extends Event{
// 定义MasterEvent公有的方法或字段
} object MasterEvent{
case class WorkStarted(message:String) extends MasterCommand
}
上面是我在开发时常用的设计消息的框架。其中Message这个trait表示对消息的抽象,其中只有一个at字段,是消息创建的时间。Command继承Message,表示对命令的抽象。Event也继承Message,表示对事件的抽象。MasterCommand这个trait继承Command标志master发出的命令。所有master发出的具体命令放在与MasterCommand这个trait同名的object中。当然也可以不同名,只要在一个object中即可。把master具体命令放到一个object中,只是为了对其进行名称的限定。如果其他类型的actor也有一个StartWork命令,在同一个actor中要对这两个StartWork同时做响应的话,会引起歧义。所以我一般都用object来进行隔离,当然是用package或者把StartWork改名也都可以对其进行隔离,这个就是个人爱好了。MasterEvent这个特质表示master收到某个命令或事件进行响应的事件,同样也是master发出的。
上一段话中,我用红色字体标志出了“发出”二字。这意味着,不管是命令还是事件,都是针对发送actor而言的。具体什么意思呢?这其实是一个代码设计的问题,但我觉得比较重要,这里需要单独解释一下。我们知道actor之间是通过消息传递来通信的,那么消息传递一个有一个发送方和接收方。在设计代码时,我们是把消息放到发送方的域中,还是放到接收方的域中呢。比如StartWork这个命令,如果放到masterActor中,就意味着master发出了一个StartWork这个命令,具体是谁收到该消息就不关心了,接收方一定知道该消息是masterActor发出的。如果放到workActor中,就意味着workActor一定会接收该命令,对其作出反应,具体是谁发送的就不关心了。对于事件可以做类比理解。
具体是按照发送方还是按照接收方封装消息,这个就仁者见仁智者见智了,只不过我比较推崇上面代码中的设计方案。因为我们可以围绕actor设计上下文边界,不会对其他领域内的对象进行引用,高内聚低耦合。
其实我们还可以通过消息名称来区分,比如有两个actor都会发出StartWork的消息,那么可以分别用StartType1Work和StartType2Work来命令。但这种方式有个问题就是没法按照类型对不同的命令进行筛选,比如我们可以使用match来对不同类型的消息进行过滤,如果消息是用消息名称进行区分的,在偏函数或者match时是很不方便的,关于这一点希望大家自己好好体会。
其实对于上图中的代码,我一般都会优化成下面的形式。就是把master相关的命令和事件上面再加一个抽象层:master消息。其实都差不多,只不过层次更深而已。优点是可以单独修改公共字段或方法,缺点是设计复杂。
trait Message{
// 消息创建的时间
final val at:Long = System.currentTimeMillis()
}
trait Command extends Message
trait Event extends Message trait MasterMessage extends Message{
// 定义Master消息共有的方法或字段
} trait MasterCommand extends MasterMessage with Command{
// 定义MasterCommand公有的方法或字段
}
trait MasterEvent extends MasterMessage with Event{
// 定义MasterEvent公有的方法或字段
} object MasterCommand{
case class StartWork(message:String) extends MasterCommand
} object MasterEvent{
case class WorkStarted(message:String) extends MasterCommand
}
关于Akka消息的设计模式就介绍到这里了,在Akka中消息设计的好坏往往决定着应用的质量,希望大家多多实践,多多体会。当然了每个人的设计理念不同,这里也只是抛砖引玉,如果你有更好的设计模式,欢迎留言讨论。
akka设计模式系列-消息模型的更多相关文章
- akka设计模式系列-消息模型(续)
在之前的akka设计模式系列-消息模型中,我们介绍了akka的消息设计方案,但随着实践的深入,发现了一些问题,这里重新梳理一下设计方法,避免之前的错误.不当的观点给大家带来误解. 命令和事件 我们仍然 ...
- akka设计模式系列-慎用ask
慎用ask应该是Akka设计的一个准则,很多时候我们应该禁用ask.之所以单独把ask拎出来作为一篇博文,主要是akka的初学者往往对ask的使用比较疑惑. "Using ask will ...
- akka设计模式系列
由于本人爱好Scala,顺便也就爱好Akka,但目前网上对Akka的介绍大多都是概念上或技术方向上的介绍,基本没有Akka设计模式或者Actor模型设计模式的资料.这对于Akka的普及非常不利,因为即 ...
- akka设计模式系列(Actor模型)
谈到Akka就必须介绍Actor并发模型,而谈到Actor就必须看一篇叫做<A Universal Modular Actor Formalism for Artificial Intellig ...
- akka设计模式系列-While模式
While模式严格来说是while循环在Akka中的合理实现.while是开发过程中经常用到的语句之一,也是绝大部分编程语言都支持的语法.但while语句是一个循环,如果循环条件没有达到会一直执行wh ...
- akka设计模式系列-Backend模式
上一节我们介绍了Akka使用的基本模式,简单点来说就是,发消息给actor,处理结束后返回消息.但这种模式有个缺陷,就是一旦某个消息处理的比较慢,就会阻塞后面所有消息的处理.那么有没有方法规避这种阻塞 ...
- akka设计模式系列-actor锚定
actor锚定模式是指使用actorSelection对acor进行锚定的设计模式,也可以说是一个对actor的引用技巧.在某些情况下,我们可能需要能够根据Actor的path锚定对应的实例.简单来说 ...
- akka设计模式系列-Chain模式
链式调用在很多框架和系统中经常存在,算不得上是我自己总结的设计模式,此处只是简单介绍在Akka中的两种实现方式.我在这边博客中简化了链式调用的场景,简化后也更符合Akka的设计哲学. trait Ch ...
- akka设计模式系列-akka在秒杀场景的应用
本博客讨论一下akka在秒杀场景下的应用,提出自己的见解,只做抛砖引玉,大神勿喷.秒杀活动涉及到前中后台各个阶段,为了说明问题,我们简化场景,只研究akka在后台如何处理秒杀业务. 秒杀活动 所谓的秒 ...
随机推荐
- World Cup(The 2016 ACM-ICPC Asia China-Final Contest dfs搜索)
题目: Here is World Cup again, the top 32 teams come together to fight for the World Champion. The tea ...
- MySQL-date和datetime
MySQL中 date表示只有日期: insert into stu values(id = null, birthday = '2000-01-11'); datetime则还包含了时间: inse ...
- MyBatis 中 resultMap 详解
resultMap 是 Mybatis 最强大的元素之一,它可以将查询到的复杂数据(比如查询到几个表中数据)映射到一个结果集当中.如在实际应用中,有一个表为(用户角色表),通过查询用户表信息展示页面, ...
- instance_name,db_name,oracle_sid之间的关系
一]对ORACLE_SID的理解 --------------------------------------------------------------------------------Ora ...
- x component of 2nd stokes wave--- C code
* Source code The following is a C code for x component of 2nd stokes wave ××××××××××××××××××××× /*s ...
- c#string类型反序列化成字典类型
c# 实现string类型转化为字典类型:黄色底纹为需要引用的dll,可以在网站下载! 下载地址:http://download.csdn.net/download/xinping_168/47107 ...
- linux下git+github个人使用记录
Linux: 安装git的命令: sudo apt install git 查看版本确认安装成功: git --version 生成密钥: ssh-keygen -t rsa -C "you ...
- zoj 1008 暴力枚举求解dfs+优化
/* 现将相同的合并计数. 再枚举判断是否符合当cou==n*n是符合就退出 */ #include<stdio.h> #include<string.h> #define N ...
- J - Invitation Cards 最短路
In the age of television, not many people attend theater performances. Antique Comedians of Malidine ...
- [codevs 1961]躲避大龙(dfs)
题目:http://dev.codevs.cn/problem/1961/ 分析: 被“SPFA”的标签骗了…… 看了hzwer的博客才知道可以用f[i][0..60]表示每个点每个秒是否可以到.至于 ...