Как стать автором
Обновить

Строим эффективный сетевой обмен в PHP-микросервисах

Время на прочтение13 мин
Количество просмотров20K
Всего голосов 43: ↑42 и ↓1+41
Комментарии38

Комментарии 38

Гм. Микросервисы на php. Звучит как cpu intensive на js.

Это реально смешно, кто сегодня микросервисы на пхп делает (кроме Авито :)

Авито делает микросервисы на PHP, Golang, Python

Может просто вы не умеете PHP готовить?

Ну и исторически - наше монолитное приложение написано на PHP, и портировать код не еняя язык в разы дешевле-)

Никогда не программировал на PHP, но много раз слышал нелестные отзывы об этом чудо-языке.

Все-таки "микросервисы на PHP" звучит реально смешно :-)

не видел, не знаю, но осуждаю.

Спасибо за статью!
Подскажите, а рассматривали еще какие-то варианты параллельных запросов к сервисам,
например, через очереди ?

Привет.

Рассматривали. И даже в ряде сценариев используем.

Но этот способ не очень подходит для интерактивных типов запросов - пока положишь в очередь пока вычитают, поработают, положат обратно, пока прочитаешь ответ.. + нужно вычитать именно свой ответ а не ответ на другой запрос, и оверхед от самой очереди..

Хорошо что у нас не php)

А зачем в закрытом контуре https? Чтобы героически его отключить?)

Привет.

Я легко могу представить больше одного сценария когда это оправдано. К примеру это требование сертификации при работе с персональными данными. Или желание защитить свои данные когда используешь не свое железо( MIM атаку никто не отменял)

Это вполне себе реальные риски. И прежде чем решить - http\https их надо оценить.

Справедливо, но ведь в таком случае и оптимизировать путем перехода на http - не выйдет.

Все так, не выйдет.

И поэтому я подсветил что эта опция не для всех подойдет.

И у нас все еще остаются другие способы оптимизации.

Спасибо за статью!
Подскажите, сколько по факту получилось сэкономить времени при реализации Reverse-proxy стратегии?
Т.е. например есть endpoint, он отдает инфу за 100мс, из них 80мс это http запрос к другому сервису. Сколько в таком случае получается сэкономить?

Боюсь я сильно конкретных цифр дать не смогу.

Оно все достаточно специфично под объемы нагрузки. Но из того чем могу поделится - уменьшения рейта ошибок до 5-10%, ускорение примерно до 5%.

до 5% звучит размыто :) Возможно сохранился какой-нибудь график, где после деплоя видно, что стало например на 1мс быстрее?

Пытался найти хоть один график, вдруг сохранился....но большую часть метрик мы уже флашнули. а что не флашнули - timeSeries схлопнула, и стало не очень нагялдно

Наших объемах фон ошибок уменьшился от 10% до 200% (то есть физически ошибок стало до 2х раз меньше)

Позволю влезть в ветку.
Поставили nginx-proxy перед внешним https-сервисом. Если ранее 3600 воркеров могли выполнять до 900 запросов без ошибок, а потом начинали валиться сетевые ошибки (разного рода - от резолва до коннект таймаутов), то с nginx-proxy, держащим до 1500 открытых коннектов до сервиса, без проблем держатся и 2k rps к внешнему сервису.
Задержки установления https-коннекта сошли на нет.

Но PHP не умеет работать в многопоточности (ждем PHP 8.1)

Подскажите, а чего именно мы там ждем? Если речь о Fibers, то они не предоставляют реальной многопоточности - это просто надстройка для упрощенной "ручной" остановки и продолжения некоего участка кода без потери контекста.

Все так. Но даже это позволит писать код, более адаптированный для неблокирующих операций. А там выйдет - найдем куда применить-)

  • Retry не работает для идемпотентных запросов.  

Не опечатка? Мне казалось только для идемпотентных и работает.

Спасибо!

и в правду.

FIXED

