Aspnetcore: Projekt Grundgestein

Erstellt am 4. Aug. 2017  ·  126Kommentare  ·  Quelle: dotnet/aspnetcore

Projekt Grundgestein

Beim Projekt-Grundgestein geht es darum, die Komponenten von Kestrel weiter zu entkoppeln, damit wir es als Grundlage für unseren Nicht-HTTP-Netzwerk-Stack verwenden können.
Wir möchten auf den Grundelementen, Mustern und Querschnittsproblemen aufbauen, die heute in ASP.NET Core-Anwendungen vorhanden sind. Das Ziel besteht darin, Frameworks auf höherer Ebene (wie SignalR oder WCF und sogar ASP.NET Core selbst) zu ermöglichen, auf Abstraktionen aufzubauen, die sie nicht an eine bestimmte Verbindungsimplementierung (OWIN for Connections) binden. Als Beispiel ermöglicht es SignalR, sowohl auf TCP als auch auf Websockets ausgeführt zu werden, ohne den zugrunde liegenden Transport verstehen zu müssen. Wir möchten auch den Aufbau von Raw-Low-Level-Protokollservern ermöglichen, um Dinge wie MQTT für IOT-Szenarien zu verarbeiten.

Es gibt 3 Hauptakteure in diesem serverseitigen Programmiermodell:

  • Anwendungen/Middleware/Frameworks – Der Anwendungscode, der Verbindungen verarbeitet und Protokollparsinglogik oder andere Logik implementiert, die den Datenstrom modifiziert (http, TLS als Beispiel)
  • Transporte - Transporte bieten eine Implementierung eines IFeatureCollection , das die zugrunde liegende Verbindungssemantik implementiert. Kurz gesagt, Transporte bieten eine konkrete Implementierung des ConnectionContext , das über den Dispatcher zur Anwendung fließt.
  • Dispatcher - Der Dispatcher ist die Komponente, die die Transportschicht und die Anwendungsschicht zusammenbringt. Seine Aufgabe ist es, die Lebensdauer der Transportverbindung und der darüber laufenden Anwendung zu verwalten. Der Disponent legt die IConnectionBuilder für eine bestimmte, für den Transport relevante Bindung frei. Zum Beispiel legt der http-Dispatcher IConnectionBuilder basierend auf einer bestimmten Route offen, während der TCP-Dispatcher ein IConnectionBuilder basierend auf einer IP-Adresse und einem Port bereitstellt.

Anwendungen/Middleware/Frameworks

Im Zentrum dieser Arbeit steht ein neuer Satz von Primitiven, die eine zugrunde liegende Verbindung darstellen:

```C#
öffentliche abstrakte Klasse ConnectionContext
{
öffentliche abstrakte Zeichenfolge ConnectionId { get; einstellen; }

public abstract IFeatureCollection Features { get; }

public abstract IDuplexPipe Transport { get; set; }

public abstract IDictionary<object, object> Items { get; set; }

}

```C#
public interface IConnectionIdFeature
{
    string ConnectionId { get; set; }
}

```C#
öffentliche Schnittstelle IConnectionTransportFeature
{
IDuplexPipe-Transport { get; einstellen; }
}

```C#
public interface IConnectionItemsFeature
{
    IDictionary<object, object> Items { get; set; }
}

Das ConnectionContext ist der "HttpContext" des Verbindungsuniversums. Es ist eine Abstraktion, die eine dauerhafte Verbindung in irgendeiner Form darstellt. Das könnte
eine TCP-Verbindung, eine Websocket-Verbindung oder etwas Hybrideres sein (wie eine Verbindung, die über ein Nicht-Duplex-Protokoll implementiert wird, wie vom Server gesendete Ereignisse + HTTP-Posts). Die Feature-Sammlung
gibt es aus dem gleichen Grund es auf dem HttpContext , der Server oder verschiedene "Middleware" können Funktionen hinzufügen, erweitern oder entfernen
aus der Verbindung, die die zugrunde liegende Abstraktion bereichern kann. Die 2 erforderlichen Funktionen sind IConnectionTransportFeature und IConnectionIdFeature .

Als nächstes führen wir die Abstraktion zum Ausführen einer Verbindung ein.

```C#
öffentlicher Delegat Aufgabe ConnectionDelegate(ConnectionContext-Verbindung);

The `ConnectionDelegate` represents a function that executes some logic per connection. That `Task` return represents the
connection lifetime. When it completes, the application is finished with the connection and the server is free to close it.

In order to build up a pipeline, we need a builder abstraction and a pipeline. The `IConnectionBuilder` (similar to the `IApplicationBuilder`) represents
a sockets pipeline. The middleware signature is `Func<ConnectionDelegate, ConnectionDelegate>` so callers can decorate the next `ConnectionDelegate`
in the chain similar to http middleware in ASP.NET Core.

```C#
public interface IConnectionBuilder
{
    IServiceProvider ApplicationServices { get; }

    IConnectionBuilder Use(Func<ConnectionDelegate, ConnectionDelegate> middleware);

    ConnectionDelegate Build();
}

Dies sind die grundlegenden Bausteine ​​für den Aufbau verbindungsorientierter Anwendungen. Dies wird im Microsoft.AspNetCore.Connections.Abstractions- Paket gespeichert.

Dieses Refactoring wird einige Dinge ermöglichen:

  • Die ASP.NET Core-Implementierung von Kestrel wird auf dieser neuen Infrastruktur neu platziert, was bedeutet, dass sie vollständig von Kestrel entkoppelt ist.
  • Die Verbindungsadapterpipeline von Kestrel wird geändert, um stattdessen IConnectionBuilder verwenden. Dies bedeutet, dass Dinge wie TLS , Windows-Authentifizierung und Verbindungsprotokollierung separate Middleware-Komponenten sein können.
  • SignalR wird darauf aufbauen, sodass SignalR auf jeder verbindungsbasierten Infrastruktur ausgeführt werden kann.

Transporte

Transporte sind dafür verantwortlich, die anfängliche IFeatureCollection Implementierung für die Verbindung bereitzustellen und der Anwendung einen Bytestrom bereitzustellen.

Libuv und System.Net.Sockets

Heute haben wir 2 Transportimplementierungen, die sich in Kestrel befinden, eine System.Net.Sockets- und eine libuv-Implementierung. Wir planen, diese 2 beizubehalten, da sie beide unterschiedliche Funktionen bieten. Libuv kann auf Datei-Handles, Named Pipes, Unix-Domain-Sockets und TCP-Sockets lauschen, während System.Net.Sockets nur eine TCP-Socket-Implementierung (und Unix-Domain-Sockets) hat.

WebSockets

Wir möchten es Menschen ermöglichen, Websocket-basierte Frameworks zu erstellen, ohne sich mit Details auf niedriger Ebene wie Verbindungsmanagement und Pufferung zu befassen. Als solches stellen wir einen Web-Socket-Transport bereit, der diese Verbindungsprimitive verfügbar macht. Dies ist derzeit im Microsoft.AspNetCore.Http.Connectons- Paket enthalten.

Andere HTTP-Transporte

SignalR hat in der Vergangenheit mehrere Transportimplementierungen für Browser bereitgestellt, die keine Websockets unterstützten. Dies sind keine Vollduplex-Transporte, sondern werden als solche durch Roundtriping einer Verbindungs-ID über http-Anfragen implementiert. Wir werden auch Implementierungstransporte für lange Abfragen und vom Server gesendete Ereignisse bereitstellen. Diese Implementierungen erfordern eine spezielle Clientbibliothek, die das zugrunde liegende Nicht-Duplex-Protokoll versteht. Diese sind derzeit in den Paketen Microsoft.AspNetCore.Http.Connectons und Microsoft.AspNetCore.Http.Connectons.Client enthalten .

QUIC

QUIC ist ein schnell aufkommender Standard, der die wahrgenommene Leistung von verbindungsorientierten Webanwendungen verbessern soll, die derzeit TCP verwenden. Wenn QUIC auf den Markt kommt, möchten wir es mit der gleichen Abstraktion unterstützen können.

Disponenten

ASP.NET Core

ASP.NET Core dient als Basis für unseren HTTP-Dispatcher. Es wird eine RequestDelegate Implementierung geben, die als Dispatcher auf der Grundlage des Routings dient.

