Comments 60

После прочтения статьи остались вопросы. Скорость на синтетических тестах — это, конечно, хорошо, но как обстоят дела с памятью и отказоустойчивостью? Вот, например, разработчики Phoenix говорят, что не имеют проблем при работе с огромными (порядка миллиона, если мне не изменяет память) количествами коннектов по вебсокету к одной ноде. С другой стороны у go могут начаться проблемы из-за сборки мусора.
Я так и не понял, в чём преимущество вашего фреймворка перед Symfony, Laravel или Phalcon? Symfony мне нравилась тем, что в ней всё работает, как в доках, пусть даже они и не всегда хорошие, а код на ней получается очень чистым, без лишнего хлама. Laravel простая, как пять копеек, даже не смотря на отвратительную производительность, полный треш в пакетах и чудачества eloquent, у неё всё равно есть своя область применения. У вас я открыл быстрый старт в документации, а там мне предлагают писать обработку аннотаций роутера или пользоваться каким-то странным классом с шаблонным кодом. Я что-то не так понял или и правда нужно нажимать так много лишних кнопок? Ну, да, пёс с ним, пользователи Лары как-то живут с её роутингом и ничего. Вы пишете, что в основном в фреймворк используется в b2b, но я так и не смог придумать ни одной причины, почему там нужно использовать интеграцию с го и не хватит просто php или питона, например. На каких задачах он сможет полноценно раскрыть свой потенциал?

почему там нужно использовать интеграцию с го и не хватит просто php или питона, например.

Если вопрос в принципе про использование сервера приложений roadrunner, он убирает оверхед на создание инстанса приложения на каждый запрос, что даёт хороший буст производительности, и легко добавляется даже в уже существующие приложения, в т.ч. на Symfony/Laravel.
Не понятно, за счет чего возникает «хороший» прирост производительности. Особенно если добавить это в существующее приложение на, допустим, laravel.
Не понятно, за счет чего возникает «хороший» прирост производительности. Особенно если добавить это в существующее приложение на, допустим, laravel.

За счёт того что не нужно инициализировать всё приложение, зависимости, сервисы и т.п. на каждый запрос, работа идёт в скрипте-демоне.
Конечно, неэффективный код приложения, если таковой есть, не особо ускорится, ну и нужно будет учитывать при разработке, что процесс после запроса не завершится и не почистит всё за собой.
что процесс после запроса не завершится и не почистит всё за собой

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

Именно так, придётся писать приложения как это принято в любом другом языке программирования.


Задача фреймворка как раз упростить разработку таких приложений и избавить вас от большинства багов.

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

C#, Java, Scala, NodeJS, да практически всё что угодно ― на них сервера пишут именно так.

Спасибо за большой комментарий.


Скорость на синтетических тестах — это, конечно, хорошо, но как обстоят дела с памятью и отказоустойчивостью?

Все хорошо, мы написали rr как раз для того чтобы приложения выдерживали резкие нагрузки. Память зависит от количества воркеров и объема вашего приложения. Про поведение сервера под нагрузками можно почитать тут — https://habr.com/ru/post/431818/ (на ядре Symfony).


Я так и не понял, в чём преимущество вашего фреймворка перед Symfony, Laravel или Phalcon? Symfony мне нравилась тем, что в ней всё работает, как в доках, пусть даже они и не всегда хорошие, а код на ней получается очень чистым, без лишнего хлама. Laravel простая, как пять копеек, даже не смотря на отвратительную производительность, полный треш в пакетах и чудачества eloquent, у неё всё равно есть своя область применения.

Мы больше склоняемся к модели Symfony, но используем работу как со стеком (middleware) Laravel. Код не сильно отличается от этих фреймворков, и, пожалуй, не должен отличаться. Плюсом можно назвать то что для запуска даже сложного приложения вам не потребуется ставить зоопарк инструментов.


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

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


Вы пишете, что в основном в фреймворк используется в b2b, но я так и не смог придумать ни одной причины, почему там нужно использовать интеграцию с го и не хватит просто php или питона, например. На каких задачах он сможет полноценно раскрыть свой потенциал?

Сейчас мы пишем в основном распределенные проекты, в таких приложениях вы можете получить максимальную пользу от фреймворка за счет встроенных инструмент.

По поводу роутинга, у вас есть уникальная возможность перенести его в golang часть (только для Spiral), передавая в аттрибутах PSR-7 выбранный роут и параметры.

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

