当前位置:网站首页>ASP. Net 6 middleware series - execution sequence

ASP. Net 6 middleware series - execution sequence

2022-04-23 03:06:00 Dotnet cross platform

80b73b8994a1510e000abad6ac297281.png

This article is ASP.NET 6 The first of a series of middleware articles 3 part , You can also read The first 1 part and The first 2 part .

The pipeline we create through middleware has execution order , The execution order is the same as the addition order of middleware , Next, let's discuss why there is an execution order , And the importance of it .

The sample project

stay GitHub You can get the code involved in this article on :

https://github.com/zilor-net/ASPNET6Middleware/tree/Part3

Execution order

In this series of The first 1 part in , Middleware constitutes a pipeline , The middleware in the pipeline is executed in a certain order , As shown in the figure below :

f5421de9e3f981b4e2b1733e8fa8326f.png

The requests pass through the middleware in sequence , The responses are returned in the reverse order .

In the previous article , We have defined two middleware classes :

  • LoggingMiddleware Used to record requests / Response log ;

  • SimpleResponseMiddleware Used to interrupt a pipe , Return response .

In this article , We still use LoggingMiddleware For example :

app.UseLoggingMiddleware();

Add delay

Let's create a new middleware class , be called IntentionalDelayMiddleware, It looks something like this :

namespace  MiddlewareNET6Demo.Middleware
{
    public  class  IntentionalDelayMiddleware
    {
        private  readonly RequestDelegate _next;

        public IntentionalDelayMiddleware(RequestDelegate next)
        {
            _next = next;
        }

        public async Task InvokeAsync(HttpContext context)
        {
            await Task.Delay(100);

            await _next(context);

            await Task.Delay(100);
        }
    }
}

This middleware will wait for both incoming requests and outgoing responses 100ms, The total waiting time is 200ms.

Of course , Under the actual situation , We won't do that .

ad locum ,IntentionalDelayMiddleware It just represents some kind of undefined middleware , It takes a predictable time to execute .

We need to add a... To the pipeline IntentionalDelayMiddleware Example . The problem lies in , We are in LoggingMiddleware Add it before or after ?

In fact, in this case , This question may not be important , Because these two middleware will not interact , And don't deal with the same thing .

In this example , Let us in LoggingMiddleware Then add IntentionalDelayMiddleware

app.UseLoggingMiddleware();
app.UseIntentionalDelayMiddleware();

If you run the application now , We may not find significant differences , because 200 Milliseconds is pretty fast .

Add execution time

In order to monitor the time consumed by each request , We often need to record the execution time of each request to our system .

This requirement is very simple for middleware , We can use .NET Provided Stopwatch Class and 2 Created in this article LoggingService To achieve .

Here's what's called TimeLoggingMiddleware Middleware class :

using MiddlewareNET6Demo.Logging;
using System.Diagnostics;

namespace  MiddlewareNET6Demo.Middleware
{
    public  class  TimeLoggingMiddleware
    {
        private  readonly RequestDelegate _next;
        private  readonly ILoggingService _logger;

        public TimeLoggingMiddleware(RequestDelegate next, 
                                     ILoggingService logger)
        {
            _next = next;
            _logger = logger;
        }

        public async Task InvokeAsync(HttpContext context)
        {
            Stopwatch watch = new Stopwatch();
            watch.Start();

            await _next(context);

            watch.Stop();
            _logger.Log(LogLevel.Information, "Time to execute: " + watch.ElapsedMilliseconds + " milliseconds.");
        }
    }
}

We need to add it to the pipeline . however , There is still a problem : Where should we add it ?

If we were to TimeLoggingMiddleware Add to IntentionalDelayMiddleware Before , Then the delay caused by the latter will be included in the range measured by the former .

If we were to TimeLoggingMiddleware Add to IntentionalDelayMiddleware after , Then the delay caused by the latter will not be included in the range measured by the former .

Let's look at the pipe :

app.UseHttpsRedirection();
app.UseStaticFiles();

//  If there is any delay in the middleware , Then the delay will not be included in the time log .
app.UseLoggingMiddleware();

//  Time recording middleware 
app.UseTimeLoggingMiddleware();

//  Delay middleware .
//  here , The delay is included in the time log .
app.UseIntentionalDelayMiddleware();

app.UseRouting();

app.UseAuthorization();

app.MapRazorPages();

app.Run();

In this Program.cs In file , Which position is more suitable for TimeLoggingMiddleware? The answer depends on a few questions :

  • Does the time log need to include execution time such as invalid Authorization ? If it is , Then you must call app.UseAuthorization() Before , place TimeLoggingMiddleware.

  • Routing calls take very little time , But you can measure . Are we going to include it ? If it is , You have to call app.UseRouting() Before , place TimeLoggingMiddleware.

Like most real-world problems , There is no clear answer to this question .

If there are no clear instructions , Then it is ultimately up to the developer to make a decision according to the specific situation of the system .

It should be noted that :

app.UseIntentionalDelayMiddleware();
app.UseTimeLoggingMiddleware();

These two are totally different :

app.UseTimeLoggingMiddleware();
app.UseIntentionalDelayMiddleware();

This is an example of why the order of Middleware in the pipeline is very important .

版权声明
本文为[Dotnet cross platform]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/04/202204230301333959.html