Heim  >  Artikel  >  Backend-Entwicklung  >  Wie implementiert man Microservices mit PHP?

Wie implementiert man Microservices mit PHP?

慕斯
慕斯nach vorne
2021-06-18 11:12:475206Durchsuche

In diesem Artikel erfahren Sie, wie Sie mit PHP Microservices implementieren. Es hat einen gewissen Referenzwert. Freunde in Not können sich darauf beziehen. Ich hoffe, es wird für alle hilfreich sein.

Wie implementiert man Microservices mit PHP?Warum sprechen wir über Service Governance? Da das Surfen im Internet immer größer wird, wächst die traditionelle MVC-Einzelarchitektur weiter, und die Anwendungsmodule nehmen weiter zu Die Anwendung wird immer aufgeblähter und schwieriger zu warten.

Wir müssen Maßnahmen ergreifen, um die Anwendung nach Anwendung aufzuteilen, dh die ursprüngliche Anwendung entsprechend den Geschäftsmerkmalen in mehrere Anwendungen aufzuteilen. Ein großes E-Commerce-System kann beispielsweise ein Benutzersystem, ein Produktsystem, ein Bestellsystem, ein Bewertungssystem usw. umfassen. Wir können sie in separate Anwendungen aufteilen. Das Merkmal der Multianwendungsarchitektur besteht darin, dass Anwendungen unabhängig sind und sich nicht gegenseitig aufrufen.

Obwohl mehrere Anwendungen das Problem aufgeblähter Anwendungen lösen, sind die Anwendungen unabhängig voneinander und einige gemeinsame Geschäfte oder Codes können nicht wiederverwendet werden.

Einzelanwendungslösung

Für ein großes Internetsystem enthält es normalerweise mehrere Anwendungen, und es gibt häufig gemeinsame Dienste zwischen Anwendungen und es gibt auch Aufrufbeziehungen zwischen Anwendungen. Darüber hinaus gibt es weitere Herausforderungen für große Internetsysteme, z. B. wie man mit dem schnellen Wachstum der Benutzer umgeht, wie man das Forschungs- und Entwicklungsteam verwaltet, um die Produktentwicklung schnell zu iterieren, wie man Produktaktualisierungen stabiler hält usw.

Um das Geschäft wiederverwendbar zu machen und das Modul einfacher zu erweitern und zu warten, hoffen wir, dass das Geschäft und die Anwendung getrennt werden. Ein bestimmtes Geschäft gehört nicht mehr zu einer Anwendung, sondern wird separat als eine verwaltet unabhängiger Service. Die Anwendung selbst ist kein aufgeblähter Stapel von Modulen mehr, sondern setzt sich aus modularen Servicekomponenten zusammen.

Serviceisierung

Funktionen

Was sind also die herausragenden Funktionen der Verwendung von Servitization?

  • Anwendungen je nach Geschäft in Dienste aufteilen
  • Jeder Dienst können unabhängig voneinander bereitgestellt werden
  • Dienste können von mehreren Anwendungen gemeinsam genutzt werden
  • Dienste können miteinander kommunizieren
  • Das System ist architektonisch klarer
  • Das Kernmodul ist stabil und kann in Einheiten von Servicekomponenten aktualisiert werden, wodurch Risiken durch häufige Releases vermieden werden.
  • Bequeme Entwicklung und Verwaltung
  • Getrennte Teamwartung, klare Arbeit und klare Verantwortlichkeiten
  • li>
  • Geschäftliche Wiederverwendung und Code-Wiederverwendung
  • Sehr einfach zu erweitern

Herausforderungen bei der Servitisierung

服务化给有那些亮点的特色呢 ?

  • 应用按业务拆分成服务
  • 各个服务均可独立部署
  • 服务可被多个应用共享
  • 服务之间可以通信
  • 架构上系统更加清晰
  • 核心模块稳定,以服务组件为单位进行升级,避免了频繁发布带来的风险
  • 开发管理方便
  • 单独团队维护、工作分明,职责清晰
  • 业务复用、代码复用
  • 非常容易拓展

服务化面临的挑战