Мне непонятно, почему нет тестов чистых golang фреймворков? Я просто сильно сомневаюсь, что скрестив гепарда с улиткой вы выиграете в производительности у гепарда.

Мне непонятно, почему нет тестов чистых golang фреймворков? Я просто сильно сомневаюсь, что скрестив гепарда с улиткой вы выиграете в производительности у гепарда.

Вряд ли у ребят есть цель обогнать golang по производительности

Привет, это именно PHP фреймфорк, так что с точки зрения PHP разработчика ничего не меняется. Golang компилируется в бинарный файл и не беспокоит вас своим присутствием.

так что с точки зрения PHP разработчика ничего не меняется

Как не меняется, если «после каждого запроса приложение должно зачищать за собой»?
Я тогда видимо не понял фразу "ну и нужно будет учитывать при разработке, что процесс после запроса не завершится и не почистит всё за собой.". В существующем приложении придется что-то менять или нет?

В приложении на spiral — нет, мы изначально разработали архитектуру для работы в режиме демона. Насчет существующего приложения не скажу, зависит от фреймфорка и вашего кода.

В приложении на spiral — нет, мы изначально разработали архитектуру для работы в режиме демона. Насчет существующего приложения не скажу, зависит от фреймфорка и вашего кода.

Ну, при желании, полагаю, можно наделать всякого нехорошего.

Но я бы сказал что писать приложения которые не готовы жить в формате демона и полагаются на перезапуск на каждый запрос — не очень хороший тон в принципе.
Roadrunner (особенно если поменять стартовый рекомендуемый бесконечный цикл воркера) прекрасно живет и в режиме «иногда умираем» и в режиме «нормально отрабатываем PSR-7» и даже «иногда инклудим файлы с ошибками синтаксиса, но всё равно сами встаём»

Подскажите, пожалуйста, что значит "архитектура для работы в режиме демона"? Может быть пример на словах, как вы архитектурно что то разрулили. Просто мне кажется дело в коде больше, чем в архитектуре. Либо я что то не понял..


Ps.Пробовали road runner, получили неплохой буст! Проект на симфони, код был готов к долгоживущим работам

Подскажите, пожалуйста, что значит «архитектура для работы в режиме демона»? Может быть пример на словах, как вы архитектурно что то разрулили. Просто мне кажется дело в коде больше, чем в архитектуре. Либо я что то не понял..


Типично:

Традиционно PHP на каждый запрос стартует, инициализируется, выполняет. Умирает целиком, нет необходимости очищать ресурсы по окончании запроса.

В режиме демона — нет старта частого. Нужно аккуратнее относится к ресурсам занимаемым.

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

А можно немного про стек вместо событий? Почему пришли именно к этому варианту. Какие, и есть ли, подводные камни? Интересный же наверное кейс.

Если кратко: стек может гарантированно заменять события, но не наоборот. При событиях обработка данных происходит вне контекста запроса, и требует множество костылей (before, after, stop propagation, priorities). Отдельно стоит отметить обработку ошибок, какая именно цепочка событий отработает предугадать сложно.


Если в приложении такое дебажить еще как-то можно, то в долгоживущем 60% проблем на ранних стадиях находилось в событиях и хуках.


Стеки же гарантированно ограничивают контекст приложения в момент запроса, если запрос заканчивается (ошибкой или нет) то вы гарантированно выйдете из стека и востановите состояние.


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

Мне непонятно, почему нет тестов чистых golang фреймворков? Я просто сильно сомневаюсь, что скрестив гепарда с улиткой вы выиграете в производительности у гепарда.


Дело не в этом.
А то давно бы весь мир писал только на Java или Go, а PHP и Python умерли бы.
Есть другие соображения, кроме производительности исполнения кода.

Скажем, как легко найти исполнителей на PHP и сколько они стоят.
И как легко и сколько — если Go.

Недостаток производительности сервера легко компенсируется небольшими деньгами.
А вот недостаток программистов — компенсируется только огромными деньгами.

Или большая скорость прототипирования на динамических языках против большей надежности на статических. А скорость для современного бизнеса — это крайне важно.
Скажем, как легко найти исполнителей на PHP и сколько они стоят.
И как легко и сколько — если Go.

Дык апологеты Go пишут что почти любого программиста можно за пару дней превратить в Go-программиста, в виду того, что язык спроектирован так, что его легко учить и можно чуть-ли ни с места в бой. Врут?


В моей предыдущей конторе несколько человек быстро перешло на Go и остались довольны. Как раз PHP разработчики.

