Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-core/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Asp.net web api 请求完成后的处理_Asp.net Web Api_Asp.net Core - Fatal编程技术网

Asp.net web api 请求完成后的处理

Asp.net web api 请求完成后的处理,asp.net-web-api,asp.net-core,Asp.net Web Api,Asp.net Core,我有一个API端点需要尽快返回给调用方。它目前返回速度低于1ms。但是,如果我将一些东西记录到数据库中,现在需要接近10毫秒 您将如何完成请求,然后在请求完成后进行某种处理?我尝试了Response.Body.Flush(),但这并没有完成请求,仍然需要整整10毫秒。看起来它正在发送/刷新有效负载,但在操作方法完成之前,请求仍然没有完成 在中间件中进行日志记录是否可行 编辑: 我发现的一个解决方法是这样使用: JobManager.Initialize(new Registry()); JobM

我有一个API端点需要尽快返回给调用方。它目前返回速度低于1ms。但是,如果我将一些东西记录到数据库中,现在需要接近10毫秒

您将如何完成请求,然后在请求完成后进行某种处理?我尝试了Response.Body.Flush(),但这并没有完成请求,仍然需要整整10毫秒。看起来它正在发送/刷新有效负载,但在操作方法完成之前,请求仍然没有完成

在中间件中进行日志记录是否可行

编辑:

我发现的一个解决方法是这样使用:

JobManager.Initialize(new Registry());
JobManager.Start();
JobManager.AddJob(() =>
{
    // do something...
}, (s) => s.ToRunOnceIn(1).Seconds());
在Program.cs中的host.Run()之前,然后通过以下操作计划立即执行的任务:

JobManager.Initialize(new Registry());
JobManager.Start();
JobManager.AddJob(() =>
{
    // do something...
}, (s) => s.ToRunOnceIn(1).Seconds());

登录中间件对您没有帮助,因为您仍然在请求管道中,并且您可能有或者没有必要的信息来记录您需要做的事情

您可以异步登录,这可能会在不进行重大架构更改的情况下为您带来最大的改进:


如果这不起作用,您可以做一些多线程的事情。这变得更加复杂,但仍然可行:

异步是解决此问题的正确方法。在您的请求期间(无论何时),启动到数据库的异步连接/查询。不要等到它结束。

你需要以某种方式开始另一个线程。放置在管道前面的中间件将使您有机会在请求完成之前完成工作。如果你从那里旋转一条线,那么它可能会工作

您可能想使用某种类型的服务器,这样就不会杀死服务器。否则,如果每个请求都启动一个线程立即工作,并且您同时有多个请求,那么最终可能会耗尽资源。生产者和消费者会帮你控制这项工作


如果您不着急,您可以再等一周左右,我将为ASP.NET提供文件记录器,然后您将在那里看到类似的实现。

这只是一个想法,所以如果我离您太远,请不要投反对票。您能使用HttpResponse.RegisterForDispose()吗?例如:

public class JobToRunAfterRequestIsComplete : IDisposable {
    public void Dispose()
    {
        // Do your post-processing here.
    } 
}

public class YourController {
    public void YourAction() {
        // Do your normal processing here
        ...
        // Register your post processing here
        this.Response.RegisterForDispose(new JobToRunAfterRequestIsComplete ());
    }
}

这有点过于宽泛,不知道您是否使用了任何消息代理/总线,也不知道您是否看到了特定的代码。可能会发布一些你正在使用的代码。最直接的方法是使用消息总线,然后触发一个事件并在以后将其记录下来。我没有使用任何类型的排队系统。我希望框架中有一些东西可以支持此功能。Response.OnCompleted接近,但运行时连接仍然打开。您确定这会导致性能问题吗?仅仅因为需要10毫秒并不意味着你的服务器将被限制在每秒100个连接。处理异步调用时,请求线程将返回池,并可用于其他请求。异步操作完成后,将使用下一个可用线程完成请求。那么,您是否做过任何性能测量来确定这是否是一个问题。我建立了一个基准。如果禁用日志记录,则所需时间少于1ms;如果我再打开它,它会跳到10秒。我对能够支持多个并发请求不太感兴趣,而是希望每个请求都尽可能快(我正在使用大量缓存来实现这一点;因为我希望“管道完成后”会有一个钩子)…Response.OnCompleted接近,但已连接的仍处于打开状态,呼叫方仍在等待我在OnCompleted中进行处理。我认为这种方法的问题在于,它仍然是管道的一部分,这意味着它会减慢您的整体响应。我不认为它真的会为您带来任何好处g除非您引入了一些异步或多线程方法。如果我可以在请求完成后(即API调用方获得完整响应后)挂接到管道中,那么从外部世界的角度来看,请求耗时不到1ms。是的,如果服务器承受很大压力,则总体速率将增加OM1ms,但这种情况很少见。有很多CPU内核在大多数情况下什么都不做。ASP.NET内核使用依赖项注入,一些服务的作用域是有限的,这意味着它们只有一个与请求相同的生命周期,并在最后得到处理。我不知道它在
ILogger
imple中的行为您确定它没有范围吗?否则此解决方案将无法工作,因为它有可能在完成之前被处理掉(如果请求速度明显快于日志记录操作)OOP,这应该是对另一个答案的评论。虽然范围很好,但我没有考虑过与这些资源的交互。微软不是你们一直告诉我们不要在ASP.NET内部启动我们自己的线程吗?(猜它也应该适用于ASP.NET核心),因为它扰乱了ASP.NET管理其线程池以处理异步请求的方式?如果使用生产者-消费者,则不必为每个请求旋转新线程。Quarts.NET、FluentScheduler和HangFire等框架似乎通过启动线程来工作。但是,据我所知,它们还不支持Core。