系统服务化之后, 增加了依赖关系复杂, 也会增加服务与服务之间交互的次数. 在 fpm 的开发模式下. 因为无法常驻内存给我们带来了, 每一次请求都要从零开始加载到退出进程, 增加了很多无用的开销, 数据库连接无法复用也得不到保护, 由于fpm是以进程为单位的fpm的进程数也决定了并发数, 这也是是fpm开发简单给我们带来的问题. 所以说为什么现在互联网平台Java比较流行了,.NETPHP在这方面都不行。PHP非内存常驻的就不用说了。除此之外,还有很多其他问题需要解决。

  • 服务越来越多,配置管理复杂
  • 服务间依赖关系复杂
  • 服务之间的负载均衡
  • 服务的拓展
  • 服务监控
  • 服务降级
  • 服务鉴权
  • 服务上线与下线
  • 服务文档 ......

你可以想象一下常驻内存给我们带来的好处 比如

  • 只启动框架初始化 如果常驻内存我们只是在启动的时候处理化框架初始化在内存中,专心处理请求

  • 连接复用,有些工程师并不能特别理解,如果不用连接池,来一个请求就发一个连接怎么样?这样就会导致后端资源连接过多。对一些基础服务来说,比如 Redis,数据库,连接是个昂贵的消耗。

那么有没有好的方案呢?答案是有的,而且很多人都在用这个框架,它就是-SwoftSwoft就是一个带有服务治理功能的RPC框架。Swoft是首个 PHP常驻内存协程全栈框架, 基于 Spring BootNach der System-Servitisierung werden Abhängigkeiten komplexer Da es im Entwicklungsmodus von fpm nicht resident sein kann, muss jede Anforderung von Grund auf neu geladen werden, bis der Prozess beendet wird, was die Anzahl der Interaktionen zwischen Diensten erheblich erhöht Es entsteht unnötiger Overhead und die Datenbankverbindung kann nicht wiederverwendet und nicht geschützt werden. Da fpm auf Prozessen basiert, bestimmt die Anzahl der Prozesse von fpm auch die Anzahl der Parallelitäten. Dies ist auch ein Problem, das uns durch die Einfachheit der fpm-Entwicklung entsteht. Warum ist also die Internetplattform Java jetzt beliebter? code> und PHP funktionieren in dieser Hinsicht nicht. Es versteht sich von selbst, dass PHP nicht speicherresident ist. Darüber hinaus gibt es noch viele andere Probleme, die angegangen werden müssen.

  • Es gibt immer mehr Dienste und das Konfigurationsmanagement ist komplex
  • Die Abhängigkeiten zwischen Diensten sind komplex
  • Lastausgleich zwischen Diensten
  • Service-Erweiterung
  • Service-Überwachung
  • Service-Downgrade
  • Service-Authentifizierung
  • Service online und offline
  • Service-Dokumentation. .....
🎜Sie können sich die Vorteile vorstellen, die uns der residente Speicher bringt, wie zum Beispiel🎜
  • 🎜Starten Sie die Framework-Initialisierung nur, wenn oft Bei der speicherbasierten Verarbeitung initialisieren wir das Framework nur beim Start im Speicher und konzentrieren uns auf die Verarbeitung von Anforderungen🎜
  • 🎜Verbindungswiederverwendung. Einige Ingenieure verstehen das nicht besonders, wenn es sich um einen Verbindungspool handelt wird nicht verwendet. Wie wäre es mit dem Senden einer Verbindung, wenn eine Anfrage eingeht? Dies führt zu zu vielen Backend-Ressourcenverbindungen. Für einige Basisdienste wie Redis und Datenbanken sind Verbindungen teuer. 🎜
🎜Gibt es also einen guten Plan? Die Antwort ist ja, und viele Leute verwenden dieses Framework, nämlich Swoft. Swoft ist ein RPC-Framework mit der Funktion Service Governance. Swoft ist das erste PHP-residente Speicher-Coroutine-Full-Stack-Framework, das auf dem von Spring Boot vorgeschlagenen Kernkonzept basiert, dass Konvention wichtiger ist als Konfiguration🎜

