Dutzende Millionen Zugangsdienste [Gateway]-Framework-Design (3: Schichtmodus)

Dieser Artikel wird im technischen Recherchemodus verfasst und kann von nicht-technischen Studierenden übersprungen werden.

Hintergrund

Bei der Implementierung des Einstiegsdienstes basierend auf dem Entwurf und der Konstruktion des Komponentenmodells (Plug-in) kommt es bei Verwendung des nativen Go-Paket-Plugins zu Funktionsfehlern, die nicht ausreichen, um die erwarteten Funktionen zu unterstützen; bei Verwendung von Das Open-Source-Paket go-plugin hat zwar Funktionsmängel behoben, jedoch einen Teil der Performance verloren (Kommunikationskosten zwischen Komponenten und Hauptprogramm).

Einzelheiten finden Sie im Rahmendesign der zig Millionen Zugangsdienste [Gateway] (1)

Einzelheiten finden Sie oben im Rahmendesign von zig Millionen Zugangsdiensten [Gateway] (1).

In diesem Artikel wird ein weiteres Architekturmuster vorgestellt, das auf „Layering“ und „Pipeline“ basiert.

geschichtet

Die Idee der Schichtung gibt es, seit Sie angefangen haben, Computer zu lernen. Computerarchitektur „von Neumann“-Modell, Datenbank-/Linux-Kernel-Architektur usw. Man kann sagen, dass „Schichtung“ der wichtigste und wirksamste Weg ist, komplexe Probleme abzubauen und zu vereinfachen.

Fügen Sie hier eine Bildbeschreibung ein

Die Geschäftslogik wird auf der oberen Ebene abstrahiert und in mehrere Schichten unterteilt, wobei die obere und die untere Ebene voneinander abhängig sind. Es ist jedoch zu beachten, dass die Implementierungskosten umso höher sind, je feiner die Granularität der Geschäftsabstraktionssteuerung ist. Wenn die Aufrufbeziehung des Geschäfts dynamisch ist, führen mehr Abstraktionsschichten zu einer Erhöhung der Gesamtkomplexität und einer größeren Größenordnung des nachfolgenden Geschäfts Kommunikation Ohne ein umfassendes Verständnis der abstrakten Schichtstruktur wird die Qualität der Funktionsimplementierung viel kosten und die Wartung und Erweiterung nachfolgender Dienste zusätzlich verschleiern.

Dynamische Anrufbeziehung: Tritt in komplexen Geschäftsszenarien auf, d. h. es gibt mehrere Downstream-Dienste, der tatsächliche Anrufdienst wird durch das Antwortfeld des Upstream-Dienstes bestimmt und die gesamte Route weist eine dynamische Beziehungstopologie auf.

Der Nebel der Wartung und Erweiterung: Er bezieht sich auf die iterative Entwicklung ohne vollständiges Verständnis des Framework-Designs, wodurch nicht garantiert werden kann, dass die bereitgestellten Funktionen die Framework-Funktionen vollständig nutzen, was die Ausgabequalität etwas spekulativ macht.

Das Folgende ist in drei Arten mit unterschiedlicher Unterteilungsgranularität unterteilt.

Verteilung+Handle

Auf der aktuellen Basis wird die Partikelgröße vergrößert, also

  • Die Geschäftsverwirklichung ist freier.
  • Das Framework wird aus dem Geschäft entfernt und die Wartungskosten sind geringer.

Fügen Sie hier eine Bildbeschreibung einIm Webmodus ist der bestehende Prozess in zwei Teile unterteilt: Router + Ausführen.

  • Router
    • Verteilen Sie den Datenverkehr an das entsprechende Handle.
  • ausführen
    • Die spezifische Geschäftsverarbeitung ist nicht in Rahmenebenen unterteilt, und das spezifische Design und die Implementierung werden von Studenten der Geschäftsentwicklung realisiert.

Verteilung+Haken

Fügen Sie auf der Grundlage des Handles Hook-Einschränkungen hinzu

  • Für Szenarien ohne Hook-Anforderungen ist die Einschränkungsgranularität zu gering und die Komplexität zu hoch.

