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在后台如何处理秒杀业务. 秒杀活动 所谓的秒 ...
随机推荐
- js之字典操作
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- C,LINUX,数据结构部分
1604期 第1期测试(面试精选:C,LINUX,数据结构部分) 本试卷从考试酷examcoo网站导出,文件格式为mht,请用WORD/WPS打开,并另存为doc/docx格式后再使用 试卷编号:24 ...
- 洛谷 1821 [USACO07FEB]银牛派对Silver Cow Party
[题解] 其实解法 #include<cstdio> #include<cstring> #include<algorithm> #define LL long l ...
- PAT 1129 Recommendation System
Recommendation system predicts the preference that a user would give to an item. Now you are asked t ...
- javaHttp请求,接收到的是中文乱码如何处理
可在service()方法中加日志,看哪种不是乱码 例如,中文乱码的话,中文编码一般有 UTF-8,GBK,ISO-8859-1 加日志为 List<String> list = new ...
- 网页中添加QQ在线客服
方法一:调用本地已安装的QQ进行会话 <a href='tencent://message/?uin=QQ号码&Site=网站地址&Menu=yes'></a> ...
- Linux学习总结(18)——Linux使用init命令关机、重启、切换模式
reboot可能是每个用过Linux的人都知道的命令,但有一个命令"init"才是命令中的精英. 最近有个同事学习安装了CentOS,明明安装的是带桌面的系统,但是启动后进入了命令 ...
- Mysql修改自增主键的起始值及查询自增主键的下一个值
MySQL [xxx_mall]> alter table shop_base_info AUTO_INCREMENT=11000;Query OK, 0 rows affected (0.0 ...
- - > 网络流(【最大流】草地排水模板题)
1993 草地排水 USACO 时间限制: 2 s 空间限制: 256000 KB 题目等级 : 钻石 Diamond 题解 题目描述 Description 在农夫约翰的农场上,每 ...
- CentOS 7: Install vsftpd
Install vsftpd All commands should be run with ‘root’ user. Run the following command in terminal to ...