Swoft bietet eine elegantere Möglichkeit, den RPC-Dienst ähnlich wie Dubbo zu nutzen. Die Leistung von Swoft ist sehr Gut. Ähnlich wie bei der Golang-Leistung ist das Folgende der Stresstest der Swoft-Leistung auf meinem PC > Stresstest Die Verarbeitungsgeschwindigkeit ist sehr erstaunlich. Mit i78-GenerationCPU, 16GB Speicher unter100.00010.000 Anfragen dauerte es nur 5sDie Zeit ist imfpmEntwicklungsmodus grundsätzlich nicht zu erreichen. Dies reicht aus, um die hohe Leistung und Stabilität vonSwoft` zu beweisen,Swoft 提供了类似 Dubbo 更为优雅的方式使用 RPC 服务, Swoft 性能是非常棒的有着类似Golang性能, 下面是我的PCSwoft 性能的压测情况.

ab压力测试处理速度十分惊人, 在 i78代CPU, 16GB 内存100000万个请求只用了5s时间在fpm开发模式下基本不可能达到. 这也足以证明Swoft` 的高性能和稳定性,

优雅的服务治理

服务注册与发现

微服务治理过程中,经常会涉及注册启动的服务到第三方集群,比如 consul / etcd 等等,本章以 Swoft 框架中使用 swoft-consul 组件,实现服务注册与发现为例。

实现逻辑

<?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
     * [
     *     &#39;host:port&#39;,
     *     &#39;host:port&#39;,
     *     &#39;host:port&#39;,
     * ]
     */
    public function getList(Client $client): array
    {        // Get health service from consul
        $services = $this->agent->services();

        $services = [
        
        ];        return $services;
    }
}

服务熔断

在分布式环境下,特别是微服务结构的分布式系统中, 一个软件系统调用另外一个远程系统是非常普遍的。这种远程调用的被调用方可能是另外一个进程,或者是跨网路的另外一台主机, 这种远程的调用和进程的内部调用最大的区别是,远程调用可能会失败,或者挂起而没有任何回应,直到超时。更坏的情况是, 如果有多个调用者对同一个挂起的服务进行调用,那么就很有可能的是一个服务的超时等待迅速蔓延到整个分布式系统,引起连锁反应, 从而消耗掉整个分布式系统大量资源。最终可能导致系统瘫痪。

断路器(Circuit Breaker)模式就是为了防止在分布式系统中出现这种瀑布似的连锁反应导致的灾难。

基本的断路器模式下,保证了断路器在open状态时,保护supplier不会被调用, 但我们还需要额外的措施可以在supplier恢复服务后,可以重置断路器。一种可行的办法是断路器定期探测supplier的服务是否恢复, 一但恢复, 就将状态设置成close。断路器进行重试时的状态为半开(half-open)状态。

熔断器的使用想到简单且功能强大,使用一个 @Breaker 注解即可,Swoft 的熔断器可以用于任何场景, 例如 服务调用的时候使用, 请求第三方的时候都可以对它进行熔断降级

<?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(&#39;Breaker exception&#39;);
    }    /**
     * @return string
     * @throws Exception
     */
    public function loopFallback(): string
    {        // Do something
    }
}

服务限流

限流、熔断、降级这个强调多少遍都不过分,因为确实很重要。服务不行的时候一定要熔断。限流是一个保护自己最大的利器,如果没有自我保护机制,不管有多少连接都会接收,如果后端处理不过来,前端流量又很大的时候肯定就挂了。

限流是对稀缺资源访问时,比如秒杀,抢购的商品时,来限制并发和请求的数量,从而有效的进行削峰并使得流量曲线平滑。限流的目的是对并发访问和并发请求进行限速,或者一个时间窗口内请求进行限速从而来保护系统,一旦达到或超过限制速率就可以拒绝服务,或者进行排队等待等。

Swoft 限流器底层采用的是令牌桶算法,底层依赖于 Redis 实现分布式限流。

Swoft 限速器不仅可以限流控制器,也可以限制任何 bean 里面的方法,可以控制方法的访问速率。这里以下面使用示例详解

