Wie verwende ich PHP zur Implementierung von Microservices?

Swoft


Warum sollte über Service Governance gesprochen werden?


Mit der zunehmenden Popularität des Internets ist die traditionelle MVC-Architektur immer aufgeblähter und sehr schwierig zu warten, da der Umfang der Anwendungen weiter zunimmt.


Wir müssen Maßnahmen ergreifen, um ein großes System gemäß den Geschäftsmerkmalen in mehrere Anwendungen aufzuteilen. Beispielsweise kann ein großes E-Commerce-System ein Benutzersystem, ein Produktsystem, ein Bestellsystem, ein Bewertungssystem usw. umfassen, und wir können sie in mehrere einzelne Anwendungen aufteilen. Die Merkmale einer Architektur mit mehreren Anwendungen sind Anwendungen, die unabhängig voneinander ausgeführt werden und sich nicht gegenseitig aufrufen können.


Obwohl mehrere Anwendungen das Problem der aufgeblähten Anwendung lösen, sind die Anwendungen unabhängig voneinander und gemeinsame Dienste oder Codes können nicht wiederverwendet werden.




Bei einem großen Internet-System enthält es normalerweise mehrere Anwendungen mit gemeinsamen Diensten, und jede Anwendung hat eine Anrufbeziehung untereinander. Darüber hinaus gibt es weitere Herausforderungen für das große Internet-System, z. B. den Umgang mit schnell wachsenden Benutzern, die Verwaltung von Forschungs- und Entwicklungsteams zur schnellen Iteration der Systementwicklung, die stabile Aufrechterhaltung des System-Upgrades usw.


Daher, um Dienste gut wiederzuverwenden und Module zu warten, um einfach zu erweitern. Wir möchten, dass die Dienste von der Anwendung getrennt werden. Ein Dienst befindet sich nicht mehr in einer Anwendung, sondern wird als separater Dienst verwaltet. Die Anwendung selbst ist kein aufgeblähter Modulstapel mehr, sondern eine modulare Servicekomponente.


Servitisierung


Eigenschaften


Was ist die Funktion von "Servitization"?


  • Eine Anwendung wird von Unternehmen in Dienste aufgeteilt
  • Einzelne Dienste können unabhängig voneinander bereitgestellt werden
  • Der Dienst kann von mehreren Anwendungen gemeinsam genutzt werden
  • Dienste können untereinander kommunizieren
  • Die Architektur des Systems ist klarer
  • Kernmodule sind stabil, und durch die Aktualisierung von Servicekomponenten in Einheiten kann das Risiko häufiger Neuerscheinungen vermieden werden
  • Einfach für Entwicklung und Verwaltung
  • Die Wartung kann von einem einzelnen Team mit klaren Arbeitsabläufen und Verantwortlichkeiten durchgeführt werden
  • Wiederverwendung von Diensten, Wiederverwendung von Codes
  • Sehr einfach zu erweitern

Die Herausforderung der Wartung


Nach der Systemwartung ist die Abhängigkeit des Systems kompliziert und die Anzahl der Interaktionen zwischen Diensten wird erhöht. Da im Entwicklungsmodus von fpm der residente Speicher nicht bereitgestellt werden kann, muss jede Anforderung bei Null beginnen, indem ein Prozess geladen wird, um den Prozess zu beenden, wodurch viel nutzloser Overhead entsteht. Außerdem kann die Datenbankverbindung nicht wiederverwendet und nicht geschützt werden, da fpm prozessbasiert ist und die Anzahl der fpm Prozesse auch die Anzahl der gleichzeitigen bestimmt. Dies sind die Probleme, die uns durch die einfache Entwicklung von fpm . Dies sind die Gründe, warum Java auf der Internetplattform im Vergleich zu .NET und PHP immer beliebter wird. Abgesehen von PHP non-memory resident , müssen noch viele andere Probleme behoben werden.


  • Mehr Services, mehr Komplexität des Konfigurationsmanagements
  • Komplexe Dienstabhängigkeiten
  • Lastausgleich zwischen Diensten
  • Serviceerweiterung
  • Serviceüberwachung
  • Service-Downgrade
  • Dienstauthentifizierung
  • Service online und offline
  • Servicedokumentation
    ......

