1

同じホスト アプリケーション内でホストされる一連の ServiceStack サービスを作成したいと考えています。これらはすべて共有ファイル リソースのセットを使用します。競合を防ぐために、同期コード (別名ロック) を作成して、ファイルの読み取り/書き込みの競合を防ぐつもりです。

単一のサービス メソッド呼び出しの間だけファイルをロックしたい場合、解決策は簡単です。たとえば、セッション キーによってロックを追跡する同期グローバル オブジェクトを作成できます。ただし、クライアント アプリケーションが、さまざまな ServiceStack サービスのさまざまなメソッドへの複数の呼び出しの間、ファイル リソースをロックできるようにしたいと考えています。

これを達成するための最良の方法は何ですか (または、これは、私がそうするべきではないと人々が私に言う質問の1つです)?

これまでに私が検討したことは次のとおりです。

  1. 複数の ServiceStack サービスで 1 つの ISession オブジェクトを共有できれば、セッション キーに基づいてファイル ロックを追跡できます。しかし、とにかくそれを行う方法を見つけることができませんでした。これは、JsonServiceClient オブジェクトを使用して C# クライアントと連携する必要があります。ServiceStack サービスごとにそのようなオブジェクトが 1 つ存在し、それぞれがサービス エンドで個別の ISession を生成します。

  2. 認証を実装した場合、認証されたユーザー ID でロックを追跡できますが、2 人の別々のユーザーが同じログインを使用する可能性があり、その場合、リソース ロックを共有できません。

  3. すべてのサービス メソッドを 1 つのサービスに結合して、1 つのセッションを共有することができました。これは、可能な複数のリクエストを組み合わせた複雑なリクエスト オブジェクトを作成することを意味します。これは、それが聞こえるようなひどいクラッジではないかもしれません. リクエスト オブジェクトは、カスタム SQL 言語で記述されたクエリ文字列である可能性があり、私のサービスはクエリを解析して実行します。コーディング作業が増えるので、これはやりたくありません (ただし、カスタム SQL 言語用の無料で堅牢な解析ツールを知っている人がいれば、検討するかもしれません)。

  4. トランザクション ID を分配するトランザクション サービスを作成します。クライアントがロックを保持したい場合、最初にトランザクション サービスからトランザクション ID を取得し、その後のすべてのサービス呼び出しでこの ID を渡す必要があります (これは、各要求クラスのオプション プロパティになります)。これは、サービス間でセッション (またはセッション キー) を共有することと大差ありませんが、クライアントにいくつかの作業を行わせています。ふー。

4

1 に答える 1

2

サービスの意味が少しわかりません。1つのアプリホストで複数のホストを使用できます。セッションメカニズムを使用すると、サービス間で特定のクライアントセッションを共有できます。サービススタック内のセッションICacheClientは登録済みのものを使用するため、たとえばサーバーファームがある場合は、のようなものを使用しRedisCacheClientて、同じアプリホストを実行している複数のサーバー間でセッション情報を共有できます。ファイルをロックしたい場合は、この情報をに保存することもできますICacheClient。だからあなたは次のようなことをすることができます:

public class FileLock
{
    public string ClientId { get; set; }
    public string FileId { get; set; }
}

public class FileLockService : Service
{
    public object Post(FileLock req)
    {
        // this will only be added to the cache if it doesn't exist
        // but understand that the cache key needs to be unique
        // within the entire system, so qualify it with a urn...
        var wasAbleToLock = Cache.Add("file:lock:" + req.FileId, req.ClientId);

        return wasAbleToLock;
    }

    public object Get(FileLock req)
    {
        // return the client id for who ever has the lock
        return Cache.Get("file:lock:" + req.FileId);
    }
}
于 2013-03-05T17:51:20.000 に答える