如何在Akka Actor

时间:2016-01-04 07:19:33

标签: mysql scala jdbc playframework akka

嘿,我读了这个jdbc文档 https://www.playframework.com/documentation/2.1.0/ScalaDatabase 这个问题 Is it good to put jdbc operations in actors?

现在我的mysql事务有一个ActorClass,每当请求到来时,这个actor都会多次实例化。所以每个请求都会实例化新的actor。连接池安全吗?

我可以使用

吗?
val connection = DB.getConnection()

是连接对象可以处理异步事务吗? 所以我可以只用一个单例来处理mysql连接并在所有实例化的actor中使用它。另外,如果我想使用anorm,我该如何创建一个隐式连接对象?

由于

4 个答案:

答案 0 :(得分:3)

如果您不想屏蔽演员,则DB.getConnection()应为promise[Connection]future[Connection]。 (答案结尾处的警告)

如果DB.getConnection()是同步的(仅返回没有换行类型的连接),则actor将挂起,直到它在处理实际消息时实际从池中获取连接。无论您的数据库是单身还是无关,最终它都会触及连接池。

话虽这么说,你可以创建actor来处理消息传递和其他actor来处理数据库中的持久性,将它们放在不同的线程调度程序中,从而为数据库密集提供更多的线程。这也在PlayFramework中提出。

注意事项:

如果你在演员内部运行期货,你不确定它将运行的线程/时间,我假设你做了一些事情(阅读评论)

def receive = {
  case aMessage => 
    val aFuture = future(db.getConnection)
    aFuture.map { theConn => //from previous line when you acquire the conn and when you execute the next line
                             //it could pass a long time they run in different threads/time 
                             //that's why you should better create an actor that handles this sync and let
                             //akka do the async part
      theConn.prepareStatemnt(someSQL)
      //omitted code...
    }
}

所以我的建议是

//actor A receives, 
//actor B proccess db (and have multiple instances of this one due to slowness from db)

class ActorA(routerOfB : ActorRef) extends Actor {
  def recieve = {
    case aMessage =>
      routerOfB ! aMessage
  }
}

class ActorB(db : DB) extends Actor {
  def receive = {
    case receive = {
      val conn = db.getConnection //this blocks but we have multiple instances 
                                  //and enforces to run in same thread
      val ps = conn.prepareStatement(someSQL)
    }
  }
}

您需要路由:http://doc.akka.io/docs/akka/2.4.1/scala/routing.html

答案 1 :(得分:1)

  • 据我所知,你无法在单个连接上为RDBMS运行多个并发查询(即使在C-API中,我还没有看到任何用于mysql的异步/非阻塞调用的资源/引用;)。要同时运行查询,您大多数都有多个连接实例。

  • 当您有多个连接实例时,
  • DB.getConnection并不昂贵。使用DB的最昂贵的区域是运行SQL查询并等待其响应。

  • 要与您的数据库调用异步,您应该在其他线程中运行它们(不在Akka或Play的主线程池中);光滑为你做。它管理一个线程池并对它们运行数据库调用,然后你的主线程将可以自由处理收入请求。然后你不需要将演员中的DB调用包装成异步。

答案 2 :(得分:0)

我认为您应该从池中获取连接并在完成后返回。如果我们通过每个actor的单个连接,如果该连接断开连接,您可能需要重新初始化它。

对于您可能想要尝试的交易

DB.withTransaction { conn =>  // do whatever you need with the connection}

答案 3 :(得分:0)

对于更实用的数据库访问方式,我建议调查slick,它有一个很好的API,可以与普通演员集成,并进一步使用streams