Скажем, как легко найти исполнителей на PHP и сколько они стоят.
И как легко и сколько — если Go.


Дык апологеты Go пишут что почти любого программиста можно за пару дней превратить в Go-программиста, в виду того, что язык спроектирован так, что его легко учить и можно чуть-ли ни с места в бой. Врут?

В моей предыдущей конторе несколько человек быстро перешло на Go и остались довольны. Как раз PHP разработчики.


Изучить язык легко.
Практически любой.

Но вот изучение библиотек, инструментов, хотя бы просто узнать о существовании GoDoc, изучение специфических паттернов написания алгоритмов для именно этого языка. и т.п. «мелочи», а также когда вы на каждый чих лазаете по интернету в поиске «а как эту вещь сделать на этом языке» — это очень много времени, когда ваша производительность серьезно снижена. Нормальный миддл при переключении стека на время превращается в джуна — только и делает, что гуглит целыми днями.

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

Я «переключал стек» у новичков, что приходили к нам, занимало это 2 недели моего личного времени. Это было выгодно и перспективно и окупилось в течении 2-х лет, так как предполагалось (и предположения оправдались), что новички будут работать у нас минимум 2 года.

Но вот например сейчас мне уже через 1,5 месяца нужно выдать готовый продукт. Который сам по себе имеет хитрые ньюансики внутри, которые я еще не знаю как мы реализуем. А тут еще и новый стек? И в этих услових обучать новичков, а потом наблюдать за рушащимся сроками deadline — совсем не хочется. В этих условиях я возьму уже того, кто умеет.

Антон, интересно ваше мнение о модуле php для Nginx (аналогичен по архитектуре и возможностям популярной связке LuaJit/Nginx в OpenResty):

github.com/rryqszq4/ngx_php7

По бенчмаркам TechEmpower легко обходит Swoole, Workerman, Load Runner и даже (неожиданно) LuaJit и фреймворки на Go.
Интересно мнение о том насколько такой модуль в связке с Nginx может быть лучше или хуже чем RoadRunner — как я понимаю, и там и там общая часть приложения инициализируется один раз при загрузке.

Плюсы и минусы будут примерно такие же как у Swoole. Придется биндится на АПИ модуля и собирать его с nginx (php встраивается). Работать будет быстрее, модифицировать будет сложнее.

yii2 и symfony рядом по производительности с phalcon?
рукалицо, да в каких розовых снах вы такое увидели?)
В вашем тесте результаты:
yii2 | laravel | symfony | phalcon | spiral
14,984 | 5,654 | 7,056 | 12,430 | 34,644

а в оригинальном:
13,530 | 5,484 | 1,213 | 23,318 | 0

Если небольшое отличие для yii2 и laravel можно назвать погрешностью, улучшенные результаты symfony оптимизацией за последние полгода (с момента последнего официального пересчёта рейтинга), то просадку phalcon почти в 2 раза никак не объяснить. Что собственно и вызвало удивление у stanlee и у меня.

Я правильно понимаю, что ваши тесты были добавлены в код оригинального бенчмарка только относительно недавно (пару месяцев назад) и вы займёте какое-то место в общем рейтинге только где-то через полгода?
Тогда если ваши текущие результаты нанести на текущий общий рейтинг, то выглядеть он будет приблизительно так:



т.е. в среднем в два раза быстрее yii2, laravel, symfony и phalcon, и в 10 раз медленнее чем workerman и swoole.

Что ж, вам есть куда расти. Не останавливайтесь на достигнутом. Если до swoole, который на C++/C, будет сложно угнаться, то достигнуть результатов workerman, который написан на чистом PHP, это уже вполне реально.
У вас есть ещё полгода до общего пересчёта рейтинга, чтобы успеть показать ещё лучшие результаты.
Я правильно понимаю, что ваши тесты были добавлены в код оригинального бенчмарка только относительно недавно (пару месяцев назад) и вы займёте какое-то место в общем рейтинге только где-то через полгода?

Все верно, ждем следующий раунд.


Если до swoole, который на C++/C, будет сложно угнаться, то достигнуть результатов workerman, который написан на чистом PHP, это уже вполне реально.

Я не уверен что в принципе возможно обогнать чистый Swoole на полноценном фреймворке с ORM и шаблонами. Если смотреть на пример Symfony+Swoole то отставание на 29%, а не в 10 раз. До самого дальнего фреймворка на Swoole/Workerman отставание в 4-5 раз, чего трудно добиться без жертв со стороны архитектуры.