```C#
Verwenden von Microsoft.AspNetCore.Builder;
Verwenden von Microsoft.AspNetCore.Hosting;
Verwenden von Microsoft.Extensions.DependencyInjection;
Verwenden von SocketsSample.EndPoints;
Verwenden von SocketsSample.Hubs;

Namespace SocketsSample
{
öffentliche Klasse Startup
{
public void ConfigureServices(IServiceCollection-Dienste)
{
Dienste.AddConnections();
}

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseConnections(routes =>
        {
            // Handle mqtt connections over websockets on the /mqtt path
            routes.MapWebSocket("mqtt", connectionBuilder =>
            {
                connectionBuilder.UseMQTT<MQTTHandler>();
            });

            // Handle SignalR chat connections on the /chat path (multiple transports)
            routes.MapConnections("chat", connectionBuilder =>
            {
                connectionBuilder.UseSignalR<Chat>();
            });
        });
    }
}

}

### Kestrel

Kestrel was originally built as an http server for ASP.NET Core. Since then it's evolved to into a bunch of separate components but has still been hyper focused on http scenarios. As part of this work, there are further refactorings that will happen and kestrel will serve as the generic sockets server that will support multiple protocols.  We want to end up with layers that look something like this:

- **Microsoft.AspNetCore.Server.Kestrel.Core** - Dispatcher implementation
- **Microsoft.AspNetCore.Server.Kestrel.Https** - Deprecate this package in favor of (**Microsoft.AspNetCore.Protocols.Tls**)
- **Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions** - Abstractions for plugging different transports into kestrel
- **Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv** - Libuv transport (tcp, pipes, unix sockets)
- **Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets** - System.Net.Sockets transport
- **Microsoft.AspNetCore.Server.Kestrel** - Meta package for ASP.NET Core to avoid breaking changes

We should introduce the following packages:

- **Microsoft.AspNetCore.Protocols.Http** - Http `ConnectionDelegate` middleware
- **Microsoft.AspNetCore.Protocols.Http2** - Http2 `ConnectionDelegate` middleware (do we merge Http and Http2?)
- **Microsoft.AspNetCore.Protocols.Tls** - TLS `ConnectionDelegate` middleware

Here's what the Kestrel for TCP could look like wired up to the generic host:

```C#
var host = new HostBuilder()
            .ConfigureServer(options =>
            {
                // Listen on (*, 5001), then get access to the ISocketBuilder for this binding
                options.Listen(IPAddress.Any, 5001, connectionBuilder =>
                {
                   // This is the SignalR middleware running directly on top of TCP
                   connectionBuilder.UseHub<Chat>();
                });

                // Listen on (localhost, 8001), then get access to the ISocketBuilder for this binding
                options.Listen("localhost", 8001, connectionBuilder =>
                {
                   // Accept connections from an IOT device using the MQTT protocol
                   connectionBuilder.UseMQTT<MQTTHandler>();
                });

                options.Listen("localhost", 5000, connectionBuilder => 
                {
                    // TLS required for this end point (this piece of middleware isn't terminal)
                    connectionBuilder.UseTls("testCert.pfx", "testPassword");

                    // ASP.NET Core HTTP running inside of a Connections based server
                    connectionBuilder.UseHttpServer(async context =>
                    {
                        await context.Response.WriteAsync("Hello World");
                    });
                });
            })
            .Build();

host.Run();
area-servers servers-kestrel 🥌 Bedrock

Hilfreichster Kommentar

Es wäre wirklich cool, auch auf der Client-Seite etwas Äquivalentes zu Transports zu haben, so dass Sie im Grunde einen abstrakteren HttpClient mit einem umschaltbaren zugrunde liegenden Transportmechanismus haben könnten

Alle 126 Kommentare

Es wäre wirklich cool, auch auf der Client-Seite etwas Äquivalentes zu Transports zu haben, so dass Sie im Grunde einen abstrakteren HttpClient mit einem umschaltbaren zugrunde liegenden Transportmechanismus haben könnten

@davidfowl was halten Sie von Leistungseinbußen nach der Einführung einer solchen Abstraktion?

@davidfowl Tolle Arbeit! Ich habe nur ein Anliegen...

Da die Abstraktionen nicht nur aspnet sein werden, meinen Sie nicht, dass wir statt Microsoft.AspNetCore.Sockets.Abstractions nur Microsoft.Sockets.Abstractions für die Kernabstraktionen verwenden könnten?

Ich stimme zu, dass Kestrel- und AspNet-Abstraktionen die entsprechenden Namen haben sollten, aber ich denke, diese Abstraktionen sind sehr ... Abstrahiert und wie Sie erwähnt haben, sind sie dazu da, sehr niedrige Primitive zu verbinden und zu verwalten.

Gute Arbeit! Sich freuen auf es! :)

Ähnlich würde Microsoft.AspNetCore.Sockets.Tls => Microsoft.Sockets.Tls Sinn machen, aber ich möchte das Feature mehr als einen Namen.

@davidfowl Was wäre, wenn wir Daten von USB- oder seriellen Ports anstelle von Steckdosen lesen müssten, wäre dies ein Szenario, in dem wir einen bestimmten Transport erstellen müssten?

@dls314

aber ich will das Feature mehr als einen Namen.

Ich auch. Aber ich hätte gerne die Paketsemantik _klarer_. Besser jetzt vorschlagen als nach der Veröffentlichung :)

@shaggygi

Was wäre, wenn wir Daten von USB- oder seriellen Ports anstelle von Sockets lesen müssten, wäre dies ein Szenario, in dem wir einen bestimmten Transport erstellen müssten?

Ich denke, das ist der Zweck der Transporte.

Zumindest habe ich das aus diesem Teil verstanden:

Transports stellen eine Implementierung einer IFeatureCollection bereit, die die zugrunde liegende Verbindungssemantik implementiert .

Bedeutet das, dass Sie den Nachrichtentransport (msmq, rabbitMq, kafka) weiter unten im Stack verschieben könnten? Ich nehme an, diese Transporte würden auf derselben Abstraktionsebene wie SignalR sitzen ....

@aL3891

Es wäre wirklich cool, auch auf der Client-Seite etwas Äquivalentes zu Transports zu haben, so dass Sie im Grunde einen abstrakteren HttpClient mit einem umschaltbaren zugrunde liegenden Transportmechanismus haben könnten

Ich habe auch über eine Kundengeschichte nachgedacht, die dazu passt. SignalR hat die Anfänge davon, aber ich habe es aus dieser Spezifikation herausgelassen.

@galversribeiro

Da die Abstraktionen nicht nur aspnet sein werden, meinen Sie nicht, dass wir anstelle von Microsoft.AspNetCore.Sockets.Abstractions nur Microsoft.Sockets.Abstractions für die Kernabstraktionen verwenden könnten?

Dies ist etwas, womit wir in der Vergangenheit zu kämpfen hatten, aber AspNetCore bedeutet mehr als nur unseren bestehenden HTTP-Stack, es ist der Server-Stack im Allgemeinen. Wir werden nichts in den Root-Namespace (dh Microsoft.Sockets) einfügen. Die Benennung erfordert jedoch etwas Arbeit, Sockets ist nicht großartig.

@shaggygi

@davidfowl Was wäre, wenn wir Daten von USB- oder seriellen Ports anstelle von Steckdosen lesen müssten, wäre dies ein Szenario, in dem wir einen bestimmten Transport erstellen müssten?

Ja, das wäre ein Transport.

@no1melman

Bedeutet das, dass Sie den Nachrichtentransport (msmq, rabbitMq, kafka) weiter unten im Stack verschieben könnten? Ich nehme an, diese Transporte würden auf derselben Abstraktionsebene wie SignalR sitzen ....

Ich verstehe die Frage nicht ganz. Ein Transport kann alles sein, aber ich würde nicht damit beginnen, HTTP über einen Nachrichtenbus zu implementieren 😄 .

Ich dachte nur, dass Sie die Nachrichtenwarteschlange als Transportmittel erstellen könnten, ähnlich wie bei signalR, dann sind Sie vom Mechanismus abstrahiert.

@davidfowl Nun , wenn AspNetCore jetzt zu einer Referenz für alle Servertechnologien in .Net wird und nicht mehr nur für den Webstack, bin ich dafür! :)

Ich bin zutiefst verärgert über das völlige Fehlen von Hinweisen auf The Flintstones in dieser Ausgabe.

Wenn AspNetCore jetzt zu einer Referenz für alle Servertechnologien in .Net wird und nicht mehr nur für den Webstack, bin ich dafür! :)

Asynchrone Bereitstellungsleistung

@no1melman

Ich dachte nur, dass Sie die Nachrichtenwarteschlange als Transportmittel erstellen könnten, ähnlich wie bei signalR, dann sind Sie vom Mechanismus abstrahiert.

SignalR machte keine Nachrichtenwarteschlange zum Transport, das waren grundlegend andere Abstraktionen.

@davidfowl

Die Benennung erfordert jedoch etwas Arbeit, Sockets ist nicht großartig.

Microsoft.AspNetCore.Bungholes

Ich hätte wirklich nichts gegen einen besseren Namen, kürzer und ohne Verwirrung zu alter Full-Framework-Technologie für AspNetCore. Vor allem, wenn es sich um den Referenznamen für den Server-Stack im Allgemeinen handelt.

In Bezug auf den Namen stimme ich zu, dass das Entfernen von "AspNetCore" eine gute Idee ist, wenn man bedenkt, wie niedrig und allgegenwärtig diese API wäre.

Ich denke, das passendste Schlüsselwort, um es zu beschreiben, ist "Netzwerk".
Also vielleicht Microsoft.Network?
Oder einfach Microsoft.Net (wie System.Net), aber es klingt wie "Microsoft .NET" :)

Microsoft.Netzwerk