Sie können sich vorstellen, welche Vorteile das residente Gedächtnis für uns bringt.


  • Starten Sie die Framework-Initialisierung erst, wenn wir uns auf die Verarbeitung von Anforderungen konzentrieren können, da das Framework beim einmaligen Start für den residenten Speicher nur einmal im Speicher initialisiert werden kann


  • Verbindungsmultiplex , einige Ingenieure können nicht verstehen, wenn sie keinen Verbindungspool verwenden. Was ist die Folge des Herstellens von Verbindungen für jede Anforderung? Es verursacht zu viele Backend-Ressourcen in Verbindungen. Für einige Basisdienste wie Redis, Datenbanken, sind Verbindungen ein teurer Abfluss.



Gibt es also eine gute Lösung? Die Antwort lautet ja, und viele Leute verwenden das Framework namens Swoft . Swoft ist ein RPC- Framework mit der Service Governance Funktion. Swoft ist das erste PHP-residente Speicher-Coroutine-Full-Stack-Framework, das auf dem Kernkonzept des Spring Boot basiert. Die Konvention ist größer als die Konfiguration.


Swoft bietet eine elegantere Möglichkeit, RPC Dienste wie Dubbo und Swoft bietet eine ähnliche Leistung wie Golang . Hier ist das Stresstestergebnis der Swoft Leistung auf meinem PC .

Swoft


Die Verarbeitungsgeschwindigkeit ist im ab Stresstest sehr erstaunlich. Mit der i7 generation 8 CPU und 16GB Speicher verwenden 100000 Anfragen nur 5s . Die Zeit ist im fpm Entwicklungsmodus grundsätzlich nicht zu erreichen. Der Test reicht auch aus, um die hohe Leistung und Stabilität von Swoft zu demonstrieren.


Elegante Service-Governance


Serviceregistrierung und -ermittlung