Graceful degradation увеличивает сложность и так непростой бизнес-логики в PHP-контроллерах.

Это наследие, или у вас реально БЛ в контроллерах?

в легси кусках монолита логика дейтвительно обитает в контроллерах (как хорошо, что таких кусков осталось очень мало)

А в целом - читай вместо контроллеров то место где лежит логика services, providers, domains, repositories

Спасибо за статью. Есть вопрос: если ретраи реализованы на reverse_proxy и выбрана стратегия фиксированого ретрая (например, 3 попытки с 1-секундным перерывом между ними), то процесс PHP всё это время висит ожидая ответа? И получает ошибку от reverse_proxy по истечении 3 секунд?

Привет, да. все верно описал, но не 3 секунды, а больше.

запрос: {таймаут 1сек}{задержка между попытками 1 сек}-{таймаут 1сек}{задержка между попытками 1 сек}-{таймаут 1сек}{задержка между попытками 1 сек}

Итого: 6 секунд

Но есть еще circuit breaker - который может ответить ошибкой мгновенно, без ожидания 6 секунд, если количество ошбок большое было

Вот уже и вышел PHP 8.1. Скажите, как с ним поменялась ваша оптимизация?

Не успела на самом деле: к моменту выхода в php почти не осталось сложного кода что обходит много сервисов. Все растащили по сервисам

А как планировалось?

А http2 не решает проблему поддержания keep alive соединений?

Её и http1.1 решает. Проблема-то не в протоколе, а в том чтобы это соединение реально сохранялось и переиспользовалось.


К примеру, короткоживущая программа не способна удержать соединение дольше чем живёт сама. А PHP в стандартном режиме использования "создан чтобы умирать", то есть очень короткоживущий.

Ну да, действительно. Это проблема для традиционных рантаймов, вроде php-fpm.
В swoole, workerman или просто в демонизированных процессах, получается, этой проблемы быть не должно.

Зависит от количества воркеров и того чем они занимаются. Cloudflare, к примеру, писали что "напоролись" на аналогичную проблему аж в nginx.


Но да, при обращении просто к сервисам такая проблема возникать не должна.

к слову - а почему "просто к сервисам" проблемы быть не может?

Потому что эта проблема тем острее, чем к большему количеству сервисов обращается программа и чем реже она обращается к каждому из них.


То есть чтобы проблема проявилась — надо сначала найти такой сервис, который будет обращаться к огромному количеству других сервисов, да ещё и в зависимости от запроса. А, и сам он должен существовать во многих инстансах. В нормальной архитектуре сюда может попасть только API gateway и всё.

Соглашусь - что такой тип проблем более свойственен api-gateway чем сервисам.

Просто есть composition сервисы, к примеру, сервисы не имеющие стейта, занимающиеся формированием ответа конечному пользователю и опрашивая другие сервисы.

Есть вообще graphQL - и там еще больше запросов может случится

Если я верно прочитал - на там напоролись с Nginx - это не только пулы соединений, но и не сбалансированная нагрузка по ядрам в зависимости от тяжести запроса. а в сервисах такое тоже вполне может случится.

Если сможете организовать коннекшн-пул в swoole, c возможностью переиспользования открытых соединений - то конечно-)

Натолкнувшись на этот пост в трекере я наконец-то понял о чём он вообще.


Автор, можно вопрос? Как вам вообще пришло в голову прокси, работающий на стороне приложения, обозвать обратным?

  1. приложение выступает тут тем самым клиентом. для которого скрыты все те абстракции что лежат под reverse proxy, включая балансировку, ретраи и прочее. Что в целом соответствует понятию reverse proxy

  2. если вместо reverse proxy использовать просто proxy - люди будут путаться еще сильнее - проверено на тестовой группе

  3. "Как вам вообще пришло в голову" - грубовато звучит, чет-)

Зарегистрируйтесь на Хабре, чтобы оставить комментарий