<?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 [&#39;requestLimiter2&#39;, $uri];
    }    
    /**
     * @param Request $request
     *
     * @return array
     */
    public function limiterFallback(Request $request): array
    {
        $uri = $request->getUriPath();        return [&#39;limiterFallback&#39;, $uri];
    }
}

key 这里支持 symfony/expression-language 表达式, 如果被限速会调用 fallback中定义的limiterFallback

Elegante Service-Governance

Dienstregistrierung und -erkennung

Der Microservice-Governance-Prozess umfasst häufig die Registrierung und den Start von Diensten für Cluster von Drittanbietern, z consul/etcd Warten Sie, in diesem Kapitel wird die Komponente swoft-consul im Swoft-Framework als Beispiel für die Implementierung der Dienstregistrierung und -erkennung verwendet.

Implementierungslogik
<?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(&#39;application&#39;);        
        // Print data
        var_dump($data);
    }
}

Service-Leistungsschalter

In einer verteilten Umgebung, insbesondere in einem verteilten System mit einer Microservice-Struktur, ruft ein Softwaresystem häufig ein anderes Remote-System auf. Der Angerufene dieses Remote-Aufrufs kann ein anderer Prozess oder ein anderer Host im Netzwerk sein. Der größte Unterschied zwischen diesem Remote-Aufruf und dem internen Aufruf des Prozesses besteht darin, dass der Remote-Aufruf möglicherweise fehlschlägt oder hängenbleibt, bis eine Zeitüberschreitung vorliegt. Was noch schlimmer ist: Wenn mehrere Anrufer denselben angehaltenen Dienst anrufen, ist es sehr wahrscheinlich, dass sich die Timeout-Wartezeit eines Dienstes schnell auf das gesamte verteilte System ausbreitet, was zu einer Kettenreaktion führt und das gesamte verteilte System viele Ressourcen verbraucht. Dies kann schließlich zu einem Systemausfall führen.

Der Leistungsschaltermodus soll Katastrophen verhindern, die durch solche wasserfallartigen Kettenreaktionen in verteilten Systemen verursacht werden.

Der grundlegende Leistungsschaltermodus stellt sicher, dass der Schutzanbieter nicht angerufen wird, wenn der Leistungsschalter im geöffneten Zustand ist. Wir benötigen jedoch auch zusätzliche Maßnahmen, um den Leistungsschalter zurückzusetzen, nachdem der Lieferant den Betrieb wieder aufgenommen hat. Ein möglicher Ansatz besteht darin, dass der Leistungsschalter regelmäßig erkennt, ob der Dienst des Lieferanten wiederhergestellt wurde, und nach der Wiederherstellung den Status auf „Geschlossen“ setzt. Beim erneuten Versuch befindet sich der Leistungsschalter im halboffenen Zustand.

Die Verwendung von Sicherungen ist einfach und leistungsstark. Verwenden Sie einfach eine @Breaker-Anmerkung. Sicherungen können in jedem Szenario verwendet werden, z. B. beim Aufrufen von Diensten Bei einem Dritten können Sie den Leistungsschalter ausschalten und herabstufen. Wenn der Dienst ausfällt, muss die Sicherung ausgeschaltet werden. Die Strombegrenzung ist das größte Werkzeug, um sich selbst zu schützen, egal wie viele Verbindungen vorhanden sind. Wenn das Backend damit nicht umgehen kann, bleibt das Frontend definitiv hängen .