Nun... es wäre nicht ganz richtig, die Transport-Abstraktion ist ziemlich flexibel; Sie könnten also einen stdin/out- oder filestream-Transport schreiben und an das Programm weiterleiten oder http aus filestream lesen und schreiben. Oder frühere Beispiele könnten von einem USB- oder seriellen Port stammen ...

Transport ist wie ein Fahrer

Microsoft.Bedrock? :)
Es ist ein cooler Name imo

Könnte auch Microsoft.Transport sein, passt konzeptionell auch ganz gut

Netzwerk ist auch außerhalb der Informatik ein recht allgemeiner Begriff. Eine seiner Definitionen lautet: "Eine Gruppe oder ein System von miteinander verbundenen Menschen oder Dingen."
Wenn Sie also etwas mit etwas anderem verbinden, schaffen Sie ein Netzwerk.

Es kann sinnvoll sein, Verbindungen mit T anstelle von Strings zu identifizieren. Vielleicht IConnectionIdFeaturemit richtig vergleichbarem T?

Ich vermute, dass die ConnectionId eine Zeichenfolge ist, um die Weitergabe zu vereinfachen.
Wenn Sie es zu einem T machen, müssen Sie einen Comparer (wie Sie bereits erwähnt haben) aber auch einen Serializer bereitstellen. Das ist eine Menge Komplexität.
Können Sie ein überzeugendes Szenario aufzeigen, in dem es viel besser wäre, etwas anderes als eine Zeichenfolge zu verwenden?

Es kann sinnvoll sein, Verbindungen mit T anstelle von Strings zu identifizieren. Vielleicht IConnectionIdFeature mit richtig vergleichbarem T?

Sinnvoll... Würde Zuordnungen mit unnötigen .ToString() Aufrufen vermeiden.

Socket Allgemeinen einen sehr fokussierten Einsatz; könnte es allgemeiner sein wie Connection ? (Auch passend zu ConnectionContext ), von denen Socket einer der vielen Verbindungstypen sein kann.

z.B

public delegate Task ConnectionDelegate(ConnectionContext connection);
public interface IConnectionBuilder
{
    IServiceProvider ApplicationServices { get; }
    IConnectionBuilder Use(Func<ConnectionDelegate, ConnectionDelegate> middleware);
    ConnectionDelegate Build();
}

Ich mag @benaadams Connection-Vorschlag. Was ist mit dem Namensraum System.IO.Connection?

Können Sie ein überzeugendes Szenario aufzeigen, in dem es viel besser wäre, etwas anderes als eine Zeichenfolge zu verwenden?

Ich bin mir nicht sicher, ob ich das kann. Mein Gedanke ist, dass die Verbindungs-ID oft als Raute verwendet werden könnte und mit etwas T könnte man ohne einen string.GetHashCode Aufruf davonkommen.

Wenn nicht T, wie wäre es mit int?

Ich mag @benaadams Connection-Vorschlag. Was ist mit dem Namensraum System.IO.Connection?

Mit System.IO.Connections die Klassenmehrdeutigkeit des gleichnamigen Namespace vermeiden?

Können Sie ein überzeugendes Szenario aufzeigen, in dem es viel besser wäre, etwas anderes als eine Zeichenfolge zu verwenden?

und

Mein Gedanke ist, dass die Verbindungs-ID oft als Hash-Schlüssel verwendet werden könnte und mit etwas T könnte man ohne einen string.GetHashCode-Aufruf auskommen

Wenn Sie eine Hash-Funktion mit diesem Wert verwenden und Ihren eigenen T Typ als ID verwenden, liegt es in Ihrer Verantwortung, GetHashCode() wie überall sonst zu überschreiben, was Sie möchten und möchten Kollisionen vermeiden. Ich verstehe nicht, warum wir string , int oder was auch immer erzwingen müssen.

Warum lassen Sie den Benutzer nicht den gewünschten Typ verwenden?

Auch ja, @benaadams Vorschlag sieht toll aus. Durch die Verwendung von Socket erwartet der Benutzer eine sehr spezifische Semantik, während Connection abstrakter ist und besser in den Kontext dieser Abstraktionen passt.

Können Sie ein überzeugendes Szenario aufzeigen, in dem es viel besser wäre, etwas anderes als eine Zeichenfolge zu verwenden?

Man könnte argumentieren, dass byte[] in einigen Fällen besser wäre, wenn Sie es mit IP-Adressen zu tun haben, wenn nicht T, vielleicht ist das eine Option

Ein weiterer Grund, warum etwas anderes als ein String schön wäre, ist, wenn Sie mehrere Komponenten für die Verbindung haben (wie eine IP und einen Port), ich meine, Sie können das natürlich als String codieren, aber dann muss das analysiert werden, wenn es wo ist möglich, T als "Adresse" zu haben Es würde viel Flexibilität eröffnen

T ConnectionId macht es ein bisschen allgemein böse

public abstract class ConnectionContext<T>
{
    public abstract T ConnectionId { get; set; }
    public abstract IFeatureCollection Features { get; }
    public abstract IPipe Transport { get; set; }
}

public interface IConnectionIdFeature<T>
{
    T ConnectionId { get; set; }
}

public interface IConnectionTransportFeature
{
    public abstract PipeFactory PipeFactory { get; set; }
    public abstract IPipe Transport { get; set; }
}

public delegate Task ConnectionDelegate<T>(ConnectionContext<T> connection);

public interface IConnectionBuilder<T>
{
    IServiceProvider ApplicationServices { get; }
    IConnectionBuilder Use(Func<ConnectionDelegate<T>, ConnectionDelegate<T>> middleware);
    ConnectionDelegate<T> Build();
}

Außerdem gibt es keine Durchsetzung der Kompilierungszeit, die dazu führt, dass T in IConnectionIdFeature mit allem anderen übereinstimmt; obwohl Sie es jetzt überall brauchen?

Auch "andere Dinge von t" können über Funktionen wie IIPAddressFeature . hinzugefügt werden

Es wird eine Schnur. Es ist einfacher und wir verwenden bereits Strings für Dinge wie die Anfrage-ID.

Wenn IConnectionTransportFeature und IConnectionIdFeature erforderliche Funktionen von ConnectionContext , warum sollten dann die Eigenschaften ConnectionId und Transport dupliziert werden?

Sehen Sie sich das Design von HttpContext . Die Eigenschaften, die auf die oberste Ebene gehoben werden, sind die am häufigsten verwendeten, die für die meisten Verbindungsimplementierungen gelten. Es ist eine Bequemlichkeit, mehr nicht. Unter dem Deckmantel legt die Implementierung dieser Eigenschaften direkt die Feature-Eigenschaften offen.

@NinoFloris

Ich hätte wirklich nichts gegen einen besseren Namen, kürzer und ohne Verwirrung zu alter Full-Framework-Technologie für AspNetCore. Vor allem, wenn es sich um den Referenznamen für den Server-Stack im Allgemeinen handelt.

Du meintest für ASP.NET nicht, AspNetCore oder? Es gibt einen Punkt, an dem Sie von der reinen Verbindungsabstraktion zum HTTP-Stack von ASP.NET Core wechseln (siehe das Beispiel "ASP.NET Core HTTP, das in ASP.NET Core Sockets ausgeführt wird"). Wie würden Sie das Bridge-Paket nennen, das die HTTP-Middleware "Verbindung" ist.

Vielleicht würde ein Markenname das Namensproblem lösen 😄.

@benaadams

Socket hat im Allgemeinen einen sehr fokussierten Einsatz; Könnte es allgemeiner sein wie Connection? (Entspricht auch dem ConnectionContext), von dem Socket einer der vielen Connection-Typen sein kann.

Ich mag das. Ich bin mir jedoch nicht sicher, ob mir der Assemblyname noch gefällt. Microsoft.AspNetCore.Connections ? Es wird an mir wachsen.

Es wird eine Schnur. Es ist einfacher und wir verwenden bereits Strings für Dinge wie die Anfrage-ID.

Macht es auch einfacher, mit Activity of System.Diagnostics zu arbeiten, zB HttpCorrelationProtocol ; byte[] du müsstest zurück zu string

Ich mag das. Ich bin mir jedoch nicht sicher, ob mir der Assemblyname noch gefällt. Microsoft.AspNetCore.Verbindungen? Es wird an mir wachsen.

Es ist die interpretierende Schicht, vielleicht:

Microsoft.AspNetCore.Protocols ?

Microsoft.AspNetCore.Protocols.Http1 - Spezifisches Http1, Http1.1-Protokoll
Microsoft.AspNetCore.Protocols.Http2 - Spezifisches HTTP2-Protokoll
Microsoft.AspNetCore.Protocols.Http - Zusammengeführtes Http1+2 (ausgehandelt)
Microsoft.AspNetCore.Protocols.Tls - TLS SocketDelegate-Middleware

Microsoft.AspNetCore.Protocol.Abstractions
Microsoft.AspNetCore.Protocol.Http
Microsoft.AspNetCore.Protocol.Tls

@davidfowl Ich mag dieses Layout am besten, aber aus