Im Governance-Prozess von Microservices ist häufig die Registrierung von Diensten involviert, die für Cluster von Drittanbietern wie Consul / etcd initiiert wurden. In diesem Kapitel wird die swoft-consul-Komponente im Swoft-Framework verwendet, um die Registrierung und Erkennung von Diensten zu implementieren.
Swoft
Implementierungslogik


 <?php declare(strict_types=1); namespace App\Common; use ReflectionException; use Swoft\Bean\Annotation\Mapping\Bean; use Swoft\Bean\Annotation\Mapping\Inject; use Swoft\Bean\Exception\ContainerException; use Swoft\Consul\Agent; use Swoft\Consul\Exception\ClientException; use Swoft\Consul\Exception\ServerException; use Swoft\Rpc\Client\Client; use Swoft\Rpc\Client\Contract\ProviderInterface; /** * Class RpcProvider * * @since 2.0 * * @Bean() */ class RpcProvider implements ProviderInterface { /** * @Inject() * * @var Agent */ private $agent; /** * @param Client $client * * @return array * @throws ReflectionException * @throws ContainerException * @throws ClientException * @throws ServerException * @example * [ * 'host:port', * 'host:port', * 'host:port', * ] */ public function getList(Client $client): array { // Get health service from consul $services = $this->agent->services(); $services = [ ]; return $services; } } 

Leistungsschalter warten


In einer verteilten Umgebung, insbesondere einem verteilten System mit Mikroservice-Architektur, ruft ein Softwaresystem häufig ein anderes Remote-System auf. Der Angerufene eines solchen Fernanrufs kann ein anderer Prozess oder ein anderer Host im Netzwerk sein. Der größte Unterschied zwischen diesem Remote-Anruf und dem internen Anruf des Prozesses besteht darin, dass der Remote-Anruf möglicherweise fehlschlägt oder hängen bleibt. Keine Antwort bis zum Timeout. Schlimmer noch, wenn mehrere Anrufer denselben angehaltenen Dienst aufrufen, ist es sehr wahrscheinlich, dass sich das Timeout eines Dienstes schnell auf das gesamte verteilte System ausbreitet, was zu einer Kettenreaktion führt, die die gesamte Menge an Ressourcen in verteilten Systemen verbraucht. Schließlich kann es zu einer Systemlähmung kommen.


Der Leistungsschaltermodus wurde entwickelt, um Katastrophen zu verhindern, die durch solche wasserfallartigen Kettenreaktionen in verteilten Systemen verursacht werden.



Im grundlegenden Leistungsschaltermodus wird sichergestellt, dass der Lieferant nicht angerufen wird, wenn der Leistungsschalter geöffnet ist. Wir benötigen jedoch auch eine zusätzliche Methode, um den Leistungsschalter zurückzusetzen, nachdem der Lieferant den Betrieb wieder aufgenommen hat. Eine mögliche Lösung besteht darin, dass der Leistungsschalter regelmäßig erkennt, ob der Dienst des Lieferanten wieder aufgenommen wird. Nach der Wiederaufnahme wird der Status auf Schließen gesetzt. Der Zustand ist halb geöffnet, wenn der Leistungsschalter erneut versucht.


Die Verwendung der Sicherung ist einfach und leistungsstark. Es kann mit einem @Breaker kommentiert werden. Die Sicherung des Swoft kann in jedem Szenario verwendet werden, z. B. wenn ein Dienst aufgerufen wird. Es kann herabgestuft oder nicht aufgerufen werden, wenn ein Dienst eines Drittanbieters angefordert wird.


 <?php declare(strict_types=1); namespace App\Model\Logic; use Exception; use Swoft\Bean\Annotation\Mapping\Bean; use Swoft\Breaker\Annotation\Mapping\Breaker; /** * Class BreakerLogic * * @since 2.0 * * @Bean() */ class BreakerLogic { /** * @Breaker(fallback="loopFallback") * * @return string * @throws Exception */ public function loop(): string { // Do something throw new Exception('Breaker exception'); } /** * @return string * @throws Exception */ public function loopFallback(): string { // Do something } } 

Serviceeinschränkung


Durchflussbegrenzung, Leistungsschalter, Service-Downgrade Diese können wiederholt hervorgehoben werden, da sie wirklich wichtig sind. Wenn der Dienst nicht funktioniert, muss er unterbrochen werden. Durchflussbegrenzung ist ein Werkzeug, um sich selbst zu schützen. Wenn es keinen Selbstschutzmechanismus gibt und Verbindungen empfangen werden, egal wie viele sie sind, bleibt das Front-End definitiv hängen, wenn der Datenverkehr sehr groß ist, während das Back-End nicht alle Verbindungen verarbeiten kann.


Die Flussbeschränkung besteht darin, die Anzahl der gleichzeitigen und die Anzahl der Anforderungen beim Zugriff auf knappe Ressourcen wie Flash-Verkaufsgüter zu begrenzen, um den Spitzenwert effektiv zu senken und die Flusskurve zu glätten. Der Zweck der Flussbeschränkung besteht darin, die Rate des gleichzeitigen Zugriffs und gleichzeitiger Anforderungen zu begrenzen oder die Geschwindigkeit der Anforderung innerhalb eines Zeitfensters zu begrenzen, um das System zu schützen. Sobald das Ratenlimit erreicht oder überschritten ist, können die Anforderungen abgelehnt oder in die Warteschlange gestellt werden.


Die unterste Ebene der Swoft von Swoft verwendet den Token-Bucket-Algorithmus, und die zugrunde liegende Ebene basiert auf Redis , um die verteilte Swoft zu implementieren.


Die Swoft-Flussbeschränkung begrenzt nicht nur Controller, sondern auch die Methoden in jeder Bean und steuert die Zugriffsrate der Methoden. Das folgende Beispiel ist die ausführliche Erklärung.


 <?php declare(strict_types=1); namespace App\Model\Logic; use Swoft\Bean\Annotation\Mapping\Bean; use Swoft\Limiter\Annotation\Mapping\RateLimiter; /** * Class LimiterLogic * * @since 2.0 * * @Bean() */ class LimiterLogic { /** * @RequestMapping() * @RateLimiter(rate=20, fallback="limiterFallback") * * @param Request $request * * @return array */ public function requestLimiter2(Request $request): array { $uri = $request->getUriPath(); return ['requestLimiter2', $uri]; } /** * @param Request $request * * @return array */ public function limiterFallback(Request $request): array { $uri = $request->getUriPath(); return ['limiterFallback', $uri]; } } 

Dies unterstützt den symfony/expression-language . Wenn die Geschwindigkeit begrenzt ist, wird die im fallback definierte limiterFallback Methode aufgerufen.


Konfigurationscenter


Bevor wir über das Konfigurationscenter sprechen, lassen Sie uns über die Konfigurationsdatei sprechen. Wir sind kein Fremder. Es bietet uns die Möglichkeit, das Programm dynamisch zu ändern. Ein Zitat von jemandem ist:


Dynamische Anpassung der Fluglage der Systemlaufzeit!

Ich kann unsere Arbeit anrufen, um Teile in schnell fliegenden Flugzeugen zu reparieren. Wir Menschen sind immer nicht in der Lage, alles zu kontrollieren und vorherzusagen. Für unser System müssen wir immer einige Steuerleitungen reservieren, um Anpassungen vorzunehmen, wenn wir sie benötigen, um die Systemrichtung zu steuern (z. B. Grausteuerung, Anpassung der Durchflussbeschränkung), was besonders für die Internetbranche wichtig ist, die Änderungen berücksichtigt.


Für die eigenständige Version nennen wir es die Konfiguration (Datei); Für das verteilte Clustersystem nennen wir es das Konfigurationszentrum (System).


Was genau ist ein verteiltes Konfigurationscenter?


Mit der Entwicklung des Geschäfts und der Aktualisierung der Mikrodienstarchitektur nehmen die Anzahl der Dienste und die Konfiguration von Programmen (verschiedene Mikrodienste, verschiedene Serveradressen, verschiedene Parameter) sowie die traditionelle Konfigurationsdateimethode und Datenbankmethode zu kann die Anforderungen von Entwicklern im Konfigurationsmanagement nicht erfüllen:


  • Sicherheit: Die Konfiguration folgt dem in der Codebasis gespeicherten Quellcode, was leicht zu Konfigurationslecks führen kann.
  • Aktualität: Ändern Sie die Konfiguration und starten Sie den Dienst neu, damit er wirksam wird.
  • Einschränkungen: Dynamische Anpassungen können nicht unterstützt werden: z. B. Protokollschalter, Funktionsschalter;

Daher müssen wir das Center konfigurieren, um die Konfiguration zu verwalten! Um Geschäftsentwickler von komplexen und umständlichen Konfigurationen zu befreien, müssen sie sich nur auf den Geschäftscode selbst konzentrieren, was die Entwicklung und die betriebliche Effizienz erheblich verbessern kann. Gleichzeitig wird die Konfiguration und Freigabe des Pakets die Erfolgsrate der Freigabe weiter verbessern und die Feinabstimmung der Steuerung und die Notfallbehandlung von Betrieb und Wartung stark unterstützen.


In Bezug auf verteilte Konfigurationszentren gibt es im Web viele Open Source-Lösungen, z.


Apollo ist ein verteiltes Konfigurationscenter, das von der Framework-Abteilung von Ctrip entwickelt wurde. Es kann die Konfiguration verschiedener Umgebungen und verschiedener Anwendungscluster zentral verwalten. Sie kann nach Änderung der Konfiguration in Echtzeit an das Anwendungsende übertragen werden. Es verfügt über die Funktionen eines standardisierten Berechtigungs- und Prozessmanagements und eignet sich für die Szenarien zum Konfigurieren und Verwalten von Microservices.


In diesem Kapitel wird Apollo als Beispiel verwendet, um Konfigurations- und sichere Neustartdienste aus dem Remote-Konfigurationscenter abzurufen. Wenn Sie mit Apollo vertraut sind, können Sie sich zunächst die Apollo Komponente der Swoft Erweiterung Swoft und die offizielle Apollo Dokumentation lesen.


In diesem Kapitel wird Apollo in Swoft als Beispiel verwendet. Wenn sich die Apollo Konfiguration ändert, starten Sie den Dienst neu (http-server / rpc-server / ws-server). Das folgende Beispiel zeigt einen Agenten:


 <?php declare(strict_types=1); namespace App\Model\Logic; use Swoft\Apollo\Config; use Swoft\Apollo\Exception\ApolloException; use Swoft\Bean\Annotation\Mapping\Bean; use Swoft\Bean\Annotation\Mapping\Inject; /** * Class ApolloLogic * * @since 2.0 * * @Bean() */ class ApolloLogic { /** * @Inject() * * @var Config */ private $config; /** * @throws ApolloException */ public function pull(): void { $data = $this->config->pull('application'); // Print data var_dump($data); } } 

Das Obige ist ein einfacher Apollo-Konfigurationszug. Zusätzlich zu dieser Methode bietet Swoft-Apollo weitere Verwendungsmöglichkeiten.



Source: https://habr.com/ru/post/de460855/


All Articles