【问题标题】:How can I synchronize the access to a resource across all the request to a web api如何在对 Web api 的所有请求中同步对资源的访问
【发布时间】:2022-11-07 14:42:20
【问题描述】:

它是一个 web api,它在服务器端使用访问令牌访问某些资源。令牌在 180 秒后过期。请求最初会从令牌端点生成令牌并将其存储在 Redis 缓存中,该操作之后是使用该令牌的后续调用。检查令牌过期,当请求发现它过期时,它将获得一个新的访问令牌并在缓存中更新它。

问题是,如果两个请求发现令牌已过期,就说第一个请求获得了一个新令牌 - abc123 并更新它,但对于第二个请求,它已经检查过令牌是否已过期,现在这将还获得一个新令牌 - xyz321 并将 abc123 替换为 xyz321。但是对于第一个请求,令牌abc123 不再有效,因此后续调用将失败,令牌abc123

所以这是我试图防止这个问题的东西:

public async Task<string> GetAccessTokenAsync()
{
    string token = string.Empty;
    using (Mutex mutex = new Mutex(false))
    {
        try
        {
            if (_storage.IsTokenExpired()) // returns "false" if expired or no token set
            {
                mutex.WaitOne();
                if (_storage.IsTokenExpired())
                {
                    token = await AccessTokenEndpointCallAsync();
                    _storage.StoreAccessToken(token);
                }
                else
                {
                    token = _storage.ReadAccessToken();
                }
            }
            else
            {
                token = _storage.ReadAccessToken();
            }
        }
        catch(Exception)
        {
            throw;
        }
        finally
        {
            mutex.ReleaseMutex();
        }
    }
    return token;
}

好吧,如果我启动浏览器并调用 api,一切正常,但如果我打开另一个浏览器并进行调用,则会引发错误 -

消息:对象同步方法是从 不同步的代码块。堆栈跟踪:在 System.Threading.Mutex.ReleaseMutex()

【问题讨论】:

  • 使用静态SemaphoreSlim,它允许您锁定异步方法,

标签: c# asp.net-core redis asp.net-core-webapi


【解决方案1】:

如果您只有一个 Web 服务器,您可以简单地在锁定对象上使用 lock()。忘记互斥锁。但是请注意,您不能在锁定上下文中等待。您的锁定块必须是同步的。

为了回答您的问题,您正在释放一个您没有获得的互斥锁。要获取 mutext,您必须首先等待它。请参阅documentation

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-08-27
    • 1970-01-01
    • 2018-05-11
    • 2011-01-31
    • 1970-01-01
    • 1970-01-01
    • 2022-08-05
    • 1970-01-01
    相关资源
    最近更新 更多