4

私の最初の質問はとても長かったので、私はこれを別の質問として尋ねています。これは、アクターベースのアプリケーションのアーキテクチャに関するもう1つのものです。

アプリケーションを介したメッセージパスを追跡する

Javaコードの一部を見てみましょう。

public void deleteTrades(User user, Date date) {
    PermissionSet ps = permissionService.findPermissions(user)
    if (ps.hasPermission("delete")) {
        Set<Trade> ts = peristence.findTrades(date);
        reportService.sendCancelReports(ts);
        positionService.updateWithDeletedTrades(ts);
    }
}

このコードでは、4つの個別のコンポーネントがあり、プロシージャに必要なコンポーネント間の相互作用はdeleteTrades明確に定義されています。メソッドに完全に含まれていdeleteTradesます。

これをsでモデル化しActor、4つのコンポーネントを4つの別々のアクターに置き換えます。手順に含まれるものを(頭の中で)追跡するにはどうすればよいですか?特に、演算子の使用を避けている場合は、にメッセージを!?送信する可能性があります。これにより、メッセージが送信され、さらにメッセージなどが送信されます。削除を処理するためのコードが散らばっています。私のアプリケーション全体。ConditionalDeletePermissionActorGetTradesAndDeletePersistenceActor

また、ほとんどすべてのアクターが(メッセージを転送するために)他のすべてのアクターのハンドルを必要とすることも意味します。

私の前の質問のように、人々はこれにどのように対処しますか?これらすべてを追跡できる優れたモデリングツールはありますか?人々は!?私があまりにも多くのコンポーネントをActorsに変えているのですか?

4

2 に答える 2

6

間違いなく5つのコンポーネントを使用します。特定のタスクを扱う俳優がいて、オーケストレーターもいます。

もちろん、あなたが持っていなければならない問題は、これをどのように非同期的に連鎖させるかということです。まあ、それは実際にはいくぶん簡単ですが、それはコードを曖昧にする可能性があります。基本的に、各コンポーネントに必要な返信を送信します。

react {
  case DeleteTrades(user,dates) => 
    PermissionService ! FindPermissions(user, DeleteTradesPermissions(dates) _)
  case DeleteTradesPermissions(dates)(ps) =>
    if (ps hasPermission "delete")
      Persistence ! FindTrades(date, DeleteTradesTradeSet _)
  case DeleteTradesTradeSet(ts) =>
    ReportService ! SendCancelReports(ts)
    PositionService ! UpdateWithDeletedTrades(ts)
}

ここでは、カリー化を使用して、最初に返される回答で「日付」を渡します。インタラクションに関連するパラメータがたくさんある場合は、進行中のすべてのトランザクションの情報をローカルのHashSetに保持し、回答を受け取ったときにその情報を見つけるために使用するトークンを渡す方がよい場合があります。

この単一のアクターは、複数の同時アクションを処理できることに注意してください。この特定のケースでは、トランザクションを削除するだけですが、処理するさまざまなアクションをいくつでも追加できます。1つのアクションに必要なデータの準備ができたら、そのアクションは続行されます。

編集

これらのクラスを定義する方法の実際の例を次に示します。

class Date
class User
class PermissionSet

abstract class Message
case class DeleteTradesPermission(date: Date)(ps: PermissionSet) extends Message
case class FindPermissions(u: User, r: (PermissionSet) => Message) extends Message

FindPermissions(new User, DeleteTradesPermission(new Date) _)

カリー化と機能についてのいくつかの説明。クラスDeleteTradesPermissionはカレーされているので、クラスに渡すことができ、Date他の関数に。を付けて完成させることができPermissionSetます。これが応答メッセージのパターンになります。

ここで、クラスFindPermissionsは2番目のパラメーターとして関数を受け取ります。このメッセージを受信したアクターは、戻り値をこの関数に渡し、Message応答として送信されるaを受信します。この例では、メッセージにはDate、呼び出し側のアクターが送信した、とPermissionSet応答側のアクターが提供しているの両方が含まれます。

の場合のように、応答が期待されない場合DeleteTradesSendCancelReportsおよびUpdateWithDeletedTradesこの例の目的のために、返されるメッセージの関数を渡す必要はありません。

回答が必要なメッセージのパラメーターとしてメッセージを返す関数を期待しているため、次のような特性を定義できます。

trait MessageResponse1[-T1] extends Function1[T1, Message]
trait MessageResponse2[-T1, -T2] extends Function2[T1, T2, Message]
...
于 2009-08-21T17:49:54.413 に答える
1

アクターは、考慮せずに従来のサービスコンポーネントを置き換えるために使用されるべきではありません。

今日私たちがトレーニングによって作成するサービスコンポーネントのほとんどは、ステートレスです。ステートレスサービスコンポーネントは、アクターよりも管理が簡単です(メッセージクラスなど)。しかし、アクターと比較した場合、それらに欠けているものの1つは、非同期実行です。ただし、クライアントがほとんどの場合同期的に結果が返されることを期待している場合は、同期ステートレスサービスコンポーネントで問題ありません。

管理する内部状態がある場合、アクターは最適です。内部状態にアクセスしたり、競合状態を心配したりするために、「act()」内で同期を行う必要はありません。に限って "!?" 「act()」内では使用されないため、デッドロックも最小限に抑える必要があります。

アクターは、メッセージの処理中に行われるブロッキング処理に注意する必要があります。アクターはメッセージを順番に処理するため、「act()」内でI / Oの待機がブロックされると、メールボックス内の他のメッセージを処理できなくなります。ここで使用するScalaイディオムは、実際のブロッキング操作を実行する別のアドホックアクターを開始することです。このアンチパターンは、イベントベースのアクターがピギーバックされているスレッドをブロックするため、イベントベースの(反応)アクターにさらに影響を与えます。

私が収集できることから、サービスコンポーネントへの4つの呼び出しはすべてブロックされている可能性があるため、アクターに変換するときは、それらをスケーリングするように注意する必要があります。

于 2009-08-22T03:37:29.513 に答える