5

すべてのクライアントが接続する 2 つの WCF サービスを設計しています。これらのサービスの 1 つが通知サービスです。

各クライアントがサービスに接続し、サブスクライブしてから、デュプレックス コールバック インターフェイスを使用して通知を受信するようにします (サービスはクライアントで「通知」操作を起動します)。

これは私のデザインのアイデアです:

ここに画像の説明を入力

私の質問は次のとおりです。各クライアントがサービスに接続するときに、データベースの「ユーザー」テーブルに対して検証します (UserNamePasswordValidator を使用し、「検証」関数を実装します)。

要件: 各ユーザーは、データベースで定義されたルールに基づいて異なる通知を受け取る必要がありますが、すべて同じコントラクトを使用します

例えば:

DB 内のJohn Smithのルールは次のようになります。価格が 100 ドルを超えるすべての新製品について通知する。

Jane Doeの DB でのルールは次のようになります。すべての新製品について、名前が「JA」で始まることを通知してください。

DB 内のJim Jabraのルールは次のようになります。「食品」タイプのすべての新製品について通知する。

私のサービスには、データベースの変更 (新しい製品がデータベースに挿入された) を検出するワーカー スレッドがあります。

次に、接続されているすべてのクライアントをループする必要があります。クライアントの通知要求に一致する場合にのみ、クライアントごとに新製品の通知を送信します。

繰り返しますが、すべてのクライアントは同じ種類の更新 (新製品) を受け取りますが、データベース内のルールに従って、各クライアントは異なる製品を受け取る必要があります。

これを実装するために私が考えた1つのアプローチは、次のリストを保持するSingletonサービスを使用することです。

  • クライアント エンドポイント
  • ユーザー オブジェクト (データベースから)

このように - ワーカー スレッドが新しい製品を検出するたびに、このリストをループして、必要な人に通知を送信します。このアプローチの問題点は、クライアントの 1 つのグローバル リストを作成するには、サービスを Singlton として使用する必要があることです。

2 番目のアプローチは...そうですね...ワーカー スレッドからサービスに接続されているクライアントのリストにアクセスする方法について、別の考えがありません...

私が抱えている主な問題は、各クライアントがさまざまな種類の製品を通知することを望んでいる可能性があることだと思います. つまり、私のシナリオではサービスがクライアントについて知る必要があるため、pub\sub メソッドはここではあまり適していません。

この頭痛を解決する方法について何か提案はありますか?

4

2 に答える 2

2

二重通信では、通知を送信できるように、サーバーからクライアントに開かれた TCP チャネルを維持する必要があります。

クライアントはサーバーへの接続を開始する人であり、この接続を開いたままにしておく必要があります。この接続が失われた場合、サーバーからクライアントへの接続を開始することはできません (すべきではありません)。クライアントは NAT の背後にあり、ファイアウォールを持っている可能性があるためです。等

したがって、クライアント接続リストを保持するサーバー側に何らかの静的 (シングルトン) オブジェクトが必要です。これは必ずしも WCF サービスではないと考えられます。このオブジェクトをサービス コンストラクターに依存性注入できます。

public class ProductRepository
{
    private EventAggregator eventAggregator;

    public void Add(Product product)
    {
        //...
        eventAggregator.Publish(new NewProductEvent(product))
    }
}
[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerSession)]
public class EventPublishingService
{
    private IClientCallback client;
    private EventAggregator eventAggregator;
    private Func<Product, bool> predicate;

    public EventPublishingService(...)
    {
        eventAggregator.Subscibe<NewProductEvent>(OnNewProduct);
    }
    private void OnNewProduct(NewProductEvent e)
    {
        if (predicate(e.Product)==true) client.Notify(e.Product);
    }

    public void Subscribe()
    {
        client = OperationContext.Current.GetCallbackChannel<IClientCallback>()
        var user = ServiceSecurityContext.PrimaryIdentity;
        predicate = GetFilterForUser(user);
    }
}
于 2012-04-24T13:40:36.953 に答える
0

私が言いたかったのは以下のことです。

フィルターを 1 回サブスクライブするために各クライアントによって呼び出される wcf サービスを作成します。wcf サービス自体は、単にデータをデータベースに追加し、クライアント名やフィルター情報などの情報をデータ ストアに含めます。次に、ウィンドウ サービスに含まれるワーカー スレッドは、単にデータベースにデータをポーリングし、データが利用可能になると、サブスクリプション テーブルから読み取ります。次に、rabbitmq のような共有キュー サーバーである可能性がある各クライアントのキューにデータをプッシュします。

クライアント側では、それがウィンドウ ベースのアプリであると仮定すると、それ自体の名前 (client1 など) を持つキューでデータを検索することにより、rabbitmq キュー サーバーにデータをポーリングするだけです。

于 2012-04-26T19:34:32.297 に答える