System.Collections
System.DirectoryServices.Protocols
System.Web.Services.Protocols

Einige der neuen Libs haben Protocol am Ende , für einen Protokollraum für einen einzigen Zweck, aber wenn wir hier viele haben: Plural fühlt sich für mich viel richtiger an. Vergleichsliste: https://apisof.net/catalog

@davidfowl ja, ich meinte, ASP.NET wird ziemlich überladen. Wie heißt der eigentliche Web-Framework-Teil davon heutzutage? The ASP.NET Core 2.0 Web Framework ?

Die Suche nach ASP.NET 2.0 macht jedoch großen archäologischen Spaß:
https://www.google.com/search?q=asp.net+2.0

Es stört mich, dass der Name ASP.NET Core aus 2 Teilen Plattformbezeichner (.NET und Core) und nur einem Teil "Produktname" besteht, was, anstatt tatsächlich ein guter Name für einen Server-Stack zu sein, nur ein Akronymverweis auf alte Technologie aus dem neunziger Jahre, es ist lang und schwer zu tippen, das Alter zeigt sich.

Jetzt können wir alle vermuten, dass die Marketingabteilung die Markenbekanntheit von ASP.NET mit der alten Garde liebt (was nicht beleidigend ist), und ich verstehe, dass die Verwendung des gleichen Namens diesen Leuten helfen könnte, den Übergang zu .NET Core zu finden. Aber es immer mehr zu überladen, tut niemandem einen Gefallen.

Mir fehlen genau die wenigen Marken-/Codenamen, auf die ich mich auf Personen beziehen kann, die direkt einem bestimmten Teil des größeren Stapels entsprechen. Nicht immer auf den lange überladenen Dachmarkennamen verweisen zu müssen, der mit einer genauen Beschreibung des Stapels verbunden ist.

Turmfalke ist ein sehr erfolgreiches Beispiel dafür.

Entschuldigung für die Entführung, gibt es einen bestimmten Ort, an dem ich das auf den Tisch legen kann?

Entschuldigung für die Entführung, gibt es einen bestimmten Ort, an dem ich das auf den Tisch legen kann?

Sicher, ein Problem auf aspnet/Home melden, aber ich muss ehrlich sein, ich bin mir nicht sicher, ob es etwas ändern wird. Die Tatsache, dass ASP.NET Core sogar ASP.NET Core heißt, dürfte ein deutliches Zeichen dafür sein. Es ist möglich, dass wir einige Dinge unter den Microsoft.Extensions Schirm verschieben, da es dafür anderen Stand der Technik gibt.

Sicher, ein Problem auf aspnet/Home melden, aber ich muss ehrlich sein, ich bin mir nicht sicher, ob es etwas ändern wird.

Ich mache mir keine Illusionen ;) Ich weiß, dass es nie zu einer Namensänderung kommen wird, alles was ich verlange, ist ein bisschen mehr Spezifität unter diesem prallen Regenschirm.

Vielleicht kann ASP.NET (Core) als Dachname beibehalten werden, aber Assemblys können anders aufgerufen werden. Turmfalke ist ein gutes Beispiel dafür.

Es ist einfach schwierig, solche Namen zu finden, daher können Sie am Ende Microsoft.AspNetCore.XXX als sichere Wahl verwenden.

Aber ich bin ganz für diese einzigartigen Namen. Sie sind unverwechselbar und leicht zu recherchieren/nachzuschlagen.

Vielleicht kann ASP.NET (Core) als Dachname beibehalten werden, aber Assemblys können anders aufgerufen werden. Turmfalke ist ein gutes Beispiel dafür.

Da gibt es keine Meinungsverschiedenheiten.

Es ist einfach schwierig, solche Namen zu finden, daher können Sie am Ende Microsoft.AspNetCore.XXX als sichere Wahl verwenden.

Wahrscheinlich gefällt mir der neueste Vorschlag von Protocols bisher am besten.

Aber ich bin ganz für diese einzigartigen Namen. Sie sind unverwechselbar und leicht zu recherchieren/nachzuschlagen.

Sie meinen einen Namen wie Turmfalke, aber der steht für diese unteren Schichten. Grundgestein 😄 könnte es sein, aber das führt zu zu vielen Flintstones-Referenzen.

Ich sehe kein Problem damit, dass das Kestrel-Zeug weiterhin in der AspNetCore-Nomenklatur verbleibt, da es sehr stark im Besitz des ASP.NET-Teams und Teil ihrer Plattform ist. Diese Änderung könnte die Komponenten von Kestrel etwas mehr entkoppeln, um eine weitere Abstraktionsebene hinzuzufügen, aber sie ist immer noch sehr stark im selben Team/der gleichen Plattform verwurzelt.

Ich sehe die Nomenklatur von Microsoft.Extensions als etwas, das die Nutzung durch Frameworks von mehreren Teams umfasst, sei es Web, Konsole, Windows-App oder Bibliothek.

Mein Vorschlag wäre, alles, was plattform-/frameworkunabhängig ist, nach Möglichkeit und sinnvoll in die Microsoft.Extensions.*-Nomenklatur zu verschieben.

Nebenbei bemerkt, ich wünschte eigentlich, die Host-Provider, die zum Bootstrap von Web-Apps verwendet werden, wären nicht in der AspNetCore-Arena, da es eine Service-Host-Option gibt, die mir eher wie eine plattformspezifische Implementierung erscheint, da sie nur ein Windows-System erfordert . Wäre schön, wenn es eine echte Abstraktion wäre, wenn es systemd und neu gestartete Implementierungen darunter geben könnte. Scheint, als wären diese eher auf das .NET-Ökosystem zu beziehen und stattdessen Teil von System.*. Fühlt sich komisch an, den Diensthost für einen Windows-Dienst zu verwenden, wenn er nicht webbasiert ist.

Nebenbei bemerkt, ich wünschte eigentlich, die Host-Provider, die zum Bootstrap von Web-Apps verwendet werden, wären nicht in der AspNetCore-Arena, da es eine Service-Host-Option gibt, die mir eher wie eine plattformspezifische Implementierung erscheint, da sie nur ein Windows-System erfordert . Wäre schön, wenn es eine echte Abstraktion wäre, wenn es systemd und neu gestartete Implementierungen darunter geben könnte. Scheint, als wären diese eher auf das .NET-Ökosystem zu beziehen und stattdessen Teil von System.*. Fühlt sich komisch an, den Diensthost für einen Windows-Dienst zu verwenden, wenn er nicht webbasiert ist.

Microsoft.Extensions.Hosting kommt. Aber das ist eine andere Spezifikation und ein anderer Codename (wenn ich mir einen ausdenken kann). Sehen Sie den Teaser als Teil der 2.0-Version https://github.com/aspnet/Hosting/tree/dev/src/Microsoft.Extensions.Hosting.Abstractions

Ich habe die Spezifikation mit den neuen Namen aktualisiert.

@davidfowl für das Hosten von Projektcodename/ Hostess CupCake 😄

Wo finde ich die Spezifikation?

Basierend auf der Beschreibung: "OWIN for Connections", wie wäre es mit dieser OCIN?
"Verbindungs-/Kommunikationsschnittstelle für .NET öffnen"?
Namespace: Microsoft.Ocin.

Ich hätte diesen Teil fast ausgelassen, aber ich dachte, es wäre eine gute Analogie. Ich würde es lieber nicht owin nennen, weil ASP.NET Core Abstraktionen hat, die nicht owin sind, und dies wird auch so sein.

Aber ich habe "OCIN" vorgeschlagen, das ist ein anderer Name :)

ONIN (Verbindung durch Netzwerk ersetzen) klingt besser, aber die Konnotation gefällt mir immer noch nicht.

@davidfowl

Die Benennung erfordert jedoch etwas Arbeit, Sockets ist nicht großartig.

Wir sprechen über verschiedene Arten der Client-Server-Kommunikation, warum also nicht Microsoft.AspNetCore.Communication .

Hallo, Sie erwähnten libuv/IOCP und offensichtlich einen einfachen alten Socket. Denken Sie darüber nach, RIO zu verwenden?

Vielen Dank.

@wholroyd Welche Art von Abstraktionen möchten Sie Systemd / Emporkömmling besser unterstützen?

Wir haben eine Anleitung , die zeigt, wie Sie systemd verwenden, um Ihre asp.net Core-App am Laufen zu halten und Protokolle zu verwalten. In 2.0.0 haben wir KestrelServerOptions.UseSystemd() hinzugefügt, um die Systemd-Socket-Aktivierung zu unterstützen. Was das ordnungsgemäße Herunterfahren betrifft, sendet systemd ein SIGTERM AFAIK, das vom Hosting verarbeitet wird.

Ich versuche nicht zu behaupten, wir könnten nicht mehr tun oder bessere Abstraktionen liefern. Mich interessieren nur deine Ideen.

