关于c#:ASP.NET核心中AsyncLocal的安全性

Safety of AsyncLocal in ASP.NET Core

AsyncLocalfor .NET的核心,是CallContext替代。然而,它是不清楚如何"安全",它是用ASP.NET中的核心。

在ASP.NET MVC(4和5)前,ASP.NET线程模型CallContext敏捷制造不稳定。因此,ASP.NET中的唯一安全的方式来实现行为通过请求一httpcontext.current.items逻辑上下文所使用。在一个CallContexthttpcontext.current.items封面,但它是实现,这是安全的方式做一个ASP.NET。

在对比,在欧文的上下文/武士刀的Web API的线程模型,敏捷性,需要的是什么问题。我可以安全地使用后小心CallContext,考虑到如何正确的处理它。

但现在我与ASP.NET的核心处理。我想用下面的中间件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public class MultiTenancyMiddleware
{
    private readonly RequestDelegate next;
    static int random;

    private static AsyncLocal<string> tenant = new AsyncLocal<string>();
    //This is the new form of"CallContext".
    public static AsyncLocal<string> Tenant
    {
        get { return tenant; }
        private set { tenant = value; }
    }

    //This is the new verion of [ThreadStatic].
    public static ThreadLocal<string> LocalTenant;

    public MultiTenancyMiddleware(RequestDelegate next)
    {
        this.next = next;
    }

    public async Task Invoke(HttpContext context)
    {
        //Just some garbage test value...
        Tenant.Value = context.Request.Path + random++;
        await next.Invoke(context);

        //using (LocalTenant = new AsyncLocal<string>()) {
        //    Tenant.Value = context.Request.Path + random++;
        //    await next.Invoke(context);
        //}
    }
}

到目前为止,上面的代码似乎工作只是罚款。但至少有一个红色的标志。在过去,它是关键,确保CallContext到什么样的资源,必须处理后invocation释放每个。

现在我没有自明湖路AsyncLocal"清洁"。

1包括该代码,显示出知识,ThreadLocal作品。它是IDisposable,所以它有明显的清洁机制。在对比的是,AsyncLocalIDisposable。这是unnerving。

这是因为还没有AsyncLocal是在释放状态的候选人?这是因为它是真正的或不再必要进行清理?

即使是在我AsyncLocal用在上面的例子,有可能是老式的"敏捷性的问题,在ASP.NET线程"的核心是要让这个中间件行不通?

特别注

对于那些有问题的unfamiliar CallContext安切洛蒂在ASP.NET应用程序,所以在本参考到后,乔恩飞碟在深入讨论有关的问题(这在转向从斯科特hanselman引用评论)。这个"问题"不是一个错误,它是只是一个accounted环境必须仔细研究。

此外,我可以亲自证明这不幸的行为。当我建立ASP.NET应用程序,我的一部分。通常包括负载测试的自动化测试基础设施。它是在负载测试,我可以变得不稳定,也见证CallContext(在2%到4%的请求被损坏的CallContext学院演出。我有一个湖泊。所以在Web API GET安切洛蒂CallContext行为稳定,但POST操作都是不稳定的。唯一的方式来实现,是依靠httpcontext.current.items完全稳定。

然而,在ASP.NET核心案例,我无法在没有httpcontext.items依赖静态...there搜索接入点。我现在还没有可以创建负载测试.NET应用程序的核心tinkering I’M个部分,这是为什么我不回答这个问题是我自己。:)

Again: Please understand that the"instability" and"problem" I'm discussing is not a bug at all. CallContext is not somehow flawed. The issue is simply a consequence of the thread dispatch model employed by ASP.NET. The solution is simply to know the issue exists, and to code accordingly (e.g. use HttpContext.Current.Items instead of CallContext, when inside an ASP.NET app).

我的目标是了解如何这一问题在动态(或不)适用于ASP.NET的核心,所以我不小心当使用新的代码生成不稳定的AsyncLocal构造。


我只是在研究corecrl的executionContext类的源代码:https://github.com/dotnet/corecrl/blob/775003a4c72f0acc37eab84628fcef541533ba4e/src/mscorlib/src/system/threading/executioncontext.cs

根据我对代码的理解,异步本地值是每个ExecutionContext实例的字段/变量。它们不基于线程本地或任何线程特定的持久化数据存储。

为了验证这一点,在我的线程池线程测试中,当重用同一个线程池线程时,将无法访问异步本地值中的一个实例,并且在下一个GC循环中调用了用于清除自身的"左"实例的析构函数,这意味着该实例将按预期进行gced。