Читая PHP-дайджест, мы в Evapps наткнулись на интересную новость — вовсю идёт голосование по [RFC] Fibers. В двух словах — это попытки внести немного асинхронности в монолитно-синхронное до сих пор выполнение PHP-кода. А там, глядишь, и до многозадачности недалеко. Но это пока лишь мечты. А в реальности, как оказалось, существует сервис, который УЖЕ создал многопоточность в PHP. Называется он Swoole. Кстати, в новом пакете Laravel — Laravel Octane — под капотом будет использоваться именно этот сервис, Swoole. Об этом рассказал создатель Laravel Тейлор во время презентации пакета.
Рассказывать о Swoole с нуля кажется бессмысленным, так как уже есть люди, которые не просто покрутили сервис на тестовом сервере, но и перевели на него свой проект, получили отличный результат, о котором и отчитались. Хотим с вами поделиться этим отчётом. Представляем перевод статьи основателя компании Appwrite Элдада Фукса Moving From Nginx+FPM to Swoole Has Increased Our PHP API Performance by 91%.
В прошлом месяце мы выпустили Appwrite 0.7 со множеством новых функций. Одно из главных нововведений — мы перешли со стека Nginx + PHP FPM на использование Swoole в качестве HTTP-сервера.
В Appwrite мы создаем бесплатную альтернативу Google Firebase — платформу с открытым исходным кодом, которую можно разместить самостоятельно в любой инфраструктуре. Наш стек состоит из набора контейнеров Docker, использующих архитектуру микросервисов, что позволяет быстро масштабировать и отлаживать отдельные компоненты, составляющие серверный API. Наш backend API является хорошей отправной точкой для создания новых веб-проектов, мобильных проектов или проектов Flutter. Продукт «?из коробки» предлагает готовые к использованию модули аутентификации (Auth), хранилище (Storage), базы данных (Database), облачные функции (Cloud Functions) и другие стандартные API-интерфейсы, которые требуются любому приложению, занимающемуся обработкой данных пользователей и разрешений.
Как мы используем Swoole
Swoole — это высокопроизводительные, масштабируемые, параллельные TCP, UDP, Unix Socket, HTTP, WebSocket сервисы с PHP и простым в использовании Coroutine fiber API. Используя Swoole, мы имеем всего один многопоточный процесс, запущенный на нашем HTTP-сервере, что позволяет обработчику HTTP-запроса разделять память между несколькими пользователями. С таким подходом мы можем поддерживать постоянные соединения с БД и избегать повторной инициализации приложения с нуля для каждого пользователя, что помогает эффективнее использовать память и процессор.
Кроме того, Swoole дает возможность использовать корутины (Coroutine). Корутины Swoole подобны корутинам в других языках или фреймворках. Swoole создаёт по одной корутине на каждый запрос и выполняет их, основываясь на IO статусе каждого запроса. Swoole идёт со встроенными асинхронными клиентами Redis, MySQL, Postgres, позволяя повысить производительность.
Использование Swoole в качестве веб-сервера отлично подходит при разработке системы для работы в архитектуре микросервисов, подобной нашей. Вместо того, чтобы иметь один контейнер с Supervisord для управления всеми процессами Nginx, FPM и PHP, работающими в фоновом режиме, каждый из наших контейнеров Docker имеет один-единственный процесс в качестве точки входа, который намного проще масштабировать, отлаживать и отслеживать. Вы можете использовать Nginx и PHP в отдельных контейнерах, но они не являются нативными для Docker, и такое их использование ведёт к дополнительным накладным расходам.
Benchmarks
Чтобы оценить улучшения, мы протестировали различные сценарии в версиях 0.6.2 и 0.7.0. Мы выполняли запросы к нескольким конечным точкам (точкам входа, endpoints) с запросами на чтение и на запись. Все запросы были направлены на конечные точки, которым требуется аутентификация и контроль за злоупотреблениями, то есть на функции, которые выигрывают от этих улучшений.
Оба теста выполнялись на одном и том же оборудовании и не были направлены на то, чтобы продемонстрировать максимальную производительность Swoole. Цель тестирования заключалась в том, чтобы сравнить работу новой и старой версий. Результаты ниже относятся к 5-минутному нагрузочному и стресс-тестированию с 500 одновременными клиентами, использующими K6.
Версия 0.6.2
Как видно на скриншоте, только 98% всех запросов были успешными. Остальные закончились тайм-аутом из-за перегрузки.
Версия 0.7
С версией 0.7 все выглядит иначе. Все запросы, которых было почти в два раза больше, успешно выполнены, а времени на ответ потребовалось примерно вдвое меньше.
Результаты
С учетом всех факторов полученные результаты означают, что производительность увеличилась примерно на 91%. Благодаря Swoole наш стек стал намного быстрее и проще в обслуживании. Фактически онлайн-тесты показывают, что Swoole + PHP с легкостью опережает популярные альтернативы Node.js и Python и не сильно отстает от компилируемых языков, таких как GO.
Такое повышение производительности — часть действий, которые мы предпринимаем, чтобы дать разработчикам возможность в полной мере использовать свои серверы на основе Appwrite. Мы предоставим больше информации о процессе разработки и тестах Appwrite при запуске новых версий.
Мы благодарим команду Swoole за поддержку и помощь в процессе миграции, который был на удивление простым и быстрым. Буквально за пару дней мы добрались до первой рабочей версии всего нашего API.
Что дальше?
Если вы заинтересовались Appwrite (https://appwrite.io), ознакомьтесь с руководствами по началу работы для Web, Flutter или Server, а также присоединяйтесь к нашему сообществу Discord, где мы обсуждаем Appwrite с более чем 1300 соавторами платформы.
Также вы можете посетить наши проекты на Github, запросить новые функции в Github issues и ознакомиться с будущими спецификациями функций в репозитории Appwrite RFCs.
xxxcoltxxx
А если вы откажетесь от бутстрапа, то вы увеличите скорость еще в несколько раз. Конечно, зависит от самого кода эндпоинта, но бутстрап фреймворка — это очень дорого. Особенно laravel
mrBarabas
Вот если совсем честно, пусть меня «закидают камнями», но мое мнение такое — что под капотом не столь важно (тут важно только удобство разработки во всех смыслах), но самое главное, это отдавать кэш, в любом случае есть накладные расходы на фреймворк, даже собственный с нуля и это легко решается кэшем даже в случае с Laravel,yii и т.д.
xxxcoltxxx
А ты попробуй реши) Ты в любом случае будешь тратить время на бутстрап, даже если это все будет в опкодах. Если ты используешь цже загруженный фреймворк (как например, в воркерах очереди laravel), ты вообще исключаешь момент загрузки фреймворка. Даже 5 мс на каждый запрос при высоком рпс может сыграть большую роль. А если у тебя блог домашнего котика с низкой посещаемостью, то тебе и swoole не нужен)