![](https://habrastorage.org/getpro/habr/upload_files/71e/ed6/303/71eed63036613946be175e664f522b72.png)
В этой статье рассказывается, как использовать PHP для построения архитектуры микросервисов. Так как PHP идет в ногу со временем, он способен поддерживать микросервисные архитектуры для больших систем.
Проблема сервитизации
При использовании traditional framework (laravel, yii, symfony) для реализации микросервисов на Php эффекта очень мало.
Почему?
В режиме разработки fpm, поскольку резидентная память не может быть предоставлена, каждый запрос должен начинаться с нуля, начиная с загрузки процесса, чтобы потом выйти из него, добавляя много бесполезных накладных расходов.
Кроме того, соединение с базой данных не может быть использовано повторно и не защищается, потому что fpm является процессно-ориентированным, и количество процессов fpm также определяет и число параллельных процессов. Таковы проблемы, с которыми мы столкнулись при обычной разработке fpm.
Он недостаточно дружелюбен к микросервисным инструментам, таким как docker, и полагается на nginx для предоставления услуг.
Таким образом, вот причины, по которым Java сейчас более популярна как интернет-платформа по сравнению с PHP. Помимо PHP non-memory resident, существует множество других проблем, требующих решения.
Теперь давайте посмотрим, как Swoft имплементирует микросервис.
Что такое Swoft?
Swoft — это фреймворк корутин для микросервисов PHP, основанный на расширении Swoole. Как и Go, Swoft имеет встроенный веб-сервер и общий клиент для корутин, и является резидентным в памяти, независимым от традиционного PHP-FPM.
Здесь есть Go-подобные языковые операции, гибкие аннотации, аналогичные фреймворку Spring Cloud, мощный контейнер для внедрения глобальных зависимостей, комплексное управление сервисами, гибкое и мощное AOP (Aspect Oriented Programming), стандартная реализация спецификации PSR (PHP Standards Recommendations) и так далее.
Swoft Github
Что нам нужно для создания микросервиса?
-
Высокопроизводительный фреймворк для приложений
-
Регистрация и обнаружение услуг
-
Автоматическое переключение услуг
-
Ограничение услуг
-
Конфигурационный центр
Да, в Swoft все уже готово
Высокая производительность Swoft
Вы можете представить, какие преимущества дает нам резидентная память.
-
Фреймворк инициализируется только один раз; мы можем сосредоточиться на обработке запросов, потому что фреймворк инициализируется в памяти только один раз при запуске для резидентной памяти
-
Мультиплексирование соединений; если мы не используем пул соединений, тогда к чему приводит создание соединений для каждого запроса, этого не могут понять некоторые инженеры. Это приводит к чрезмерному использованию ресурсов бэкенда. Для некоторых основных сервисов, таких как Redis, базы данных, соединения оказываются дорогостоящим расходом ресурсов.
Итак, есть ли подходящее решение? Ответ — да, и многие используют фреймворк под названием Swoft. Swoft — это RPC (Remote Procedure Call)-фреймворк с функциональностью Service Governance. Swoft — это первый фулл-стек PHP-фреймворк, резидентный в памяти, корутинный, базирующийся на основной концепции Spring Boot согласно которой соглашение важнее чем конфигурация.
Swoft обеспечивает более элегантный способ использования RPC-сервисов, таких как Dubbo, имеет отличную производительность, схожую с Golang. Вот результат стресс-теста производительности Swoft на моем PC.
![](https://habrastorage.org/getpro/habr/upload_files/f24/1a7/373/f241a737357991816aca2f7165c94f30.png)
Скорость обработки данных в стресс-тесте ab очень впечатляет. С процессором i7 generation 8 и памятью 16GB на 100000 запросов уходит всего 5s. Такого быстродействия практически невозможно достичь в режиме разработки fpm.
Данного теста также достаточно, чтобы продемонстрировать высокую производительность и стабильность Swoft.
Регистрация и обнаружение сервисов
В процессе управления микросервисами часто требуется регистрация сервисов, инициированных на сторонних кластерах, таких как consul/etcd. В этой главе для осуществления регистрации и обнаружения сервисов используется компонент swoft-consul в составе фреймворка Swoft.
![](https://habrastorage.org/getpro/habr/upload_files/9f9/f9e/69b/9f9f9e69b9c6657dd1f11fc6e1293205.png)
Логика реализации
<?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; } }
Сервисный автоматический выключатель
В базовом режиме автоматический выключатель гарантирует, что поставщик не будет вызван, когда он находится в разомкнутом состоянии, однако нам также необходим дополнительный метод сброса автоматического выключателя после возобновления обслуживания поставщиком.
Одно из возможных решений заключается в том, что автоматический выключатель периодически определяет, возобновлено ли обслуживание. Как только оно возобновляется, он устанавливается в закрытое положение. При повторной попытке состояние становится полуоткрытым.
![](https://habrastorage.org/getpro/habr/upload_files/b05/900/485/b05900485289a3bb3639f7042aece7a4.png)
Использование предохранителя является простым и мощным. Он может быть аннотирован с помощью @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 использует алгоритм token bucket
, а основной слой опирается на Redis для реализации распределенного ограничения потока.
Ограничение потока Swoft не только ограничивает контроллеры, оно также ограничивает методы в любом бине и контролирует скорость доступа к методам. Ниже приводится пример с подробным объяснением.
<?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]; } }
Здесь поддерживается выражение symfony/expression-language. Если скорость ограничена, будет вызван метод limiterFallback
, определенный в fallback
.
Прежде чем перейти к обсуждению центра конфигурации, давайте поговорим о конфигурационном файле. Он нам хорошо знаком. С его помощью мы можем динамически изменять программу. Вот чья-то цитата об этом:
Динамическая регулировка полета системы во время выполнения
Для автономной версии мы называем его конфигурацией (файлом); для распределенной кластерной системы мы называем его центром конфигурации (системой);
В этой главе в качестве примера используется Apollo для извлечения сервисов конфигурации и безопасного перезапуска из удаленного центра конфигурации. Если вы не знакомы с Apollo, вы можете сначала посмотреть на компонент Apollo расширения Swoft и прочитать официальную документацию Apollo.
В этой главе в качестве примера используется Apollo в Swoft. При изменении конфигурации Apollo перезапустите службу (http-server
/ rpc-server
/ ws-server
). Ниже приведен пример агента:
<?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-фреймворк, этого достичь очень сложно. Но с помощью Swoft все гораздо проще.
Материал подготовлен в рамках курса «PHP Developer. Professional».
Всех желающих приглашаем на двухдневный онлайн-интенсив «Пишем микросервисный бэкенд на PHP». На занятии:
— Познакомимся с понятием контейнеризации на примере Docker и принципами в работе с контейнерами;
— Сложим понимание термина микросервис и построим инфраструктуру для приложения, состоящего из двух микросервисов;
— Узнаем как работают Nginx и PHP-FPM в связке и внедрим их в созданные микросервисы.
>> РЕГИСТРАЦИЯ
ссылка на оригинал статьи https://habr.com/ru/articles/580264/
Добавить комментарий