23

Play!を使用して、Scalaで記述されたWebアプリケーションに取り組んでいます。フレームワークとAkka。コードは基本的に次のように構成されています。PlayコントローラーはAkkaアクターにメッセージを送信します。次に、アクターは、データベースアクセスを抽象化する永続層と通信します。アプリケーションでのこれらのコンポーネントの使用の典型的な例:

class OrderController(orderActor: ActorRef) extends Controller {
  def showOrders(customerId: Long) = {
    implicit request => Async {
      val futureOrders = orderActor ? FindOrdersByCustomerId(id)

      // Handle the result, showing the orders list to the user or showing an error message.
    }
  }
}

object OrderActor extends Actor {
  def receive = {
    case FindOrdersByCustomerId(id) => 
      sender ! OrderRepository.findByCustomerId(id)
    case InsertOrder(order) =>
      sender ! OrderRepository.insert(order)
      //Trigger some notification, like sending an email. Maybe calling another actor.
  }
}

object OrderRepository {
  def findByCustomerId(id: Long): Try[List[Order]] = ???
  def insert(order: Order): Try[Long] = ???
}

ご覧のとおり、これは基本的なCRUDパターンであり、他の言語やフレームワークで見られるものとよく似ています。クエリは下のレイヤーに渡され、アプリケーションがデータベースから結果を取得すると、その結果はUIに到達するまで戻ってきます。関連する唯一の違いは、アクターと非同期呼び出しの使用です。

今、私は俳優の概念に非常に慣れていないので、まだ完全には理解していません。しかし、私が読んだことから、これは俳優が使用されることになっている方法ではありません。ただし、場合によっては(たとえば、注文が挿入されたときに電子メールを送信する)、真の非同期メッセージパッシングが必要になることに注意してください。

だから、私の質問は:このように俳優を使うのは良い考えですか?FuturesやAkkaの他の同時実行機能を利用して、ScalaでCRUDアプリケーションを作成するための代替手段は何ですか?

4

2 に答える 2

5

アクター ベースの同時実行性はそのままではトランザクション操作に適合しませんが、永続化レイヤーを適切に操作すれば、そのようにアクターを使用することを止めることはありません。挿入( write ) がアトミックであることを保証できる場合は、アクターのプールが安全にそれを行うことができます。通常、データベースにはスレッドセーフな読み取りがあるため、findも期待どおりに機能するはずです。それとは別に、挿入がスレッドセーフでない場合は、書き込み操作専用の単一の WriteActor を 1 つ持つことができ、メッセージの順次処理により原子性が保証されます。

于 2012-12-19T13:41:57.593 に答える
2

注意すべきことの 1 つは、アクターが一度に 1 つのメッセージを処理することです。ルーターを使用して、アクターのプールを使用できます。

あなたの例では、リポジトリのブロッキング API を定義しています。これは、データベース ドライバーによっては、実行できる唯一のことかもしれません。可能であれば、そこでも非同期 API を使用する必要があります。つまり、Future を返します。アクターでは、代わりに Future の結果を送信者にパイプします。

于 2012-12-19T14:24:56.493 に答える