@halter73 Wusste nichts von KestrelServerOptions.UseSystemd() . Der Teil, auf den ich mich bezog, war die Tatsache, dass es einen Diensthost gibt (unter https://github.com/aspnet/Hosting/blob/dev/src/Microsoft.AspNetCore.Hosting.WindowsServices/WebHostService.cs), aber es ist ein Framework spezifisch ( IWebHost ) und verwendet ServiceBase (Windows).

Ich mag das Hosting-Einstiegspunkt-Konzept, das in der Bibliothek verwendet wird, ich wünschte nur, es wäre abstrahiert genug, um Framework-agnostisch zu sein (eher IHost - AspNetCore könnte es dann weiter zu IWebHost abstrahieren) und eine Plattform zu werden agnostisch (Nicht-Windows). Ich denke, es würde eine Änderung an .NET selbst bedeuten, um ServiceBase auf Nicht-Windows-Systemen nutzbar zu machen - haken Sie sich nach Bedarf in Systemd/Upstartd/Windows ein.

Sinn ergeben?

Ich denke, das macht Sinn. Implementieren von Methoden wie ServicBase.OnStop oder IHost.OnStop scheint viel einfacher als Sachen zu schreiben wie diese selbst.

Ich kann ein Problem öffnen, um es anzufordern. Sollte es zu dotnet/netstandard gehen? @halter73

@wholroyd gib ihm ein paar Tage. Ich werde bald eine Spezifikation veröffentlichen.

@davidfowl glauben Sie, dass das Kestrel GitHub-Repository nach der Veröffentlichung des neuen Abstraktionsmaterials in nur KestrelServer umbenannt wird?

@shaggygi sicher

Wenn ich als Verbraucher Microsoft.AspNetCore.Protocols.Http einziehe, würde ich persönlich erwarten, dass ich http 0.x bis hin zu http2 und darüber hinaus habe. Hätte nichts dagegen, dass es ein Metapaket ist, um fortgeschrittenere Anwendungsfälle zu ermöglichen (zB: mein Dienst unterstützt nur http2). Das Zusammenführen würde für Neulinge eine angenehmere Erfahrung machen (und weniger verwirrend), imo.

Ich freue mich darauf zu sehen, wie AMQP in Zukunft dazu passt (im Allgemeinen nicht an RabbitMQ usw. gebunden)

Die Benennung erfordert jedoch etwas Arbeit, Sockets ist nicht großartig.

Wenn es um Transportabstraktion geht, sollten Sie es benennen:

Microsoft.AspNetCore.Transport(e)

@aL3891 Ich denke, wir müssen jetzt auch Kunden unterstützen.

Mir ist gerade aufgefallen, dass dies auf v2.2 verschoben wurde.
Aber wie wird dies mit dem kommenden SignalR (mit ASP.NET 2.1) kompatibel sein?

Es gibt viele Überschneidungen zwischen Bedrock und SignalR, daher wäre es ideal, wenn sie einige Abstraktionsschichten teilen.

Bearbeiten: Zum Beispiel definieren beide eine Klasse ConnectionContext , die im Grunde dasselbe tut.

Und mit "SignalR" meine ich die untergeordneten Bibliotheken, die Teil des SignalR-Repositorys sind, wie Microsoft.AspNetCore.Sockets.Abstractions .

@MuleaneEve das ist beabsichtigt. Der Plan ist, Protokollabstraktionen in SignalR zu verwenden und sockets.abstractions zu entfernen.

Wir haben heute einige Entscheidungen getroffen:

  • Wir werden die Transportschicht in 2.1 beibehalten (wie sie in 2.0 war). Wir sind der Meinung, dass es Platz gibt, um Clients zur bestehenden Abstraktion hinzuzufügen, daher möchten wir die API noch nicht in Stein gemeißelt haben. Das Schreiben eines Transports wird weiterhin möglich sein, aber die API wird sich ändern und in 2.2 öffentlich sein.
  • Dies wird ein Multi-Release-Aufwand sein. In 2.1 werden wir mehr Kestrel-Eingeweide als öffentliche API in 2.2 (HttpParser, Basisklasse für den Umgang mit Http) verfügbar machen, um den Aufbau hocheffizienter spezialisierter Server zu ermöglichen (siehe https://github.com/davidfowl/PlatformLevelTechempower/blob/ 944597f9ad196d3a333b837fb8c62a7304d5f9d2/ServerWithKestrel2.1/WebSocketConnection.cs)
  • Wir haben heute eine API-Überprüfung durchgeführt und werden einige Dinge umbenennen:

Middleware

Microsoft.AspNetCore.Connections.Http - Hat den HttpConnectionHandler (heute ist dieser intern in Kestrel)
Microsoft.AspNetCore.Connections.Tls - TLS-Verbindungs-Middleware
Microsoft.AspNetCore.Connections.Logging - Middleware für die Protokollierung von Verbindungen

Protokollabstraktionen

Microsoft.AspNetCore.Protocol.Abstractions -> Microsoft.AspNetCore.Connections.Abstractions

Verschieben Sie EndPoint in Connections.Abstractions, und benennen Sie es in ConnectionHandler um.

C# public abstract ConnectionHandler { Task OnConnectionAsync(ConnectionContext connectionContext); }

Wenn man bedenkt, wie nah wir an der Version 2.1 sind, ist dies wahrscheinlich die beste Lösung.

Bedeutet das, dass die Verbindungsschicht hier und die Sockets-Schicht in SignalR vorerst auch intern sein werden?

Übrigens gefällt mir der Name _Connections_.

Bedeutet das, dass die Verbindungsschicht hier und die Sockets-Schicht in SignalR vorerst auch intern sein werden?

Nein, es wird öffentlich.

Okay. Haben Sie sich das von mir veröffentlichte Peer-to-Peer-Beispiel angesehen ?
Ich hoffe, dass solche Szenarien unterstützt werden.

@KPixel ja, ich habe es gesehen, aber TBH Ich sehe nicht, wie Sie die Verbindungsabstraktionen verwenden möchten.

Sind die Layer Connections & Sockets (meistens) endgültig?

Ich werde dieses Beispiel und meine App neu schreiben, indem ich sie verwende, um zu sehen, wo ich feststecke.

Sind die Layer Connections & Sockets (meistens) endgültig?

Es sind jetzt alle Verbindungen und die Client-API ist nicht endgültig. Ich bin ziemlich zuversichtlich, dass die ConnectionContext-API nicht viel abwälzen wird. Wir werden jedoch weitere Dinge hinzufügen und Pakete und Namespaces umbenennen.

@KPixel Ich habe

  • Wir haben derzeit nichts für UDP- oder Nicht-Streaming-Transporte im Allgemeinen. Dies kam in der Vergangenheit auf, wurde aber nicht konkretisiert.
  • Das aktuelle API-Muster bedeutet, dass Sie zurückgerufen werden. Wenn Sie also Daten über Bindungen hinweg zusammenführen, müssen Sie den Status irgendwie weitergeben. Dazu können Sie DI oder einen anderen Zustandsfreigabemechanismus verwenden.

@davidfowl Danke fürs

Ich untersuche auch die neuen Ebenen... Morgen werde ich eine neue Ausgabe erstellen, um diese Diskussion fortzusetzen.

Grundgesteins-Update (Mittwoch, 28. März 2018)

Protokollabstraktionen (Basis-API alle öffentlich in 2.1)

  • Microsoft.AspNetCore.Connections.Abstractions

```C#
öffentliche abstrakte Klasse ConnectionContext
{
öffentliche abstrakte Zeichenfolge ConnectionId { get; einstellen; }

public abstract IFeatureCollection Features { get; }

public abstract IDictionary<object, object> Items { get; set; }

public abstract IDuplexPipe Transport { get; set; }

}

öffentliche Schnittstelle IConnectionBuilder
{
IServiceProvider ApplicationServices { get; }

IConnectionBuilder Use(Func<ConnectionDelegate, ConnectionDelegate> middleware);

ConnectionDelegate Build();

}

öffentlicher Delegat Aufgabe ConnectionDelegate(ConnectionContext-Verbindung);

öffentlicher abstrakter ConnectionHandler
{
Task OnConnectionAsync(ConnectionContext connectionContext);
}

### Remaining 2.1 work

- Figuring out how to merge use `ConnectionContext` as the client abstraction (SignalR needs this).
- Adding support for aborting the connection (a first class Abort method) semi related to the first bullet https://github.com/aspnet/KestrelHttpServer/issues/2054

### 2.2 and beyond

- Nothing specifically planned at this layer besides adding more feature interfaces

## Kestrel specific transport layer (pubternal in 2.1)

- **Microsoft.AspNetCore.Kestrel.Transport.Abstractions** - Required to implement a kestrel transport
- **Microsoft.AspNetCore.Kestrel.Transport.Libuv** - Libuv implementation
- **Microsoft.AspNetCore.Kestrel.Transport.Sockets** - Sockets implementation

3rd party implementations:

- **RedHatX.AspNetCore.Server.Kestrel.Transport.Linux** - https://github.com/tmds/kestrel-linux-transport - Native epoll transport for linux

The transport layer remains pubternal in 2.1 because we think there might be some bigger design
changes we want to make (see 2.2 and beyond for details).

## Remaining 2.1 work

We may add support for Abort on the `ConnectionContext` and will need to implement it at the transport layer.

## 2.2 and beyond

- Make the API public
- Support for clients (libuv client/sockets client)
- Potentially share abstractions for Kestrel's TCP transports and SignalR's HTTP based transports
- Design changes around who creates the Pipe (see https://github.com/aspnet/KestrelHttpServer/issues/2429)

## Kestrel Core (ASP.NET IServer implementation)

Even though the transport layer itself is pubternal in 2.1, consuming the IConnectionBuilder
from Kestrel is public. This is what our platform techempower benchmark is built on.

```C#
public class Program
{
    public static void Main(string[] args)
    {
        var host = WebHostBuilder.CreateDefaultBuilder(args)
            .UseKestrel(options =>
            {
                options.Listen(IPAddress.Loopback, 9001, builder =>
                {
                    // Log all of the bytes as they are sent and received
                    builder.UseConnectionLogging();

                    // Connection builder API is exposed here
                    builder.UseConnectionHandler<ChatHandler>();
                });

                options.Listen(IPAddress.Any, 8004, builder => 
                {
                    // Using hubs bound to TCP
                    builder.UseHub<Chat>();
                });
            })
            .UseContentRoot(Directory.GetCurrentDirectory())
            .UseStartup<Startup>()
            .Build();

        host.Run();
    }
}

2.2 und darüber hinaus

  • Nehmen Sie die entsprechenden Änderungen vor, damit die Verbindungs-Middleware beim Herunterfahren ordnungsgemäß funktioniert
    und Verbindungsmanagement.
  • Veralten Sie Verbindungsadapter und ersetzen Sie sie durch Verbindungs-Middleware.
  • Entkoppeln Sie den TCP-Stack von Kestrel von der IServer-Implementierung von ASP.NET, was die direkte Verwendung im HostBuilder (nicht im WebHostBuilder) ermöglicht.

Verbindungs-Middleware

  • Microsoft.AspNetCore.Connections.Http - Hat den HttpConnectionHandler
  • Microsoft.AspNetCore.Connections.Tls - TLS-Verbindungs-Middleware
  • Microsoft.AspNetCore.Connections.Logging - Middleware für die Protokollierung von Verbindungen

Dies sind die Verbindungsadapter, die heute in Kestrel vorhanden sind und auf Middleware portiert werden müssen.

2.2 und darüber hinaus

  • Implementieren Sie die Verbindungs-Middleware tatsächlich

SignalR

  • Microsoft.AspNetCore.Http.Connections - ASP.NET Core HTTP-basierte Transporte und API zum Bereitstellen von IConnectionBuilder
  • Microsoft.AspNetCore.Http.Connections.Common – Gemeinsamer Code zwischen Server und Client
  • Microsoft.AspNetCore.Http.Connections.Client - Verbindungsabstraktion über die 3 Transporte (Websockets, LongPolling, ServerSentEvents)

```C#
öffentliche Klasse Startup
{
public void ConfigureServices(IServiceCollection-Dienste)
{
Dienste.AddConnections();
}

public void Configure(IApplicationBuilder app)
{
    app.UseConnections(routes =>
    {
        routes.MapConnections("/chat", builder => 
        {
            // Connection builder API is exposed here
            builder.UseConnectionHandler<ChatHandler>();
        });

        routes.MapConnections("/mqtt", builder => 
        {
            // Log all of the bytes as they are sent and received
            builder.UseConnectionLogging();

            builder.UseConnectionHandler<MQTTHandler>(options => 
            {
                // Restrict to websockets only
                options.Transports = TransportType.WebSockets;

                // Specify the subprotocol
                options.SubProtocol = "mqttv3.1";
            });
        });

        // Shortcut to directly map a single connection handler
        routes.MapConnectionHandler<NotificationHandler>("/notifictions");
    });
}

}

```C#
var connection = new HttpConnection(new Uri("http://localhost:8001"));
await connection.StartAsync();

var result = await connection.Transport.Input.ReadAsync();
await connection.Transport.Output.WriteAsync(result.Buffer.ToArray());

await connection.DisposeAsync();

Verbleibende Arbeit

  • Führen Sie die Paketumbenennungen durch (in Bearbeitung)
  • ConnectionContext als Client-API verwenden (Vereinheitlichung des Client- und Server-Verbindungsobjekts)

2.2 und darüber hinaus

  • Erstklassige TCP-Unterstützung

    • SignalR funktioniert serverseitig mit reinem TCP in 2.1 zusätzlich zu Kestrels vorhandenem

      Verbindungsbauer.

    • Wir brauchen hier eine erstklassige Kundentransportgeschichte. Weitere Informationen finden Sie im Abschnitt Kestrel.Core Transport Abstractins.

  • Eventuell andere Transporte, wo es Sinn macht.

SignalR 2.2 -> Erstklassige TCP-Unterstützung

Ich möchte das gerne früher haben, um einen mqtt-Transport zu starten, aber es sieht so aus, als ob das etwas länger warten muss

Ich möchte das gerne früher haben, um einen mqtt-Transport zu starten, aber es sieht so aus, als ob das etwas länger warten muss

Transport wofür genau? Die SignalR-TCP-Unterstützung ist eher eine offizielle Aussage, wir arbeiten nicht explizit daran für 2.1, aber sie wird funktionieren und es wird keine Client-Unterstützung geben (Sie können Nutzlasten von einem benutzerdefinierten TCP-Client senden). Wir liefern jedoch die APIs aus, die für die Implementierung eines serverseitigen Protokolls erforderlich sind (Client auf dem Weg).

Ich möchte einen mqtt-Transport für Signalr erstellen, damit ich das Hub-Programmiermodell als meinen mqtt-Broker verwenden kann

Ich möchte einen mqtt-Transport für Signalr erstellen, damit ich das Hub-Programmiermodell als meinen mqtt-Broker verwenden kann

Nur um es klarzustellen: Websockets oder TCP ist der Transport richtig? Sie möchten Hub-Aufrufe mit Mqtt-Paketen beschreiben? Es hört sich so an, als ob Sie ein IHubProtocol schreiben möchten
In SignalR ist dies ein benutzerdefiniertes Hub-Protokoll https://github.com/aspnet/SignalR/blob/2f9942e1f20ff6b76542900eadd5828a2b61957a/src/Microsoft.AspNetCore.SignalR.Common/Internal/Protocol/IHubProtocol.cs. Aber wenn du das noch klarstellen könntest wäre das super

@davidfowl Ich bin
Papierdesign:
C# interface IIOService { Task<IDuplexPipe> ConnectTcpAsync(string host, int port); IAsyncDisposable AcceptOnTcp(IPAddress address, int port, Action<IDuplexPipe> onAccept); }
Verwandte (aus der Implementierungsperspektive) ist dieses offene Problem https://github.com/aspnet/KestrelHttpServer/issues/1587 , damit Endpunkte von denselben LibuvThreads behandelt werden können.

Sicher, da die API-Form für die Transportabstraktionen noch nicht in Stein gemeißelt ist (pubternal APIs sind in dieser Kategorie), können wir das Design iterieren. Diese spezielle API-Form halte ich jedoch für zu minimal, Transporte müssen mehr als nur eine Duplex-Pipe kommunizieren.

Ich weiß absolut, dass ich hier dicht bin, aber ich bin etwas verwirrt, was es bedeutet, einen TCP-Transport und / oder ein benutzerdefiniertes Protokoll in Kestrel zu haben (da ich Kestrel immer als TCP / HTTP betrachtet habe).

In diesem Szenario, in dem ich mich entschieden habe, den TCP-Transport zu verwenden und ein benutzerdefiniertes Protokoll zu schreiben (in diesem Beispiel für den Moment ohne SignalR), welche Arbeit macht Kestrel selbst? Ist dieses Szenario der Verwendung des alten TcpListener ähnlich, oder geben mir diese Abstraktionen etwas mehr als das?

Sorry für die dumme Frage, alle.

In diesem Szenario, in dem ich mich entschieden habe, den TCP-Transport zu verwenden und ein benutzerdefiniertes Protokoll zu schreiben (in diesem Beispiel für den Moment ohne SignalR), welche Arbeit macht Kestrel selbst?

Kestrel ist der Klebstoff, es verkabelt die Transportschicht, kümmert sich um das Verbindungsmanagement und Zeitüberschreitungen, das anmutige und unangemessene Herunterfahren von Verbindungen.

Ist dieses Szenario der Verwendung des alten TcpListener ähnlich, oder geben mir diese Abstraktionen etwas mehr als das?

Die Verbindungsabstraktionen entkoppeln Sie vom zugrunde liegenden Transport. Ihr Protokollparsing nimmt nur Bytes aus der Pipeline und es spielt keine Rolle, woher diese Bytes kommen. Sie sind nicht an TCP gebunden, was bedeutet, dass Sie Ihre Protokoll-Parsing-Schicht problemlos mit einer einfachen In-Memory-Pipe testen können, die Bytes manuell schiebt (im Grunde beim Speichertransport).

Klingt super David, danke!

Ich habe an einem Tutorial für Pipelines and Connections gearbeitet und stecke fest, weil es derzeit schwierig ist, die Connections-Bibliothek zu erklären, ohne sie an SignalR oder Kestrel zu binden.

image

Derzeit befindet sich der TCP-Transport in Kestrel, der WebSockets-Transport (und andere) in SignalR.
Und sie haben ihre eigenen internen Disponenten.

Wenn ich Project Bedrock richtig verstehe, besteht der nächste Schritt in 2.2 darin, diese Transporte und Dispatcher so umzugestalten, dass wir Anwendungen entwickeln können, die sie verwenden, ohne von SignalR oder Kestrel abhängig zu sein. Richtig?

Turmfalken wird aus meiner Sicht immer benötigt, aber es wird eine bessere Schichtung darüber geben. damit kannst du tun:
tcp > [TLS] > http > aspnet
tcp > [TLS] > http > signalr
tcp > [TLS] > mqtt > [signalr]
tcp > dein eigenes Ding

Ich habe an einem Tutorial für Pipelines and Connections gearbeitet und stecke fest, weil es derzeit schwierig ist, die Connections-Bibliothek zu erklären, ohne sie an SignalR oder Kestrel zu binden.

Das sind die 2 Gastgeber, was erwartest du? Dispatcher müssen vorhanden sein, damit Sie das auf Verbindungen aufbauende Framework tatsächlich ausführen können. Der dritte Dispatchertyp ist die manuelle in der Speichertestverbindung. Wo Sie Ihren Verbindungshandler neu einrichten und einen Test bestehen ConnectionContext .

Derzeit befindet sich der TCP-Transport in Kestrel, der WebSockets-Transport (und andere) in SignalR.
Und sie haben ihre eigenen internen Disponenten.

Das ist richtig und beabsichtigt. Es könnte auch einen reinen Websockets-Dispatcher geben, aber niemand brauchte ihn, also wurde es nicht getan.

Wenn ich Project Bedrock richtig verstehe, besteht der nächste Schritt in 2.2 darin, diese Transporte und Dispatcher so umzugestalten, dass wir Anwendungen entwickeln können, die sie verwenden, ohne von SignalR oder Kestrel abhängig zu sein. Richtig?

Nicht ganz, das hat definitiv geringere Priorität als die anderen Dinge. Der Hauptpunkt von 2.2 besteht darin, die Transportabstraktion für Kestrel zu vervollständigen und es richtig öffentlich zu machen (sowohl für Clients als auch für Server).

@KPixel wo

@JanEggers

Turmfalken wird aus meiner Sicht immer benötigt, aber es wird eine bessere Schichtung darüber geben. damit kannst du tun:
tcp > [TLS] > http > aspnet
tcp > [TLS] > http > signalr
tcp > [TLS] > mqtt > [signalr]
tcp > dein eigenes Ding

Das ist richtig, wir werden sehen, ob die Kestrel-Transportschicht am Ende eigenständig ist oder nicht, wenn wir mit dem Design fertig sind, aber das wird ein zusätzlicher Bonus für gutes Design sein.

Wir werden sehen, ob die Kestrel-Transportschicht am Ende eigenständig ist

Das meinte ich im Grunde.
Damit hast du meine Frage beantwortet :)

Jetzt, da Microsoft.AspNetCore.Connections.Abstractions veröffentlicht wird, habe ich eine Frage:

Warum hängt es von Microsoft.AspNetCore.Http.Features ab?

Wenn es für normales TCP verwendbar sein sollte, warum brauche ich http-Funktionen?

Gibt es auch einen Code für die tls-Middleware / welches Repository / wie lautet der Paketname?

und schließlich wollte ich die neue Abstraktion für mqttnet verwenden. Der Autor dieser Bibliothek befasst sich mit der Aktualisierung der aspnetcore-Abhängigkeit auf 2.1. Also dachte ich darüber nach, nur von System.IO abhängig zu sein, Pipelines wäre eine gute Idee, da dies abwärtskompatibel zu Netstandard 1.3 ist und Kestrel überhaupt nicht erforderlich ist. Die Frage ist also: Wird die tls-Schicht nur von System.IO.Piplines abhängen oder wird sie auf der Verbindungsabstraktion sitzen? Und wenn es von Connections abhängt, besteht die Möglichkeit, dass Connection Abstractions auch NetStandard1.3-kompatibel sein könnten, vielleicht in einer späteren Version von sich selbst?

Warum hängt es von Microsoft.AspNetCore.Http.Features ab?

IFeatureCollection. Schade, aber das war das kleinere Übel:

  1. Erstellen Sie eine neue Abstraktion, die eine Feature-Sammlung ist, aber keine IFeatureCollection
  2. Geben Sie forward zu einer anderen Assembly ein (dies ist immer noch eine Option), aber es würde den Namespace nicht reparieren
  3. Verweisen Sie einfach auf die Baugruppe.

Wir wählten 3. 2 ist immer noch auf weitgehend bruchsichere Weise möglich, aber es würde den Typnamen nicht korrigieren (Namespace wäre http).

Gibt es auch einen Code für die tls-Middleware / welches Repository / wie lautet der Paketname?

Es existiert noch nicht. Es wird in diesem Repository sein.

und schließlich wollte ich die neue Abstraktion für mqttnet verwenden. Der Autor dieser Bibliothek befasst sich mit der Aktualisierung der aspnetcore-Abhängigkeit auf 2.1. Also dachte ich darüber nach, nur von System.IO abhängig zu sein, Pipelines wäre eine gute Idee, da dies abwärtskompatibel zu Netstandard 1.3 ist und Kestrel überhaupt nicht erforderlich ist.

Mit ASP.NET Core 2.1 meint der Autor netstandard 2.0 richtig?

Die Frage ist also: Wird die tls-Schicht nur von System.IO.Piplines abhängen oder wird sie auf der Verbindungsabstraktion sitzen? Und wenn es von Connections abhängt, besteht die Möglichkeit, dass Connection Abstractions auch NetStandard1.3-kompatibel sein könnten, vielleicht in einer späteren Version von sich selbst?

Verbindungsabstraktionen. Vielleicht, aber wir riefen dazu auf, mindestens den Netstandard 2.0 anzustreben.

Mit ASP.NET Core 2.1 meint der Autor netstandard 2.0 richtig?

Wenn ich von Connection.Abstractions abhängig bin, müssen die Consumer dieses Pakets Kestrel auf 2.1 aktualisieren, sonst gibt es keine Listenoptions zum Hooken des Connectionhandlers oder habe ich etwas übersehen? Ich kann dies nicht auf Kestrel 2.0 tun, oder kann ich?
https://github.com/JanEggers/MQTTnet/blob/732ede1f2475610b8a181635a571210716a3da9f/Tests/MQTTnet.TestApp.AspNetCore2/Program.cs#L16

https://github.com/JanEggers/MQTTnet/blob/732ede1f2475610b8a181635a571210716a3da9f/Frameworks/MQTTnet.AspnetCore/ConnectionBuilderExtensions.cs#L7 -L9

thx für die erklärung!

Sie benötigen ASP.NET Core 2.1, um ConnectionHandler mit Kestrel zu verwenden.

Ich denke darüber nach, einen FTP-Server mit der API in Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions , weil er (fast) perfekt zusammenpasst. Wie wird sich diese API in 2.2 ändern? Wird es für die Entwicklung eines Nicht-HTTP-Servers weniger (oder mehr) nützlich sein?

@fubar-coder Ich würde Kestrel dafür direkt verwenden, nicht die Transportabstraktionsschicht.

@davidfowl Was wäre der Ausgangspunkt für die Entwicklung eines Nicht-HTTP-Dienstes? Der Grund, warum ich über M.ANC.S.K.Transport.Abstractions nachgedacht habe, war, all diesen HTTP(S)-spezifischen Code zu vermeiden.

Ich versuche, genau das in den Griff zu bekommen, was Sie implementieren müssen, um die Verbindungsabstraktion in Kestrel zu verwenden. Wenn man sich @JanEggers

@b3nt0 das wars, alles andere hängt von Ihrem Protokoll oder der Bibliothek ab, die Sie anpassen. Da Sie nicht einmal den ConnectionContext benötigen, können Sie den gesamten Code in die ConnectionHandler-Klasse einfügen. Was ich am meisten vermisse, ist der Client-Support, der als 2.2 angekündigt wurde, um Sachen von den Signalr-Samples nach Polyfill zu kopieren

@davidfowl Ich möchte einige spezifische Informationen von der Transportschicht erhalten. Zum Beispiel einige Informationen über Socket.Handle und bringen Sie sie auf die Anwendungsschicht. Kann ich das mit diesem Modell machen? Oder muss ich einen eigenen http-Server mit http-Parsern und viel anderer Arbeit erstellen?

Etwas mehr zur Bewerbung:
Ich möchte HttpRequests abhören, einige spezifische Informationen von eingehenden Socket-Verbindungen abrufen und abhängig von diesen Informationen Anfragen an verschiedene Webapi-Anwendungen weiterleiten, dann eine Antwort von Webapi erhalten und sie zurück zum Client leiten.
Ich verstehe, dass es ein sehr spezieller Fall ist, aber es ist sehr wichtig für mich.

scheme

Pseudocode

var _incomingConnection = await HandleConnection();

var _info = GetSpecificInfo(incomingConnection.IncomingSocket.Handle);

while (true)
{
    var httpRequest = await _incomingConnection.ReadHttpRequest();

    switch (_info)
    {
        case _:
            await SendHttpRequestToWebApi5001(httpRequest);
            break;
        case _:
            await SendHttpRequestToWebApi5002(httpRequest);
            break;
    }

    var response = await ReceiveResponse();
    await SendHttpResponseToClient(response);
}

Klar, welche Informationen möchten Sie aus dem Griff bekommen?

@davidfowl sehr schnell danke dafür :)
In unserem Projekt verwenden wir ein debian-ähnliches Betriebssystem mit benutzerdefinierten Sicherheitsrichtlinien über Standard-Linux. Es verwendet ein benutzerdefiniertes Subsystem, um Sicherheitslabels für Benutzer, Dateisysteme, Sockets usw. festzulegen.

