在某项目里,有个 actor 需要做一些持久化的操作,这些操作耗时比较久,理应使用异步的代码来写,但是需求又强调每次只能做一个持久化操作,后来的请求应该等待。一个显然的做法是阻塞式的写,这样就能比较简单的实现顺序花操作。

代码写完以后,我觉得在 actor 中 block 不够完美,就想其他的解决方案。实际上,借助 akka actor 的一些函数,可以实现在不阻塞的情况下实现顺序执行请求的功能的。这种办法的核心是使用 become, unbecome 函数:actor 设置两种状态 free 和 busy,当 free 的时,处理消息,当 busy 时,暂时将消息存储起来,处理消息后,给 actor 返回 done 指令,actor 的状态重新返回到 free,准备处理下一个请求。具体的实现又有很多细节可以考虑,比如当 busy 时到来的请求存储到哪里,是 stash 起来还是在 actor 内部维护一个 queue。请求的处理逻辑是写在 actor 内部,还是借鉴 cameo 模式,再创建一个 actor。

网上已有一种实现,我看了下,觉得应该没有问题。只不过 actor 内部维护了一个 queue,这可能会造成 actor 死亡后重启数据丢失的情况。更好的办法应该是 cameo 模式创建新的 actor 来处理可能出现异常(危险)的工作,其次是把 actor 的 mailbox 当做那个 queue,不要自己维护,按照 doc 缩写,actor 重启后,mailbox 的消息不会丢失。

package actors

import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global import akka.actor.{ Actor, ActorRef } import play.api.libs.concurrent.Akka
import play.api.Logger
import play.api.Play.current trait SequentialActor {
this: Actor => import SequentialActor._ // Actor defines type Receive as PartialFunction[Any, Unit]
type ReceiveAsync = PartialFunction[Any, Future[_]] private val queue = scala.collection.mutable.Queue[Job]()
private def enqueue(job: Job): Unit = queue enqueue job
private def dequeue: Option[Job] = if (queue.isEmpty) None else Some(queue.dequeue) private var _senderAsync: ActorRef = _
def senderAsync = _senderAsync def receive: Receive = {
case msg =>
context become busy
process(Job(msg, sender))
} def busy: Receive = {
case Done =>
dequeue match {
case None => context.unbecome
case Some(job) => process(job)
}
case msg =>
enqueue(Job(msg, sender))
} def process(job: Job) {
_senderAsync = job.sender
(receiveAsync orElse fallback)(job.msg).onComplete { _ => self ! Done }
} def receiveAsync: ReceiveAsync def fallback: ReceiveAsync = {
case msg =>
Logger.error(s"Unhandled message: $msg")
Future.successful{ () }
} }
object SequentialActor {
case object Done
case class Job(msg: Any, sender: ActorRef)
}

  

顺序执行到来的消息 actor的更多相关文章

  1. 关于MQ的几件小事(五)如何保证消息按顺序执行

    1.为什么要保证顺序 消息队列中的若干消息如果是对同一个数据进行操作,这些操作具有前后的关系,必须要按前后的顺序执行,否则就会造成数据异常.举例: 比如通过mysql binlog进行两个数据库的数据 ...

  2. .NET中按预定顺序执行任务

    更新记录 本文迁移自Panda666原博客,原发布时间:2021年7月1日. 一.说明 在.NET中线程可以定义按先后顺序进行执行,适合部分有先后次序的业务逻辑.Task也可以按照预定义的先后顺序执行 ...

  3. js的并行加载以及顺序执行

    重新温习了下这段内容,发现各个浏览器的兼容性真的是搞大了头,处理起来很是麻烦. 现在现总结下并行加载多个js的方法: 1,对于动态createElement('script')的方式,对所有浏览器都是 ...

  4. 【原创】cs+html+js+css模式(七): 顺序执行与并发执行问题,IIS7及其以上版本的抛错问题解决

          在进行开发的过程中,针对于这种模式,我们继承的IRequiresSessionState,这种对于我们的同一个IIS的执行中是顺序执行即一个ajax请求处理完成后,才能执行下一个ajax, ...

  5. testng xml中按顺序执行java类

    如红字部份,将安顺序执行4个类 <?xml version="1.0" encoding="UTF-8"?><suite name=" ...

  6. js的并行加载与顺序执行

    javaScript文件(下面简称脚本文件)需要被HTML文件引用才能在浏览器中运行.在HTML文件中可以通过不同的方式来引用脚本文件,我们需要关注的是,这些方式的具体实现和这些方式可能会带来的性能问 ...

  7. gulp顺序执行任务

    gulp的任务的执行是异步的. 所以,当我写完一系列的任务,准备一股脑地执行. # gulp.task('prod', ['clean', 'compass', 'image', 'style', ' ...

  8. testng.xml顺序执行多个case配置

    testng.xml顺序执行多个case配置 项目结构如图:

  9. 多命令顺序执行、管道符 ; && || |

    多命令顺序执行:

随机推荐

  1. 使用cocos2d-x 3.0 beta开发的小游戏

    主要是参考了http://philon.cn/post/cocos2d-x-3.0-zhi-zuo-heng-ban-ge-dou-you-xi 这篇文章,只是移植到了3.0 beta版. 代码地址: ...

  2. 初学者利用git 上传代码到Coding的简单操作步骤

    1.首先登陆coding网站注册账号https://coding.net/ (注册完后需登陆邮箱激活邮件) 2.登陆刚注册的coding账号 ,添加项目 添加项目—〉输入项目名称—〉输入对项目的简单描 ...

  3. jenkins2 pipeline介绍

    文章来自:http://www.ciandcd.com 文中的代码来自可以从github下载: https://github.com/ciandcd   什么是jenkins2的pipeline?   ...

  4. nodeJs开发app.js解析

    在 node.js 中模块分为核心模块和文件模块两种,核心模块是通过 require('xxxx') 导入的,文件模块是以 require('/xxxx') 或 require('./xxxx').r ...

  5. String.Format in javascript

    有些时候,我们确实需要在JavaScript中进行字符串替换,类似于C#中的String.Format()方法一样,只不过这种格式化替换只局限于对由'{0}','{1}','{2}'...所组成的“占 ...

  6. VS2013编译经常卡在正在从以下位置加载xxx.dll的符号

    换了系统后,重新下载了一个vs2013 with update2安装,编译的时候总是卡在 正在从以下位置加载xxx.dll的符号 如图: 解决方法: 进入VS---工具---选项----调试----符 ...

  7. Leetcode 234 Palindrome Linked List 链表

    判断链表是否是回文. 我直接将链表的一半进行倒置,然后将两半的链表进行比较 /** * Definition for singly-linked list. * struct ListNode { * ...

  8. gcc5.1.0升级指南

    请使用root权限用控制台安装gcc5.1.0(重要) 1.首先把旧的gcc相关的编译工具安装好(没有安装会导致后面的错误) yum upgrade gcc //升级gcc库 yum -y insta ...

  9. php: zend server 安装及相关配置

    运行安装文件(ZendServer-CE-php-5.3.2-5.0.1-Windows_x86.exe)开始安装,选项请参照我的选择. 这里不做改动,维持默认选择即可 点击Browse按钮更改安装目 ...

  10. iOS7隐藏状态栏 statusBar

    转:http://blog.csdn.net/dqjyong/article/details/17896145 评:通过这点变化,可以看出苹果倾向于使用delegate取代全局变量. IOS7中,不仅 ...