当前位置:网站首页>. Net cloud native architect training camp (responsibility chain mode) -- learning notes

. Net cloud native architect training camp (responsibility chain mode) -- learning notes

2022-06-23 17:47:00 Zhengziming

Catalog

  • The chain of responsibility model
  • Source code

The chain of responsibility model

The processor in the responsibility chain is responsible for handling the request , The customer just needs to send the request to the responsibility chain , There is no need to care about the processing details of the request and the delivery of the request , So the responsibility chain decouples the sender of the request and the handler of the request

When to use : Filter many channels when processing messages

Use scenarios :

  • There are multiple objects that can handle the same request , The specific object to handle the request is automatically determined by the runtime
  • In the absence of an explicit recipient , Submit a request to one of multiple objects
  • You can dynamically specify a set of objects to handle requests

Source code

https://github.com/dotnet/aspnetcore/

stay ASP .NET Core Source code Kestrel among , structure KestrelConnection Then send to HttpConnectionMiddleware Middleware processing pipeline

In the catalog Microsoft.AspNetCore.Server.Kestrel.Core Below KestrelServerImpl There is one of them. UseHttpServer Method

options.UseHttpServer(ServiceContext, application, options.Protocols, addAltSvcHeader);

stay UseHttpServer Method constructs a HttpConnectionMiddleware, After the construction, the IConnectionBuilder Of Use Method

public static IConnectionBuilder UseHttpServer<TContext>(this IConnectionBuilder builder, ServiceContext serviceContext, IHttpApplication<TContext> application, HttpProtocols protocols, bool addAltSvcHeader) where TContext : notnull
{
    var middleware = new HttpConnectionMiddleware<TContext>(serviceContext, application, protocols, addAltSvcHeader);
    return builder.Use(next =>
    {
        return middleware.OnConnectionAsync;
    });
}

stay IConnectionBuilder Implementation class of ConnectionBuilder You can see it and ASP .NET Core The pipes are exactly the same

There is one IList Of _components The interface of

private readonly IList<Func<ConnectionDelegate, ConnectionDelegate>> _components = new List<Func<ConnectionDelegate, ConnectionDelegate>>();

call Use Method is added to _components in

public IConnectionBuilder Use(Func<ConnectionDelegate, ConnectionDelegate> middleware)
{
    _components.Add(middleware);
    return this;
}

Last Build Do a reverse when

public ConnectionDelegate Build()
{
    ConnectionDelegate app = features =>
    {
        return Task.CompletedTask;
    };

    foreach (var component in _components.Reverse())
    {
        app = component(app);
    }

    return app;
}

KestrelServerImpl Of UseHttpServer Method by options call

options.UseHttpServer(ServiceContext, application, options.Protocols, addAltSvcHeader);

Although it is ListenOptions, But it's actually a ConnectionBuilder

public class ListenOptions : IConnectionBuilder, IMultiplexedConnectionBuilder

It has one _middleware Of List

internal readonly List<Func<ConnectionDelegate, ConnectionDelegate>> _middleware = new List<Func<ConnectionDelegate, ConnectionDelegate>>();

call Use Method time , All middleware will be added

public IConnectionBuilder Use(Func<ConnectionDelegate, ConnectionDelegate> middleware)
{
    _middleware.Add(middleware);
    return this;
}

Last call Build When , Connect all Middleware in series

public ConnectionDelegate Build()
{
    ConnectionDelegate app = context =>
    {
        return Task.CompletedTask;
    };

    for (var i = _middleware.Count - 1; i >= 0; i--)
    {
        var component = _middleware[i];
        app = component(app);
    }

    return app;
}

Build Then generate connectionDelegate, Pass in _transportManager

options.UseHttpServer(ServiceContext, application, options.Protocols, addAltSvcHeader);

var connectionDelegate = options.Build();

options.EndPoint = await _transportManager.BindAsync(options.EndPoint, connectionDelegate, options.EndpointConfig, onBindCancellationToken).ConfigureAwait(false);

stay _transportManager You can see where the binding is passed into StartAcceptLoop in

StartAcceptLoop(new GenericConnectionListener(transport), c => connectionDelegate(c), endpointConfig);

stay StartAcceptLoop Bind to connectionDispatcher

var connectionDispatcher = new ConnectionDispatcher<T>(_serviceContext, connectionDelegate, transportConnectionManager);
var acceptLoopTask = connectionDispatcher.StartAcceptingConnections(connectionListener);

stay connectionDispatcher When it starts , Monitor requests

var connection = await listener.AcceptAsync();

When there is a request, it will _connectionDelegate Package to KestrelConnection

var kestrelConnection = new KestrelConnection<T>(id, _serviceContext, _transportConnectionManager, _connectionDelegate, connection, Log);

_connectionDelegate It is an encapsulation of queue requests based on thread pool , Last kestrelConnection Will be pushed into a request queue for execution

ThreadPool.UnsafeQueueUserWorkItem(kestrelConnection, preferLocal: false);

The main process to be performed can be in KestrelConnection View in , It inherited IThreadPoolWorkItem, This is a queue method

internal class KestrelConnection<T> : KestrelConnection, IThreadPoolWorkItem where T : BaseConnectionContext

stay ExecuteAsync When it comes to execution _connectionDelegate

await _connectionDelegate(connectionContext);

This is the whole Kestrel Network request received , All subsequent processing actions

Here, the principle of opening and closing is also followed , The latter responsibility chain model can be continuously expanded

It also embodies the principle of separation of concerns , Certain parts, such as the receiving network , The byte part is processed first , Then the uncertain part is handled through the responsibility chain pipeline

原网站

版权声明
本文为[Zhengziming]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/01/202201052033309522.html