Ich verwende eine nicht verwaltete Bibliothek, um das Sicherheitsetikett von Socket.Handle zu erhalten. Bei einem einfachen TCP-Testprojekt funktioniert es gut. Aber ich muss httprequest und httpresponse korrekt an meine Webapi weiterleiten - es ist eine komplexere Aufgabe.
Wenn ich dieses Modell verwenden kann, wo kann ich meine Routing-Logik platzieren?

@davidfowl Ich

Transportschicht-Handle-Verbindung, dann Dispatcher verarbeiten sie und bis zur Middleware. Im Anwendungscode kann ich diese Verbindung von HttpContext.Features verwenden.

image

Wenn ich richtig liege, kann ich in meinem Fall auf das Socket-Objekt in SocketTransport zugreifen und dann mein Sicherheitslabel auf socketconnection setzen.
Dafür muss ich vorhandene SocketTransport und SocketConnection ändern . Routing-Logik für benutzerdefinierte Middlware.
Es ist der richtige Weg? Oder kann ich auf andere Weise auf die Incomig-Socket-Verbindung zugreifen?

Es tut mir leid, dass ich über die Diskussion hinausgegangen bin.

Das ist richtig. Wir müssten eine neue Funktion bereitstellen, die den Socket-Handle freilegt. Dann könnten Sie die Logik schreiben, die Sie schreiben wollten.

