如何在多个服务之间分割多个ServiceStack服务调用实现资源同步?

时间:2013-03-05 14:51:29

标签: transactions locking servicestack

我想创建一组托管在同一主机应用程序中的ServiceStack服务,这些服务都将使用一组共享的文件资源。为了防止冲突,我打算创建同步代码(也称为锁定)以防止文件的读/写冲突。

如果我只想在单个服务方法调用期间锁定文件,那么解决方案很简单。例如,我可以创建一个同步的全局对象,通过Session Key跟踪锁定。但是,我希望客户端应用程序能够在不同ServiceStack服务中的不同方法的MULTIPLE调用期间锁定文件资源。

实现这一目标的最佳方式是什么(或者这是人们会告诉我不应该这样做的问题之一)?

这是我到目前为止所考虑的内容:

  1. 如果我可以在多个ServiceStack服务中共享一个ISession对象,我可以根据Session密钥跟踪文件锁。但我无论如何也找不到这样做。这需要使用JsonServiceClient对象与C#客户端一起工作,每个ServiceStack服务都会有一个这样的对象,它们每个都在服务端生成一个单独的ISession。

  2. 如果我实施了身份验证,我可以通过经过身份验证的用户ID跟踪锁定,但是两个单独的人可能会使用相同的登录,在这种情况下,他们无法共享资源锁。

  3. 我可以将所有服务方法合并到一个服务中,然后共享一个会话。这意味着创建一个复杂的请求对象,它将是几个可能的请求的组合。这可能不是听起来像是糟糕的kludge。请求对象可以是用自定义SQL语言编写的查询字符串,我的服务将解析并运行查询。我不想这样做,因为它有更多的编码工作(尽管如果有人知道自定义SQL语言的免费,强大的解析工具,我可能会考虑它。)

  4. 创建一个处理交易ID的交易服务。如果客户端想要持有锁,它必须首先从Transaction服务获取事务ID,并在每次后续服务调用时传入此ID(它将是每个请求类中的可选属性)。这与在服务之间共享会话(或者更确切地说是会话密钥)没什么不同,但我正在让客户端完成一些工作。 FEH。

1 个答案:

答案 0 :(得分:2)

我对服务的含义有点迷失,你可以拥有一个应用程序主机,并且使用会话机制将允许你在服务之间共享特定的客户端会话。服务堆栈中的会话使用您已注册的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);
    }
}