我想创建一组托管在同一主机应用程序中的ServiceStack服务,这些服务都将使用一组共享的文件资源。为了防止冲突,我打算创建同步代码(也称为锁定)以防止文件的读/写冲突。
如果我只想在单个服务方法调用期间锁定文件,那么解决方案很简单。例如,我可以创建一个同步的全局对象,通过Session Key跟踪锁定。但是,我希望客户端应用程序能够在不同ServiceStack服务中的不同方法的MULTIPLE调用期间锁定文件资源。
实现这一目标的最佳方式是什么(或者这是人们会告诉我不应该这样做的问题之一)?
这是我到目前为止所考虑的内容:
如果我可以在多个ServiceStack服务中共享一个ISession对象,我可以根据Session密钥跟踪文件锁。但我无论如何也找不到这样做。这需要使用JsonServiceClient对象与C#客户端一起工作,每个ServiceStack服务都会有一个这样的对象,它们每个都在服务端生成一个单独的ISession。
如果我实施了身份验证,我可以通过经过身份验证的用户ID跟踪锁定,但是两个单独的人可能会使用相同的登录,在这种情况下,他们无法共享资源锁。
我可以将所有服务方法合并到一个服务中,然后共享一个会话。这意味着创建一个复杂的请求对象,它将是几个可能的请求的组合。这可能不是听起来像是糟糕的kludge。请求对象可以是用自定义SQL语言编写的查询字符串,我的服务将解析并运行查询。我不想这样做,因为它有更多的编码工作(尽管如果有人知道自定义SQL语言的免费,强大的解析工具,我可能会考虑它。)
创建一个处理交易ID的交易服务。如果客户端想要持有锁,它必须首先从Transaction服务获取事务ID,并在每次后续服务调用时传入此ID(它将是每个请求类中的可选属性)。这与在服务之间共享会话(或者更确切地说是会话密钥)没什么不同,但我正在让客户端完成一些工作。 FEH。
答案 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);
}
}