"How to run 200+ PHP services in production without losing your mind?", Yurii Panaiotov
2.
Let's get acquainted
➢Solutions Architect at Silpo (E-commerce)
➢ In IT since 2008 (17 years of experience)
➢ Has experience in various roles (full-stack, backend,
team lead, architect, CTO)
➢ Prints on a 3d printer for PrintArmy
3.
➢ 10+ millionorders during this last 3 years
➢ 6+ million unique Guests
Silpo E-commerce in Numbers
➢ IT specialists: 370+
➢ Teams: 35 (26 product teams + 9 service
teams)
➢ Releases: 30K+
➢ Merge requests: 50K+
4.
Offline Shops
Silpo E-commerce
andEcosystem
Today we’ll talk about…
➢ Products: 14+
➢ Service and microservices: 400+
➢ RPS: 4k+
➢ Requests per month: 6B+
➢ Total Data Served per month: 30TB+
PHP Frameworks hell
●Team have the
ability to choose
the framework
● Only team with
knowledge of specific
framework can efficiently
make changes in service
● Cross teams code review
will not be efficient
● The issue solved in one
service can appear in the
other
Pros: Cons:
Symfony Framework
● Oneof the most
popular PHP
Frameworks
● Big and active
community
● Single approach
through all teams,
only business logic
is different
● Efficient cross teams
code review
● Performance overhead
(if out of the box)
● Configuration-heavy
● Development Speed
Pros: Cons:
11.
Fixing Cons (Configuration-heavyand Development Speed)
Service Pack:
● Provides a set of required public and custom
Symfony bundles and configs with meaningful
default values (Configuration-heavy)
● Creating a new service: just require the Service
Pack via Composer and you’re ready to go
(Development Speed)
● Centralized fixes applied to all services at once
(Development Speed)
Client interaction
● Clientcan get
access to any data
(can save time
during
development)
● Client can get access to
any data (security issue)
● Client knows about
backend architecture
● Refactoring or any
change on the backend
must be supported with
frontend
● Each service can be
accessed from the
outside
Pros: Cons:
Client interaction: APIGateway
● Single endpoint can
merge data from
different services
● Services are not
accessible from the
outside
● Client doesn’t know
about backend
architecture
● Single point for
monitoring and
alerting
● Can be a bottleneck
● Needs add proxy for
service endpoints
(development
overhead)
Pros: Cons:
16.
Service to servicesync interaction
● Any service can
get any
information from
other service
● Chaotic service to
service connections
● Very hard to
understand all
dependencies
Pros: Cons:
Service to servicesync interaction: API Gateway
● Strict service to
service interaction
pattern
● Each service
knows only about
API Gateway
● Single point for
monitoring and
alerting
● Can be a bottleneck
● Needs add proxy for
service endpoints
(development overhead)
Pros: Cons:
API web server
Keepin mind:
● One process per container in
k8s pod
● Each OpenSwoole worker has
its own php environment and
keeps the code in memory
● !!! Each worker maintains its
own persistent PHP state
across requests !!!
23.
OpenSwooleBundle
Main features:
● ControlsOpenSwoole server
(start/stop/reload/status)
● Integrates OpenSwoole request/response
handling with Symfony
● Ensures all state-dependent services
reset their state on each request
● Enables parallel execution of functions via
OpenSwoole coroutines
…
Clear state code example:
Errors and tracing:Sentry
● Async error & trace export via
OpenSwoole task workers
● Custom implementation of Sentry
HttpClientInterface to use OpenSwoole
task workers under the hood
● Doesn’t affect request/response latency
● Track 100% of errors and warnings
● Sample traces for 1% of requests, with
the ability to enforce tracing for specific
request
36.
Errors and tracing:Sentry Alert Example
Alerts as a code Sentry alert
Slack alert
Autoscaling: First Iteration
Formulafor KEDA
triggers:
query: sum(rate(http_requests_total{service="ecom--order-service"}[1m]))
threshold: "20"
How it works:
● Metric from Symfony
● Each pod can handle ~20 RPS safely
● If traffic grows → more pods
● If traffic drops → fewer pods
Traffic increase (RPS)
Pods scaled up to 13
40.
Autoscaling: Second Iteration
Formulafor KEDA
triggers:
query: ((sum(openswoole_workers_total - openswoole_workers_idle) / sum(openswoole_workers_total)) + 0.5) * kube_deployment_status_replicas_available
threshold: "1"
How it works:
● Metric from OpenSwoole
● Scales pods by worker load: when
workers are near full, add pods
41.
Development Gates
● Cross-teamcode reviews
● Tests are part of the Definition of Done
● Static analyzers: PHPStan, PHPMD, PHPCP, etc.
● SonarQube rules and gates
● Security checks: dependency vulnerabilities, OWASP, SAST, secret detection
43.
Our custom Symfonybundles are public now
https://github.com/silpo-tech
● OpenSwooleBundle
● RestBundle
● ExceptionHandlerBundle
● PaginatorBundle
● HealthCheckBundle
● FilterBundle
● … and more on GitHub
44.
300 UAH promocode for SilpoApp https://jobs.dou.ua/companies/silpo/vacancies/
Silpo (E-commerce) vacancies
Editor's Notes
#11 Розповісти про те що у нас є Service Pack. Такий собі бандл бандлів для Symfony. Маючи це, ми сильно спрощуємо створення нових сервісів і пришвидшуємо швидкість розробки.
#12 Розповісти про те що у нас є підключення стандартних бандлів та ліб (можуть бути публічні, або наші кастомні). Далі у нас є структура підключення бандлів і конфігурацій аналогічна сімфоні. Ну і найголовніший секрет/хак. Ми екстендимо кернел сімфоні і додаємо йому можливість завантаження бандлів та конфігурації сервіс паку. В тому числі якщо розробник у своєму сервісі захоче перевизначити дефолтні конфігурації, то він це зможе робити, бо логіка завантаження сімфоні завжди має пріорітет над бандлами сервіс паку.
#22 Обов’язково сказати про те що workers - для обробки реквестів/респонсіт, а task workers - для важких асинхронних операцій
#37 Приклад трейсінгу. Це приклад доволі складного ендпоінта в якому є ланцюжок сервісів які викликають один одного, але ми все одно маємо можливість бачити вкладені трейси завдяки шаред хедеру X-Trace-ID та стандарту OpenTelementry. Якщо вам здалося що в даному прикладі є паралельні спани (тобто паралельні виконання деяких функцій), то вам не здалося. Це також реалізовано завдяки OpenSwoole корутінам. Цей фукнціонал називається батч раннер. Його було створено одним з наших розробників і він є частиною нашого кастомного OpenSwoole Symfony Bundle
#42 Впевнений, майже у кожного з вас виникло до мене питання - Юра, ти розповідаєш як у вас все класно, але ж ви написали багато кастомного коду? Ти просто хизуєшся чи шо?
Я підготувався до цього питання і у мене є аж 3 відповіді:
1. Ну, тепер ви знаєте що так можна і це перевірено продакшеном одного з найбільших еком проектів України… Не дуже, відповідь, так?
2. Ви можете зааплаїтися на наші вакансії і працювати в такому стеку (куар код та посилання будуть на останньому слайді)... Вже трошки краще, але все ж таки не ідеально, так?
Добре, тоді у мене є третя відповідь - переключаюсь на наступний слайд
#43 Всі наші кастомні базові бандли та бібліотеки ми віддаємо в опен сорс і тепер ви можете спробувати наші підходи. Тестуйте, експеремінтуйте, контріб’ютьте, створюйте іщюси. Будемо раді взаємодії та новим ідеям.