Я не уверен что в принципе возможно обогнать чистый Swoole на полноценном фреймворке с ORM и шаблонами.
Судя по всему в следующем раунде мы так же увидим swoft (фреймворк на основе swoole). Его код уже присутствует в бенчмарке. Будем ждать пересчёта. Будет на кого ориентироваться.
Судя по всему в следующем раунде мы так же увидим swoft (фреймворк на основе swoole). Его код уже присутствует в бенчмарке. Будем ждать пересчёта. Будет на кого ориентироваться.

Стоит упомянуть, что Swoft/Swoole асинхронные, в отличие от, так что в реальных приложениях при должном использовании они всегда будут быстрее.
То что они будут быстрее никто и не сомневался :)
Вопрос «насколько сильно».
Например, workerman на тестах медленнее swoole в два раза, а на моих задачах «всего» на 10-20%, но мне гораздо приятнее работать с workerman, чем со swoole, поэтому я готов на такие «жертвы», лишь бы не читать документацию на китайском, спрашивать у разрабов, за что отвечает тот или иной магический параметр, у которого нет описания даже на китайском и т.д. С workerman я могу в любой момент залезть в код и разобраться что там, и как и даже что-то поправить и отправить пуллреквест.
Чёрт, перешёл по второй ссылке из вашей статьи:
Полные бенчмарки доступны тут и тут.
Наверное вам в статье, тоже стоит поправить.

Имелось ввиду что там два набора бенчмарков. Это разные проекты.

Почему-то решил, что раз первая ссылка — результат бенчмарка, то вторая ссылка — код того же фреймворка, а не какого-то другого.
Теперь понятно, что перепутал.
Скажу в контексте RoadRunner, а не Spiral, от последнего использую только Spiral\RoadRunner\PSR7Client и Spiral\Goridge\StreamRelay.

Спасибо большое за вашу работу. Реквестирую расширить документацию к RoadRunner — реально по крохам между страницами приходится понимать базовые вещи (те же golang middlewares). Такое ощущение, что писатель документации взял за цель минимизировать количество текста, оставив только чистую эссенцию новой информации.

Ещё бы реквестировал доку или пример работы не через php-cli, а через php-cgi в командной строке. В теории оно должно работать, на практике пока сложновато продраться через дебри.

Ещё вопрос, почему внутри используется zend diactaros, а не laminas diactaros? То есть ругающийся composer update иногда настораживает.

Ещё вопрос, а возможно ли заменить тот же diactaros на другой? например, более быстрый Nyholm\Psr7?

Ещё вопрос, а не рассматривали подход с fasthhttp? В теории, так как воркеров ограниченное количество, можно сделать ± zero memory allocation работу, или хотя бы минимизировать это дело.
Ну и ещё вопрос: а можно ли STDIN и STDOUT пайпы (через которые гоняют данные PHP и golang) приспособить для вызова RPC методов? Я так понимаю, эти пайпы самый быстрый способ обмена между ними, быстрее чем линукс-сокеты или обычные локальные сетевые соединения?..

В теории go-часть может ждать в Stdout первый бит или байт, если он допустим, «1» — это означает, что сейчас придёт response, если он «2» — сейчас придёт вызов RPC от PHP части, надо будет обработать и передать ответ назад, а PHP часть в свою очередь будет считывать свой STDIN.

Можно, но для этого придется модифицировать протокол. Поддержка асинхронных клиентов задумана в 3й версии.

Ну и ещё вопрос: а можно ли STDIN и STDOUT пайпы (через которые гоняют данные PHP и golang) приспособить для вызова RPC методов? Я так понимаю, эти пайпы самый быстрый способ обмена между ними, быстрее чем линукс-сокеты или обычные локальные сетевые соединения?..


Unix-сокеты довольно шустрые.

Если для вашей задачи настолько важна производительность этой части — то есть смысл задуматься о смене языка PHP на что-то шустрое (тот же Go).

Но, практически, здесь socket/local net/etc не является узким местом. СУБД куда как более значительный тормоз вашей системы.

В теории go-часть может ждать в Stdout первый бит или байт, если он допустим, «1» — это означает, что сейчас придёт response, если он «2» — сейчас придёт вызов RPC от PHP части, надо будет обработать и передать ответ назад, а PHP часть в свою очередь будет считывать свой STDIN.