Fügen Sie hier eine Bildbeschreibung ein

Teilen Sie im Webmodus den vorhandenen Prozess in die Logik „router + afterhook\execute\beforehook\assert“ auf.

  • Router

    • Verteilen Sie den Datenverkehr an das entsprechende Handle.
  • afterhook\execute\beforehook\assert

    • Steuern Sie zwischen bestimmten Geschäftsprozessen die Größe der Granularität, vor der Ausführung, Ausführung und nach der Ausführung.

Verteilung + gleichzeitige Schichtung

Es ist notwendig, das aktuelle Geschäft zu ordnen, die Aufrufreihenfolge der Unterdienste neu aufzuteilen und gleichzeitig in Schichten aufzurufen

  • Es gibt Szenarien, in denen sich das Routing nachgelagerter Unterdienste dynamisch ändert, was nicht im Voraus vorhergesagt und geschichtet werden kann und zusätzliches Routing entworfen werden muss.
  • Die meisten Serviceaufrufe können von seriell auf parallel umgestellt werden, wodurch die Leistung verbessert wird.
  • Wenn ein dynamisches Routing-Problem vorliegt, muss für dieses Problem eine zusätzliche Verarbeitung durchgeführt werden, und die Komplexität von Design und Implementierung ist hoch.

Die Verwendungsvoraussetzung besteht darin, dass eine statische Unterdienst-Topologiekarte vorhanden ist und die Dienstaufrufbeziehung dynamisch gefärbt und in verschiedene Ebenen unterteilt ist und gleichzeitige Anrufe entsprechend der Dienstebene durchgeführt werden.

  • Zwei Teile werden abstrahiert: Parameterkonstruktion + Antwortspleißen und gleichzeitiger Dienstaufruf.

Pipeline

Die Idee von Pipelines ist in traditionellen Sprachen möglicherweise selten zu finden. In Goland, Ruby und anderen neuen Stilen ist sie häufiger anzutreffen, insbesondere bei der Unterstützung von Parallelität und Cloud-native-orientierten Designs auf Sprachebene. Der Schwerpunkt liegt auf dem Ultimativen Streben nach Leistung und leistungsstarker Stream-Verarbeitung von Daten wie Big Data und großen Modellen.

Hinweis: Weitere Informationen zu Cloud Native finden Sie unter: Migration der Cloud Native-Anwendungsarchitektur 1: Inkrementelles Migrationsparadigma

Fügen Sie hier eine Bildbeschreibung ein

Aber das spielt keine Rolle, Sie können einfach zuerst das Konzept der Middleware in die Pipeline übertragen und dann mehr erfahren. Das Design hier basiert auf dem Kanal in Goland.

Hinweis: Wenn Sie mehr über Goland erfahren möchten, gehen Sie zu: Design Reflection of Go Language

Kanal

In den oben genannten verschiedenen Schemata und Implementierungen handelt es sich bei allen um String-Änderungen und -Merges innerhalb der Anfrage, und sogar die Sprachebene lässt „auf der Basis von vorhandenem PHP arbeiten“.

Hier sprechen wir über ein Pipeline-basiertes Musterdesign, das Parallelität auf Serviceebene realisiert, sich besonders für extrem große Parallelitätsszenarien eignet und den Eigenschaften der Go-Sprache entspricht.

Fügen Sie hier eine Bildbeschreibung ein

Die Haupt-Coroutine ist für die Überwachung und gleichzeitigen Aufrufe jedes Self-Service verantwortlich, und die Business-Coroutine wird nur für die Initiierung von Diensten und den Empfang von Antworten verwendet. Fassen Sie verschiedene Anfragen in der Sub-Service-Dimension zusammen und rufen Sie sie parallel auf.

