我如何在Akka工作?

lau*_*cer 28 scala scalability websocket actor akka

当您需要执行I/O(即数据库操作)时,actor模型(在Akka中)如何工作?

我的理解是,阻塞操作会引发异常(并且由于Akka使用的Netty的自然性质而基本上破坏了所有并发性).因此我将不得不使用Future或类似的东西 - 但我不理解并发模型.

  1. 1个演员可以同时处理多个消息吗?
  2. 如果一个actor在一个future(即.future.get())中进行了一个阻塞调用,它只会阻止当前actor的执行; 还是会阻止所有参与者的执行,直到阻止呼叫完成?
  3. 如果它阻止所有执行,那么使用未来辅助并发(即,将来不会调用阻塞调用仍然等于创建一个actor并执行阻塞调用)?
  4. 处理多阶段进程的最佳方法是什么(即从数据库中读取;调用阻塞的Web服务;从数据库中读取;写入数据库)每个步骤依赖于最后一步?

基本情况是这样的:

  • 我正在使用Websocket服务器,它将维护数千个会话.
  • 每个会话都有一些状态(即身份验证详细信息等);
  • Javascript客户端将向服务器发送JSON-RPC消息,该消息将把它传递给相应的会话actor,后者将执行它并返回结果.
  • 执行RPC调用将涉及一些I/O和阻塞调用.
  • 将会有大量并发请求(每个用户将通过WebSocket连接发出大量请求,并且会有很多用户).

有没有更好的方法来实现这一目标?

Ray*_*urg 28

阻塞操作不会在Akka中抛出异常.你可以阻止来自Actor的调用(你可能想要最小化,但这是另一个故事).

  1. 不,1个演员实例不能.
  2. 它不会阻止任何其他演员.您可以使用特定的Dispatcher来影响这一点.Futures使用默认调度程序(通常驱动的全局事件),因此它在池中的线​​程上运行.您可以选择要为演员使用的调度员(每个演员或所有人).我想如果你真的想要创建一个问题,你可能能够将完全相同的(基于线程的)调度程序传递给期货和演员,但这需要你的一些意图.我想如果你有大量的期货无限期阻塞并且执行器服务已被配置为固定数量的线程,你可能会炸毁执行器服务.所以很多'如果'.只有当Future还没有完成时,f.get才会阻止.它将阻止您调用它的Actor的"当前线程"(如果您从Actor调用它,顺便说一下这不是必需的)
  3. 你不一定要阻止.你可以使用回调而不是f.get.你甚至可以不受阻碍地创作期货.有关详细信息,请查看Viktor关于"akka的充满希望的未来"的演讲:http://skillsmatter.com/podcast/scala/talk-by-viktor-klang
  4. 我会在步骤之间使用异步通信(如果这些步骤本身就是有意义的进程),那么每个步骤都使用一个actor,其中每个actor都向下一个发送单向消息,也可能单向消息发送给其他不会可以监督过程的块.通过这种方式,您可以创建可以制作多个actor的链,在它之前可以放置一个负载平衡actor,这样如果一个actor在一个链中阻塞,则另一个链中的另一个相同类型可能不会.这也适用于你的"上下文"问题,将工作量传递给本地参与者,将它们链接到负载平衡角色后面.

至于netty(我假设你的意思是远程演员,因为这是在Akka中唯一使用netty的东西),如果你担心的话,尽快将你的工作传递给当地演员或未来(带回调)关于时间安排或阻止netty以某种方式完成它的工作.


par*_*tic 10

阻塞操作通常不会抛出异常,但等待未来(例如通过使用!!!!!发送方法)可能会抛出超时异常.这就是为什么你应该尽可能地坚持使用即发消失,使用有意义的超时值并尽可能选择回调.

  1. akka actor不能连续显式处理多个消息,但您可以throughput通过配置文件来播放该值.然后,如果它的消息队列不是空的,那么actor将处理几个消息(即它的receive方法将被顺序调用几次):http://akka.io/docs/akka/1.1.3/scala/dispatchers.html#id5

  2. 在actor中阻塞操作不会"阻止"所有actor,但如果你在actor之间共享线程(推荐用法),调度程序的一个线程将被阻塞,直到操作恢复.因此,尽量尽量编写期货,并注意超时价值.

3和4.我同意Raymond的回答.