STDIN/STDOUT — это неудобно для мультиплексирования, но, да — возможно.
Посмотрите, к примеру, как реализован протокол WebSocket. Если отвлечься от того, что это сетевой протокол, то внутри он реализует обмен по одному потоку.
Я задумывался о теоретической возможности делать запросы к СУБД из golang, посылая результат в PHP, и тут как раз могут быть относительно большие потоки данных. Но да, вопрос больше теоретический.

(Отвечая на вопрос «зачем» — экспериментирую, можно ли сделать общий кеш запросов между всеми воркерами).
Я задумывался о теоретической возможности делать запросы к СУБД из golang, посылая результат в PHP

Тормозит сама СУБД.
А не связь с ней из Go или PHP. Поэтому без разницы.

Привет,


Такое ощущение, что писатель документации взял за цель минимизировать количество текста, оставив только чистую эссенцию новой информации.
Так и есть, покрыть такое количество материала достаточно сложно с первого раза.

Ещё бы реквестировал доку или пример работы не через php-cli, а через php-cgi в командной строке. В теории оно должно работать, на практике пока сложновато продраться через дебри.
CGI интеграцию еще не делали.

Ещё вопрос, почему внутри используется zend diactaros, а не laminas diactaros? То есть ругающийся composer update иногда настораживает.
В процессе переключения, ничего не хотим сломать.

Ещё вопрос, а возможно ли заменить тот же diactaros на другой? например, более быстрый Nyholm\Psr7?
Без проблем, фреймворк как раз и использует Nyholm по умолчанию.

Ещё вопрос, а не рассматривали подход с fasthhttp? В теории, так как воркеров ограниченное количество, можно сделать ± zero memory allocation работу, или хотя бы минимизировать это дело.
Есть в пайплайне, но большого прироста не ожидаем так как боттлнек на стороне PHP.
фреймворк как раз и использует Nyholm по умолчанию

Спасибо, покопался, отвечу сам себе и тем, кто зайдёт сюда через год:
$psr7 = new Spiral\RoadRunner\PSR7Client(new Spiral\RoadRunner\Worker($relay), new \Nyholm\Psr7\Factory\Psr17Factory());

Ещё вопрос, почему внутри используется zend diactaros, а не laminas diactaros? То есть ругающийся composer update иногда настораживает.

Войдет в 1.7.1 релиз. :)

Добрый день.
Не нашел в обсуждениии, но очень интересно — в 20 году планируется выход PHP8, RoadRunner и Spiral будут с ним работать? Наверное больше интересует будет ли корректно взаимодействовать RoadRunner с кодом на PHP8?

Добрый день. Не вижу ни одной причины почему код может не работать, с 7.4 у нас проблем нет, старую магию давно выпилили.

Т.е. сервер RoadRunner который написан на Go запускает PHP интерпритатор который установлен на машине где он запускается? Т.е. если я в конце года, когда выйдет PHP8, установлю новый php и RoadRunner будет с ним работать, но код так же должен быть написан на php8, а фреймворк spiral может отвалиться т.к. он написан под php7?

Spiral это PHP фреймворк, к моменту выхода PHP8 мы будем поддерживать эту версию.

Как любитель новых веяний в webDev — в противовес тяжеловесным традициям — какое то время присмативаюсь к spiral стэку. Пардон, не скажу про себя особо высоко как о знатоке backend языков/инструментов/паттернов.., но, суть, имя целью: 1) Обучение основам (и дальше/больше) вэб технологий в своём (пока) городе, в ср. азии, где население +-500тыс. 2) Смастерить вэб приложение административного (enterprise) типа для информ.оснащения некоего хозяйства (где отсутствие оперативной инфы встаёт в копеечку ), тут — к слову — создатели сети вилгуд автосервисов послужили эталоном…
В общем, мне со своей колокольни видеться, что: а) spiral фреймворк — детище принципально новое, где в придачу go-lang реально в пользу. б) Если при этом бенчмарки не врут и на деле значительный выигрыш в производительности + сделан акцент на упрощение разработки (сравнивая с тем же symfony, сам больше приверженец модульности). в) В окружении семейный ряд инструментов (RR!!, ORM, Toolkit etc.) для покрытия основной части нужд для полноценной фулстэк работы,
то определенно фреймворк достоен внимания, хотя и пока — понятно — без популярности дедов, но, хочу отметить, тут номером 1 стоит вопрос о полноте документации, и чтобы даже зеленый php ламер мумел по ней найти путь…
Честно, пока толком руки не доходят до практико-изучения сего инструмента, но, есть планы в скором засучить рукава, будем видеть :))
Only those users with full accounts are able to leave comments. Log in, please.