Wir müssten eine neue Funktion bereitstellen, die den Socket-Handle freilegt. Dann könnten Sie die Logik schreiben, die Sie schreiben wollten.

Es wäre toll. Was wird dafür benötigt?
Kann ich irgendwie helfen?

@westfin Ja! Sie können ein Problem einreichen, in dem Sie dasselbe angeben, was Sie hier getan haben, und wir können eine Funktion entwickeln, die das zugrunde liegende Socket-Handle verfügbar macht, und dann können Sie eine PR senden.

@davidfowl Während ich verstehe, dass das Projekt #bedrock die Arbeit ist, um zu ermöglichen, dass die Nicht-HTTP-Protokollimplementierung Teil des AspNetCore-Frameworks wird, gibt es eine Liste von Protokollen, die als Bürger erster Klasse angesehen werden könnten / könnten, dh. SFTP, FTP und FTPS

Sie können einen Blick auf meine Beispiel-Website werfen: https://wseco.azurewebsites.net/
Was Sie hier tun können, ist, dass Sie einen Hub im laufenden Betrieb dynamisch verbinden/erstellen können, anstelle einer statischen Hub-Definition;
wss://wsecho.azurewebsites.net/hub/XYZ.....
Anstatt verschiedene Ports abzuhören, können Sie verschiedene Hubs für verschiedene Verbindungen verwenden.

