草庐IT

c# - ASP.NET Core 中 AsyncLocal 的安全性

coder 2023-07-09 原文

对于 .NET 核心, AsyncLocal CallContext 的替代品.但是,尚不清楚在 ASP.NET Core 中使用它有多“安全”。

在 ASP.NET 4 (MVC 5) 和更早版本中,thread-agility model of ASP.NET made CallContext unstable .因此,在 ASP.NET 中,实现每个请求逻辑上下文行为的唯一安全方法是使用 HttpContext.Current.Items。在幕后,HttpContext.Current.Items 是用 CallContext 实现的, 但它是以对 ASP.NET 安全的方式完成的。

相比之下,在 OWIN/Katana Web API 的上下文中,线程敏捷模型不是问题。在 careful considerations of how correctly to dispose it 之后,我能够安全地使用 CallContext .

但现在我正在处理 ASP.NET Core。我想使用以下中间件:

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 至关重要被视为必须在每次调用后释放的资源。

现在我发现没有不言而喻的“清理”方法AsyncLocal .

我包含了代码,注释掉了,展示了如何 ThreadLocal<T>作品。是IDisposable ,所以它有一个明显的清理机制。相比之下,AsyncLocal不是 IDisposable .这令人不安。

这是因为 AsyncLocal尚未处于发布候选状态?还是真的不需要清理了?

即使 AsyncLocal在我上面的示例中使用得当,ASP.NET Core 中是否存在任何类型的老式“线程敏捷性”问题会使该中间件无法运行?

特别说明

对于那些不熟悉问题的人 CallContext在 ASP.NET 应用程序中,在 this SO post, Jon Skeet 中引用 in-depth discussion about the problem (反过来引用 commentary from Scott Hanselman )。这个“问题”不是错误 - 它只是一种必须仔细考虑的情况。

此外,我可以亲自证明这种不幸的行为。当我构建 ASP.NET 应用程序时,我通常将负载测试作为我的自动化测试基础结构的一部分。在负载测试期间,我可以见证 CallContext变得不稳定(可能有 2% 到 4% 的请求显示 CallContext 已损坏。我还看到 Web API GET 具有稳定的 CallContext 行为,但 POST 操作都不稳定的情况。唯一实现完全稳定的方法是依赖 HttpContext.Current.Items。

但是,在 ASP.NET Core 的情况下,我不能依赖 HttpContext.Items...没有这样的静态访问点。我还无法为我正在修改的 .NET Core 应用程序创建负载测试,这也是我自己没有回答这个问题的部分原因。 :)

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 Core 中应用(或不应用),这样我就不会在使用新的 AsyncLocal 时意外地构建不稳定的代码。构造。

最佳答案

我只是在查看 CoreClr 的 ExecutionContext 类的源代码: https://github.com/dotnet/coreclr/blob/775003a4c72f0acc37eab84628fcef541533ba4e/src/mscorlib/src/System/Threading/ExecutionContext.cs

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

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

关于c# - ASP.NET Core 中 AsyncLocal 的安全性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36511243/