Die aktuelle Begrenzung besteht darin, die Anzahl der gleichzeitigen Zugriffe und Anfragen beim Zugriff auf knappe Ressourcen wie Flash-Sales und Rush-Sale-Produkte zu begrenzen und so Spitzen effektiv zu reduzieren und die Verkehrskurve zu glätten. Der Zweck der Strombegrenzung besteht darin, die Rate des gleichzeitigen Zugriffs und der gleichzeitigen Anforderungen zu begrenzen oder die Rate der Anforderungen innerhalb eines Zeitfensters zu begrenzen, um das System zu schützen. Sobald die Ratenbegrenzung erreicht oder überschritten wird, kann der Dienst verweigert oder in die Warteschlange gestellt werden und wartete. 🎜🎜Swoft Die unterste Schicht des Strombegrenzers verwendet den Token-Bucket-Algorithmus, und die unterste Schicht verlässt sich auf Redis, um eine verteilte Strombegrenzung zu implementieren. 🎜🎜Swoft-Geschwindigkeitsbegrenzer kann nicht nur den aktuellen Controller begrenzen, sondern auch die Methoden in jeder Bean begrenzen und die Zugriffsrate der Methode steuern. Hier ist eine detaillierte Erklärung mit dem folgenden Anwendungsbeispiel 🎜rrreee🎜key Dies unterstützt symfony/expression-sprache-Ausdrücke. Wenn die Geschwindigkeit begrenzt ist, wird der in definierte <code>limiterFallback verwendet fallback wird aufgerufen. Methode 🎜🎜Konfigurationscenter🎜🎜 Bevor wir über das Konfigurationscenter sprechen, ist es uns nicht unbekannt. Es bietet uns die Möglichkeit, das Programm dynamisch zu ändern Lauffähigkeiten. Um jemand anderen zu zitieren: 🎜🎜🎜Dynamische Anpassung der Fluglage während der Systemlaufzeit! 🎜🎜🎜Ich könnte meinen Job als Reparatur von Teilen in einem schnell fliegenden Flugzeug bezeichnen. Wir Menschen können nicht immer alles kontrollieren und vorhersagen. Für unser System müssen wir immer einige Steuerleitungen reservieren, um Anpassungen vorzunehmen, wenn wir die Systemrichtung steuern müssen (z. B. Graustufensteuerung, Strombegrenzungsanpassung). Dies ist besonders wichtig für die Internetbranche, die Veränderungen begrüßt. 🎜🎜Für die eigenständige Version nennen wir es die Konfiguration (Datei); für das verteilte Clustersystem nennen wir es das Konfigurationscenter (System); 🎜🎜Was genau ist das verteilte Konfigurationscenter? Geschäft, Microservices Mit der Aktualisierung der Architektur nimmt die Anzahl der Service- und Programmkonfigurationen zu (verschiedene Microservices, verschiedene Serveradressen, verschiedene Parameter), und die herkömmliche Konfigurationsdateimethode und Datenbankmethode können die Anforderungen der Entwickler an das Konfigurationsmanagement nicht mehr erfüllen: 🎜
  • 安全性:配置跟随源代码保存在代码库中,容易造成配置泄漏;
  • 时效性:修改配置,需要重启服务才能生效;
  • 局限性:无法支持动态调整:例如日志开关、功能开关;

因此,我们需要配置中心来统一管理配置!把业务开发者从复杂以及繁琐的配置中解脱出来,只需专注于业务代码本身,从而能够显著提升开发以及运维效率。同时将配置和发布包解藕也进一步提升发布的成功率,并为运维的细力度管控、应急处理等提供强有力的支持。

关于分布式配置中心,网上已经有很多开源的解决方案,例如:

Apollo是携程框架部门研发的分布式配置中心,能够集中化管理应用不同环境、不同集群的配置,配置修改后能够实时推送到应用端,并且具备规范的权限、流程治理等特性,适用于微服务配置管理场景。

本章以Apollo 为例,从远端配置中心拉取配置以及安全重启服务。如果对 Apollo 不熟悉,可以先看Swoft 扩展 Apollo 组件以及阅读 Apollo 官方文档。

本章以 Swoft 中使用 Apollo 为例,当 Apollo 配置变更后,重启服务(http-server / rpc-server/ ws-server)。如下是一个 agent 例子:

<?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(&#39;application&#39;);        
        // Print data
        var_dump($data);
    }
}

以上就是一个简单的 Apollo 配置拉取,Swoft-Apollo 除此方法外,还提供了更多的使用方法。

官方链接

  • Github
  • Doc
  • swoft-cloud/community

推荐学习:php视频教程

Das obige ist der detaillierte Inhalt vonWie implementiert man Microservices mit PHP?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:csdn.net. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen