Heim > Artikel > Backend-Entwicklung > Wie implementiert man Microservices mit PHP?
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.
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ösungFü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
Servitization
?服务化
给有那些亮点的特色呢 ?
系统服务化之后, 增加了依赖关系复杂, 也会增加服务与服务之间交互的次数. 在 fpm
的开发模式下. 因为无法常驻内存给我们带来了, 每一次请求都要从零开始加载到退出进程, 增加了很多无用的开销, 数据库连接无法复用也得不到保护, 由于fpm
是以进程为单位的fpm
的进程数也决定了并发数, 这也是是fpm
开发简单给我们带来的问题. 所以说为什么现在互联网平台Java
比较流行了,.NET
和PHP
在这方面都不行。PHP非内存常驻
的就不用说了。除此之外,还有很多其他问题需要解决。
你可以想象一下常驻内存给我们带来的好处 比如
只启动框架初始化 如果常驻内存我们只是在启动的时候处理化框架初始化在内存中,专心处理请求
连接复用,有些工程师并不能特别理解,如果不用连接池,来一个请求就发一个连接怎么样?这样就会导致后端资源连接过多。对一些基础服务来说,比如 Redis,数据库,连接是个昂贵的消耗。
那么有没有好的方案呢?答案是有的,而且很多人都在用这个框架,它就是-Swoft
。Swoft
就是一个带有服务治理
功能的RPC框架。Swoft
是首个 PHP常驻内存协程全栈框架, 基于 Spring Boot
Nach 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.
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-Generation
CPU, 16GB
Speicher unter
100.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 von
Swoft` zu beweisen,Swoft
提供了类似 Dubbo
更为优雅的方式使用 RPC
服务, Swoft
性能是非常棒的有着类似Golang
性能, 下面是我的PC
对Swoft
性能的压测情况.
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 * [ * 'host:port', * 'host:port', * 'host:port', * ] */ 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('Breaker exception'); } /** * @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 ['requestLimiter2', $uri]; } /** * @param Request $request * * @return array */ public function limiterFallback(Request $request): array { $uri = $request->getUriPath(); return ['limiterFallback', $uri]; } }
key 这里支持 symfony/expression-language
表达式, 如果被限速会调用 fallback
中定义的limiterFallback
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<?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); } }Service-Leistungsschalter
@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('application'); // Print data var_dump($data); } }
以上就是一个简单的 Apollo 配置拉取,Swoft-Apollo
除此方法外,还提供了更多的使用方法。
推荐学习: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!