akka:分享可变状态

时间:2011-09-05 11:14:13

标签: scala functional-programming akka

我需要有一个全局变量(单例),它很少会发生变化。实际上它只会在actor重新启动时更改,并重新初始化变量。由于我无法在伴随对象中使用singleton val,我必须将其声明为var(mutable)。

object UserDatabase {
    var dbConnection = "" // initializing db connection
}

我读过的许多指南都反对共享一个可变状态。所以我将变量移动到类并使用消息传递来检索变量。

class UserDatabase extends Actor{
    val dbConnection = "" // initializing db connection locally
    def receive = {case GetConnection => self.reply(dbConnection)}
}

问题是,许多演员经常访问dbConnection,并且不断发送消息会降低性能(因为akka进程邮箱一个接一个)。

我不知道如何在不牺牲性能的情况下做到这一点。任何的想法?

4 个答案:

答案 0 :(得分:3)

答案 1 :(得分:2)

首先,您是否真的测量/注意到性能下降?由于消息传递是轻量级的,也许它对您的应用程序来说足够快。

然后,一个可能的解决方案:如果很少编写“全局”状态,但经常访问,则可以选择推送策略。每次更改时,UserDatabase actor都会将更新后的值发送给感兴趣的actor。然后,您可以使用发布/订阅方法,依赖actor注册,使用actor池等等。

class UserDatabase extends Actor{
    var dbConnection = "" // initializing db connection locally
    def receive = {
      case SetConnection( newConnection ) if dbConnection != newConnection => {
        dbConnection = newConnection
        sendUpdatedConnection(); // sends the change to every relevant actor
      }
    }
}

答案 2 :(得分:1)

如果在任何情况下都不需要经常使用变量,那么将它变为java.lang.concurrent.atomic.AtomicReference或在synchronized块中包装它的每次访问可能更简单,更有效(在变量上)。演员不会始终使事情变得更容易和更安全,通常。

答案 3 :(得分:0)

  1. 创建许多演员作为RoundRobinRouter的路线。
  2. 让每个actor处理一个连接并实际处理数据库逻辑。