Hier ein kurzer Überblick über das Programm:

  • Zusammenstellen von „nur Dienstparameter orchestrieren“
    • Vom linearen Prozessdesign bis zum optimierten, hochmontierten Design.
  • beschleunigen
    • Konvertieren Sie mehrere Dienste in einem einzigen PV von seriell in parallel.
    • Konvertieren Sie einzelne PV-Anrufe in gleichzeitige.
  • expandieren
    • Service-Modularisierung, Multi-Route-Aufrufe sind zu 100 % wiederverwendbar.
    • Das Framework ist stark, schützt die Geschäftsnutzung und stellt hohe Anforderungen an die Realisierung der grundlegenden Aufruffunktion „Funktionen vervollständigen, benutzerdefinierte Konfiguration unterstützen“.

Aber es sollte beachtet werden, dass

  • Es handelt sich um das Go-Channel-Modell und die Implementierungskosten sind relativ hoch.
    • Die Berücksichtigung von Problemen/Systemen wie einer strengen und wissenschaftlichen Berichterstattung und gleichzeitigen Deadlocks ist erforderlich.
Demo-Implementierung
package main

import (
	"fmt"
	"sync"
)


type FInput struct{
    
    
	callback chan FInput
	param string
	res string
}


func main () {
    
    
	fmt.Println("hello https://tool.lu/")
	c := make(chan FInput,3)
	defer close(c)
	var wg sync.WaitGroup
	wg.Add(3)  
	go F(c,wg) //服务开启监听
	go A(c,wg) //发起服务请求
	go B(c,wg) //发起服务请求
	wg.Wait()
	fmt.Println("X https://tool.lu/ is finish")
}

func F (c chan FInput,wg sync.WaitGroup){
    
    
	fmt.Println("F https://tool.lu/ len:",len(c))
	for{
    
    
		i, ok := <-c
		fmt.Println("F https://tool.lu/ ok:",ok)
		fmt.Println("F https://tool.lu/ param:",i.param)
		if ok{
    
    
			i.res = i.param + " is executed "
			i.callback <- i
		}
	}
	fmt.Println("F https://tool.lu/ is finish")
	wg.Done()
}

func A (c chan FInput,wg sync.WaitGroup){
    
    
	cb:=make(chan FInput)
	defer close(cb)
	var p FInput
	p.callback = cb
	p.param = "A"
	c<-p
	i, ok := <-cb
	if ok{
    
    
		fmt.Println("A https://tool.lu/ res ok:",ok)
		fmt.Println("A https://tool.lu/ res param:",i.param)
		fmt.Println("A https://tool.lu/ res value:",i.res)
	}
	fmt.Println("A https://tool.lu/ is finish")
	wg.Done()
}

func B (c chan FInput,wg sync.WaitGroup){
    
    
	cb:=make(chan FInput)
	defer close(cb)
	var p FInput
	p.callback = cb
	p.param = "B"
	c<-p
	i, ok := <-cb
	if ok{
    
    
		fmt.Println("B https://tool.lu/ res ok:",ok)
		fmt.Println("B https://tool.lu/ res param:",i.param)
		fmt.Println("B https://tool.lu/ res value:",i.res)
	}
	fmt.Println("B https://tool.lu/ is finish")
	wg.Done()
}

Zusammenfassung

Wenn man die oben genannten verschiedenen architektonischen Musterentwürfe vergleicht, weist jedes seine eigenen Merkmale auf und seine Vor- und Nachteile vereinen sich. Bei der Auswahl einer Architektur ist das Nachdenken über verschiedene Modelle nur der erste Schritt. Nur unter dieser Prämisse kann eine weitere Auswahl getroffen werden.

Da chatGPT in das Blickfeld der Öffentlichkeit gelangt, ist der „Big Model Channel“ populär geworden und sein einzigartiger Entwicklungsprozess ist noch herausragender. Um es ganz klar auszudrücken: Verschiedene Anwendungen werden in Zukunft intelligentere und größere Modelle sein ...

Im nächsten Kapitel wird vorgestellt, wie der „Eintrittsdienst“ mit dem „großen Modell“ kombiniert wird, um ein zukunftsorientiertes Architekturmodell zu entwerfen. Bleiben Sie also dran!

Anhang

Ich denke du magst

Origin blog.csdn.net/qq_34417408/article/details/131473186
Empfohlen
Rangfolge