有关c# - ASP.NET Core 中 AsyncLocal 的安全性的更多相关文章

  1. ruby - 如何使用 Ruby aws/s3 Gem 生成安全 URL 以从 s3 下载文件 - 2

    我正在编写一个小脚本来定位aws存储桶中的特定文件,并创建一个临时验证的url以发送给同事。(理想情况下,这将创建类似于在控制台上右键单击存储桶中的文件并复制链接地址的结果)。我研究过回形针,它似乎不符合这个标准,但我可能只是不知道它的全部功能。我尝试了以下方法:defauthenticated_url(file_name,bucket)AWS::S3::S3Object.url_for(file_name,bucket,:secure=>true,:expires=>20*60)end产生这种类型的结果:...-1.amazonaws.com/file_path/file.zip.A

  2. c# - 如何在 ruby​​ 中调用 C# dll? - 2

    如何在ruby​​中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL

  3. C# 到 Ruby sha1 base64 编码 - 2

    我正在尝试在Ruby中复制Convert.ToBase64String()行为。这是我的C#代码:varsha1=newSHA1CryptoServiceProvider();varpasswordBytes=Encoding.UTF8.GetBytes("password");varpasswordHash=sha1.ComputeHash(passwordBytes);returnConvert.ToBase64String(passwordHash);//returns"W6ph5Mm5Pz8GgiULbPgzG37mj9g="当我在Ruby中尝试同样的事情时,我得到了相同sha

  4. ruby - 如何安全地删除文件? - 2

    在Ruby中是否有Gem或安全删除文件的方法?我想避免系统上可能不存在的外部程序。“安全删除”指的是覆盖文件内容。 最佳答案 如果您使用的是*nix,一个很好的方法是使用exec/open3/open4调用shred:`shred-fxuz#{filename}`http://www.gnu.org/s/coreutils/manual/html_node/shred-invocation.html检查这个类似的帖子:Writingafileshredderinpythonorruby?

  5. 基于C#实现简易绘图工具【100010177】 - 2

    C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.

  6. ruby - 用 YAML.load 解析 json 安全吗? - 2

    我正在使用ruby2.1.0我有一个json文件。例如:test.json{"item":[{"apple":1},{"banana":2}]}用YAML.load加载这个文件安全吗?YAML.load(File.read('test.json'))我正在尝试加载一个json或yaml格式的文件。 最佳答案 YAML可以加载JSONYAML.load('{"something":"test","other":4}')=>{"something"=>"test","other"=>4}JSON将无法加载YAML。JSON.load("

  7. ruby - 在 ASP 页面上 Mechanize 中断 - 2

    require'mechanize'agent=Mechanize.newlogin=agent.get('http://www.schoolnet.ch/DE/HomeDE.htm')agent.clicklogin.link_withtext:/Login/然后我得到Mechanize::UnsupportedSchemeError。 最佳答案 Mechanize不支持javascript但您可以将搜索字段添加到表单并为其分配搜索词并使用mechanize提交表单form=page.forms.firstform.add_fie

  8. ruby-on-rails - 安全地显示使用回形针 gem 上传的图像 - 2

    默认情况下:回形针gem将所有附件存储在公共(public)目录中。出于安全原因,我不想将附件存储在公共(public)目录中,所以我将它们保存在应用程序根目录的uploads目录中:classPost我没有指定url选项,因为我不希望每个图像附件都有一个url。如果指定了url:那么拥有该url的任何人都可以访问该图像。这是不安全的。在user#show页面中:我想实际显示图像。如果我使用所有回形针默认设置,那么我可以这样做,因为图像将在公共(public)目录中并且图像将具有一个url:Someimage:看来,如果我将图像附件保存在公共(public)目录之外并且不指定url(同

  9. ruby - 使写入文件线程安全 - 2

    我在一个ruby​​文件中有一个函数可以像这样写入一个文件File.open("myfile",'a'){|f|f.puts("#{sometext}")}这个函数在不同的线程中被调用,使得像上面这样的文件写入不是线程安全的。有谁知道如何以最简单的方式使这个文件写入线程安全?更多信息:如果重要的话,我正在使用rspec框架。 最佳答案 您可以通过File#flock给锁File.open("myfile",'a'){|f|f.flock(File::LOCK_EX)f.puts("#{sometext}")}

  10. c# - C# 中的 Flatten Ruby 方法 - 2

    我如何做Ruby方法"Flatten"RubyMethod在C#中。此方法将锯齿状数组展平为一维数组。例如:s=[1,2,3]#=>[1,2,3]t=[4,5,6,[7,8]]#=>[4,5,6,[7,8]]a=[s,t,9,10]#=>[[1,2,3],[4,5,6,[7,8]],9,10]a.flatten#=>[1,2,3,4,5,6,7,8,9,10 最佳答案 递归解决方案:IEnumerableFlatten(IEnumerablearray){foreach(variteminarray){if(itemisIEnume

随机推荐