我有一个API端点需要尽快返回给调用者。它目前返回不到1毫秒。但是,如果我将一些内容记录到数据库中,现在需要接近10毫秒。
如何完成请求,然后在请求完成后进行某种处理?我尝试使用Response.Body.Flush(),但这并没有完成请求,它仍然需要整整10毫秒。看起来它正在发送/刷新有效负载,但在动作方法完成之前,请求仍然没有完成。
是否可以在中间件中进行日志记录?
编辑:
我找到的一个解决方法是使用FluentScheduler,如下所示:
JobManager.Initialize(new Registry());
JobManager.Start();
在Host.cun()之前的Program.cs中然后从这样的动作安排一个即时任务:
JobManager.AddJob(() =>
{
// do something...
}, (s) => s.ToRunOnceIn(1).Seconds());
答案 0 :(得分:2)
你需要以某种方式开始一个不同的线程。放在管道前面的中间件将使您有机会在请求完成之前完成工作。如果你从那里旋转一个线程,那么它可能会起作用。
你可能想要使用某种producer-consumer pattern,这样你就不会杀掉你的服务器。否则,如果每个请求都启动了一个立即生效的线程,并且您同时有多个请求,那么最终可能会耗尽资源。生产者 - 消费者会帮助你限制这项工作。
如果您不赶时间,我可以等待一周左右,当我为ASP.NET提供文件记录器时,您会在那里看到类似的实现。
答案 1 :(得分:1)
登录中间件不会对您有所帮助,因为您仍然在请求管道中,并且您可能有也可能没有必要的信息来记录您需要做的事情。
您可以异步登录,这可能会在没有重大架构更改的情况下为您带来最大的改进:Async Programming : Introduction to Async/Await on ASP.NET
如果这不起作用,您可以执行多线程的操作。这变得更复杂,但它仍然可行:Multithreading in C# .NET 4.5 (Part 1)
答案 2 :(得分:0)
异步是解决此问题的正确方法。在您的请求期间(无论何时),启动对数据库的异步连接/查询。只是不要等它完成。
答案 3 :(得分:0)
这只是一个想法,所以如果我离开的话,请不要投票。你能用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 ());
}
}