Die Implementierung des SignalR v1-Hubs war schrecklich, v2 wurde verbessert, aber immer noch schwer zu implementieren.
mit Kestrel habe ich eine Liste für den Hub erstellt, im Grunde ist es eine Liste. Immer wenn es einen neuen Hub erhält, wird es der Liste hinzugefügt, und ich habe alle Methoden entsprechend geändert.

PS: Irgendwann stürzt die Kestrel App ab, weil für den Fehler in Kestrel diese Seite die erste Version von Kestrel verwendet. Ich werde es später upgraden.

@davidfowl irgendwelche Updates dazu, seit 2.2 raus ist?

seit 2.2 ist out?

🤔 Glaubst du noch nicht?

@JanEggers es sieht so aus, aber es ist nur als 2.2.0 markiert kann keine Veröffentlichung finden?

Jedenfalls hatte ich nur auf Neuigkeiten speziell über eine clientseitige Implementierung von Connections.Abstractions gehofft.

Nein, wir haben in 2.2 keine Fortschritte gemacht

Es ist sehr traurig :( Ich habe den Entwicklern gesagt, dass sie auf 2.2 warten und Sie diesen hässlichen Code entfernen können, der direkt mit Sockets funktioniert.

Nun, tatsächlich gibt es eine öffentliche API, die Sie heute verwenden können, sie ist nur in ihrem aktuellen Zustand an Kestrel gebunden.

@davidfowl Ich habe versucht, die KestrelServer-Klasse direkt zu verwenden, um so etwas wie einen TCP-Echo-Server zu implementieren. Das Problem ist, dass es immer noch an HTTP gekoppelt ist. Als ich eine Anfrage vom Browser gesendet habe, hat es irgendwie funktioniert. Aber wenn Telnet verwendet wird, wird die Verbindung geschlossen und nicht beibehalten. Ich gehe davon aus, dass es verworfen wird, weil einige obligatorische HTTP-Header nicht gesendet werden oder nur weil es von einer Anfrage -> Antwort abhängt, ohne dauerhafte Verbindungen aufrechtzuerhalten. Wenn Sie ein Beispiel mit einer ähnlichen Implementierung wie hier https://github.com/davidfowl/TcpEcho teilen können, aber Kestrel verwenden, wäre das großartig.

Irgendwelche Fortschritte in 3.0?

Ich möchte https://github.com/AceHack/MultiplexedWebSockets portieren, um das Grundgestein so zu verwenden, wie es am sinnvollsten ist. Ich habe eine Version, an der ich arbeite, die https://github.com/Microsoft/bond verwendet.

@davidfowl Ich mochte die Einfachheit deines Beispiels sehr > Siehe https://github.com/davidfowl/MultiProtocolAspNetCore

Irgendwelche Tipps oder Hinweise zur Implementierung von TLS für etwas, das nicht an HTTPS gekoppelt ist (z. B. ein TCP-Gerät, das die Übermittlung seiner Daten mit TLS verschlüsselt)?

Mein WIP PR hier ersetzt das Netzwerk von Orleans auf den pubternalen 'Bedrock'-APIs und fügt Client-Unterstützung hinzu. Orleans hat externe Clients, aber Silos müssen auch miteinander kommunizieren (die meisten verteilten Systeme haben diese Anforderung), daher ist eine Unterstützung für Client-Netzwerke dringend erwünscht.

Vielleicht könnte Bedrock eine Microsoft.Extensions-Bibliothek werden & TLS kann ein Teil dieser Pipeline sein (mit Client-Unterstützung), zB: Microsoft.Extensions.{Transport,Connection,Networking}.Abstractions.

Hier sind die Kernschnittstellen, die ich zusätzlich zu den @davidfowl verwende :

```C#
// Kundenseite
öffentliche Schnittstelle IConnectionFactory
{
AufgabeConnectAsync(string endPoint);
}

// Serverseite
öffentliche Schnittstelle IConnectionListenerFactory
{
IConnectionListener Create(string endPoint, ConnectionDelegate connectionDelegate);
}

öffentliche Schnittstelle IConnectionListener
{
Aufgabe BindAsync();
Aufgabe UnbindAsync();
Aufgabe StopAsync();
}
```

Diese können sich ändern und vielleicht ist "Transport" in diesen Namen besser geeignet als "Verbindung".

ASP.NET verwendet eine IEndpointInformation Schnittstelle anstelle der string Schnittstelle, die mein PR derzeit verwendet. Ich habe keine starke Meinung, aber IEndpointInformation fühlte sich peinlich an. Wir können dies vor dem Zusammenführen ändern.

Ist es richtig, dass ich, wenn ich TLS verwenden möchte, die folgenden Schritte ausführen muss:

  1. Wickeln Sie die Rohre in einen Bach
  2. SSLStream verwenden
  3. Wickeln Sie den Strom in Rohre

Ich hoffte, dass ich diese Pipe <-> Stream <-> Pipe-Konvertierung vermeiden konnte.

Dies wird geschlossen, weil der Kern des Grundgesteins in Kestrel liegt. Wir haben noch eine Reihe von Reaktionen, die wir machen möchten (zum Beispiel #4623), aber diese sollten in separaten Ausgaben verfolgt werden.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen