Search
Write a publication
Pull to refresh
41
0
Andrey Helldar @Helldar

Senior PHP Developer

Send message

Ну вот. А у меня VPS c двумя ядрами и 4 RAM... И файлы в нём же на NVMe локальном.

А у прода какая конфигурация? Само железо?

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

Касательно производительности самого сервера, то при дефолтных настройках ab тест на RoadRunner показывал около 145 rps, а FrankenPHP около 250 rps. PHP-Fpm при этом не замерял.

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

Содержимое файла .rr.yaml Laravel Octane формирует самостоятельно, но при запущенном инстансе он выглядит так (копипаст с прода):

Показать содержимое .rr.yaml
version: '3'
rpc:
    listen: 'tcp://127.0.0.1:6001'
server:
    command: 'php app.php'
    relay: pipes
http:
    address: '0.0.0.0:8080'
    middleware:
        - gzip
        - static
    static:
        dir: public
        forbid:
            - .php
            - .htaccess
    pool:
        num_workers: 1
        supervisor:
            max_worker_memory: 100
jobs:
    pool:
        num_workers: 2
        max_worker_memory: 100
    consume: {  }
kv:
    local:
        driver: memory
        config:
            interval: 60
metrics:
    address: '127.0.0.1:2112'

Также при старте создаётся ещё один файл - storage/logs/octane-server-state.json со следующим содержимым:

Показать содержимое octane-server-state.json
{
    "masterProcessId": 808,
    "state": {
        "appName": "Test App",
        "host": "127.0.0.1",
        "port": "9000",
        "rpcPort": "6001",
        "workers": 0,
        "maxRequests": "500",
        "octaneConfig": {
            "server": "roadrunner",
            "https": false,
            "listeners": {
                "Laravel\\Octane\\Events\\WorkerStarting": [
                    "Laravel\\Octane\\Listeners\\EnsureUploadedFilesAreValid",
                    "Laravel\\Octane\\Listeners\\EnsureUploadedFilesCanBeMoved"
                ],
                "Laravel\\Octane\\Events\\RequestReceived": [
                    "Laravel\\Octane\\Listeners\\CreateConfigurationSandbox",
                    "Laravel\\Octane\\Listeners\\CreateUrlGeneratorSandbox",
                    "Laravel\\Octane\\Listeners\\GiveNewApplicationInstanceToAuthorizationGate",
                    "Laravel\\Octane\\Listeners\\GiveNewApplicationInstanceToBroadcastManager",
                    "Laravel\\Octane\\Listeners\\GiveNewApplicationInstanceToDatabaseManager",
                    "Laravel\\Octane\\Listeners\\GiveNewApplicationInstanceToDatabaseSessionHandler",
                    "Laravel\\Octane\\Listeners\\GiveNewApplicationInstanceToFilesystemManager",
                    "Laravel\\Octane\\Listeners\\GiveNewApplicationInstanceToHttpKernel",
                    "Laravel\\Octane\\Listeners\\GiveNewApplicationInstanceToLogManager",
                    "Laravel\\Octane\\Listeners\\GiveNewApplicationInstanceToMailManager",
                    "Laravel\\Octane\\Listeners\\GiveNewApplicationInstanceToNotificationChannelManager",
                    "Laravel\\Octane\\Listeners\\GiveNewApplicationInstanceToPipelineHub",
                    "Laravel\\Octane\\Listeners\\GiveNewApplicationInstanceToCacheManager",
                    "Laravel\\Octane\\Listeners\\GiveNewApplicationInstanceToSessionManager",
                    "Laravel\\Octane\\Listeners\\GiveNewApplicationInstanceToQueueManager",
                    "Laravel\\Octane\\Listeners\\GiveNewApplicationInstanceToRouter",
                    "Laravel\\Octane\\Listeners\\GiveNewApplicationInstanceToValidationFactory",
                    "Laravel\\Octane\\Listeners\\GiveNewApplicationInstanceToViewFactory",
                    "Laravel\\Octane\\Listeners\\FlushDatabaseRecordModificationState",
                    "Laravel\\Octane\\Listeners\\FlushDatabaseQueryLog",
                    "Laravel\\Octane\\Listeners\\RefreshQueryDurationHandling",
                    "Laravel\\Octane\\Listeners\\FlushLogContext",
                    "Laravel\\Octane\\Listeners\\FlushArrayCache",
                    "Laravel\\Octane\\Listeners\\FlushMonologState",
                    "Laravel\\Octane\\Listeners\\FlushStrCache",
                    "Laravel\\Octane\\Listeners\\FlushTranslatorCache",
                    "Laravel\\Octane\\Listeners\\PrepareInertiaForNextOperation",
                    "Laravel\\Octane\\Listeners\\PrepareLivewireForNextOperation",
                    "Laravel\\Octane\\Listeners\\PrepareScoutForNextOperation",
                    "Laravel\\Octane\\Listeners\\PrepareSocialiteForNextOperation",
                    "Laravel\\Octane\\Listeners\\FlushLocaleState",
                    "Laravel\\Octane\\Listeners\\FlushQueuedCookies",
                    "Laravel\\Octane\\Listeners\\FlushSessionState",
                    "Laravel\\Octane\\Listeners\\FlushAuthenticationState",
                    "Laravel\\Octane\\Listeners\\EnforceRequestScheme",
                    "Laravel\\Octane\\Listeners\\EnsureRequestServerPortMatchesScheme",
                    "Laravel\\Octane\\Listeners\\GiveNewRequestInstanceToApplication",
                    "Laravel\\Octane\\Listeners\\GiveNewRequestInstanceToPaginator"
                ],
                "Laravel\\Octane\\Events\\RequestHandled": [],
                "Laravel\\Octane\\Events\\RequestTerminated": [],
                "Laravel\\Octane\\Events\\TaskReceived": [
                    "Laravel\\Octane\\Listeners\\CreateConfigurationSandbox",
                    "Laravel\\Octane\\Listeners\\CreateUrlGeneratorSandbox",
                    "Laravel\\Octane\\Listeners\\GiveNewApplicationInstanceToAuthorizationGate",
                    "Laravel\\Octane\\Listeners\\GiveNewApplicationInstanceToBroadcastManager",
                    "Laravel\\Octane\\Listeners\\GiveNewApplicationInstanceToDatabaseManager",
                    "Laravel\\Octane\\Listeners\\GiveNewApplicationInstanceToDatabaseSessionHandler",
                    "Laravel\\Octane\\Listeners\\GiveNewApplicationInstanceToFilesystemManager",
                    "Laravel\\Octane\\Listeners\\GiveNewApplicationInstanceToHttpKernel",
                    "Laravel\\Octane\\Listeners\\GiveNewApplicationInstanceToLogManager",
                    "Laravel\\Octane\\Listeners\\GiveNewApplicationInstanceToMailManager",
                    "Laravel\\Octane\\Listeners\\GiveNewApplicationInstanceToNotificationChannelManager",
                    "Laravel\\Octane\\Listeners\\GiveNewApplicationInstanceToPipelineHub",
                    "Laravel\\Octane\\Listeners\\GiveNewApplicationInstanceToCacheManager",
                    "Laravel\\Octane\\Listeners\\GiveNewApplicationInstanceToSessionManager",
                    "Laravel\\Octane\\Listeners\\GiveNewApplicationInstanceToQueueManager",
                    "Laravel\\Octane\\Listeners\\GiveNewApplicationInstanceToRouter",
                    "Laravel\\Octane\\Listeners\\GiveNewApplicationInstanceToValidationFactory",
                    "Laravel\\Octane\\Listeners\\GiveNewApplicationInstanceToViewFactory",
                    "Laravel\\Octane\\Listeners\\FlushDatabaseRecordModificationState",
                    "Laravel\\Octane\\Listeners\\FlushDatabaseQueryLog",
                    "Laravel\\Octane\\Listeners\\RefreshQueryDurationHandling",
                    "Laravel\\Octane\\Listeners\\FlushLogContext",
                    "Laravel\\Octane\\Listeners\\FlushArrayCache",
                    "Laravel\\Octane\\Listeners\\FlushMonologState",
                    "Laravel\\Octane\\Listeners\\FlushStrCache",
                    "Laravel\\Octane\\Listeners\\FlushTranslatorCache",
                    "Laravel\\Octane\\Listeners\\PrepareInertiaForNextOperation",
                    "Laravel\\Octane\\Listeners\\PrepareLivewireForNextOperation",
                    "Laravel\\Octane\\Listeners\\PrepareScoutForNextOperation",
                    "Laravel\\Octane\\Listeners\\PrepareSocialiteForNextOperation"
                ],
                "Laravel\\Octane\\Events\\TaskTerminated": [],
                "Laravel\\Octane\\Events\\TickReceived": [
                    "Laravel\\Octane\\Listeners\\CreateConfigurationSandbox",
                    "Laravel\\Octane\\Listeners\\CreateUrlGeneratorSandbox",
                    "Laravel\\Octane\\Listeners\\GiveNewApplicationInstanceToAuthorizationGate",
                    "Laravel\\Octane\\Listeners\\GiveNewApplicationInstanceToBroadcastManager",
                    "Laravel\\Octane\\Listeners\\GiveNewApplicationInstanceToDatabaseManager",
                    "Laravel\\Octane\\Listeners\\GiveNewApplicationInstanceToDatabaseSessionHandler",
                    "Laravel\\Octane\\Listeners\\GiveNewApplicationInstanceToFilesystemManager",
                    "Laravel\\Octane\\Listeners\\GiveNewApplicationInstanceToHttpKernel",
                    "Laravel\\Octane\\Listeners\\GiveNewApplicationInstanceToLogManager",
                    "Laravel\\Octane\\Listeners\\GiveNewApplicationInstanceToMailManager",
                    "Laravel\\Octane\\Listeners\\GiveNewApplicationInstanceToNotificationChannelManager",
                    "Laravel\\Octane\\Listeners\\GiveNewApplicationInstanceToPipelineHub",
                    "Laravel\\Octane\\Listeners\\GiveNewApplicationInstanceToCacheManager",
                    "Laravel\\Octane\\Listeners\\GiveNewApplicationInstanceToSessionManager",
                    "Laravel\\Octane\\Listeners\\GiveNewApplicationInstanceToQueueManager",
                    "Laravel\\Octane\\Listeners\\GiveNewApplicationInstanceToRouter",
                    "Laravel\\Octane\\Listeners\\GiveNewApplicationInstanceToValidationFactory",
                    "Laravel\\Octane\\Listeners\\GiveNewApplicationInstanceToViewFactory",
                    "Laravel\\Octane\\Listeners\\FlushDatabaseRecordModificationState",
                    "Laravel\\Octane\\Listeners\\FlushDatabaseQueryLog",
                    "Laravel\\Octane\\Listeners\\RefreshQueryDurationHandling",
                    "Laravel\\Octane\\Listeners\\FlushLogContext",
                    "Laravel\\Octane\\Listeners\\FlushArrayCache",
                    "Laravel\\Octane\\Listeners\\FlushMonologState",
                    "Laravel\\Octane\\Listeners\\FlushStrCache",
                    "Laravel\\Octane\\Listeners\\FlushTranslatorCache",
                    "Laravel\\Octane\\Listeners\\PrepareInertiaForNextOperation",
                    "Laravel\\Octane\\Listeners\\PrepareLivewireForNextOperation",
                    "Laravel\\Octane\\Listeners\\PrepareScoutForNextOperation",
                    "Laravel\\Octane\\Listeners\\PrepareSocialiteForNextOperation"
                ],
                "Laravel\\Octane\\Events\\TickTerminated": [],
                "Laravel\\Octane\\Contracts\\OperationTerminated": [
                    "Laravel\\Octane\\Listeners\\FlushOnce",
                    "Laravel\\Octane\\Listeners\\FlushTemporaryContainerInstances"
                ],
                "Laravel\\Octane\\Events\\WorkerErrorOccurred": [
                    "Laravel\\Octane\\Listeners\\ReportException",
                    "Laravel\\Octane\\Listeners\\StopWorkerIfNecessary"
                ],
                "Laravel\\Octane\\Events\\WorkerStopping": [
                    "Laravel\\Octane\\Listeners\\CloseMonologHandlers"
                ]
            },
            "warm": [
                "auth",
                "cache",
                "cache.store",
                "config",
                "cookie",
                "db",
                "db.factory",
                "db.transactions",
                "encrypter",
                "files",
                "hash",
                "log",
                "router",
                "routes",
                "session",
                "session.store",
                "translator",
                "url",
                "view",
                "App\\Http\\Webhooks\\MainHandler",
                "App\\Queries\\AdministratorQuery",
                "App\\Queries\\ChatQuery",
                "App\\Queries\\CommandQuery",
                "App\\Queries\\MemberQuery",
                "App\\Queries\\MessageQuery",
                "App\\Queries\\ModuleQuery",
                "App\\Queries\\RoleQuery",
                "App\\Services\\AdministratorService",
                "App\\Services\\ChatService",
                "App\\Services\\MemberService",
                "App\\Services\\MessageService",
                "App\\Services\\ModuleService",
            ],
            "flush": [],
            "tables": {
                "example:1000": {
                    "name": "string:1000",
                    "votes": "int"
                }
            },
            "cache": {
                "rows": 1000,
                "bytes": 10000
            },
            "watch": [
                "app",
                "bootstrap",
                "config\/**\/*.php",
                "database\/**\/*.php",
                "public\/**\/*.php",
                "resources\/**\/*.php",
                "routes",
                "composer.lock",
                ".env"
            ],
            "garbage": 50,
            "max_execution_time": 30
        }
    }
}

При этом, в команде запуска октана можно указать лишь уровень логов параметром --log-level:

'-o', 'logs.mode=production',
'-o', 'logs.level='.($this->option('log-level') ?: (app()->environment('local') ? 'debug' : 'warn')),
'-o', 'logs.output=stdout',
'-o', 'logs.encoding=json',

Вполне возможно что и дохлые. у Вас 8к RPS в каких условиях выполнялись? С самого сервера на себя же? Или комп запроса с сервером в разных странах? И сервер на VPS с двумя защитами от дудоса - один от CloudFlare, а вторая от хостинга?

Кода там нет никакого кроме роута, который я выложил. Конфиг роадраннера тоже дефолтный и составляется самим Laravel Octane в момент его запуска. Руками в файл нельзя лазить иначе его можно запросто сломать и он не будет запускаться.

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

По сути, всё что Вам нужно сделать для запуска нового проекта под roadrunner, это выполнить эти команды:

laravel new test && cd test
composer require laravel/octane spiral/roadrunner-cli spiral/roadrunner-http
php vendor/bin/rr get-binary

И, либо в супервизор конфигурацию воткнуть, либо руками локально запустить:

php artisan octane:start

Через htop не смотрел, не видел особого смысла, а у хостинга единый пик в статистике отображён:

Один из моих проектов через FPM отдавал данные примерно за 300-350 мс. С Октаном на RoadRunner возвращает примерно за 90-100мс.

Прогревом октан занимается при первом запросе к нему. Я проверял с точки зрения простейшего использования по принципу "установил зависимость - запустил фрейм - протестировал". Никаких улучшений и тонких настроек. Только дефолт. Только хардкор.

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

Октан был на RoadRunner.

Шутку понял. Смешно.

В данном контексте я говорил за админку, которая, по своей сути, является фреймворком. Тот же nuxt. Удобство использования измеряется в отношении конкретного продукта. Где-то он идеально подойдёт, а где-то будет мешать.

А бэкенд, конечно же, на фрейме Laravel. Здесь без вариантов 🙂

“Ого, очень интересно было бы узнать, на чем написаны эти самописные CMS. Остальная часть вроде совпадает с моими представлениями... Ну может WordPress я думал повыше будет…”

Александр Макаров

На прошлой работе CRM была написана на VueJs 2 с нуля и общалась с бэкендом по Rest API.

На текущей написан на React 18 и также общается с бэком по апи.

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

Но я бы не сказал что это прям CMS.

Я так и не понял в чем претензия

Если два живых примера не убедили, то на этом мои полномочия всё :)

если вы толкаете в значения херню, то и на выходе получаете херню

Всё так. И одно дело когда разработчик сам такое толкает, и совсем другое когда фреймворк к этому подталкивает.

Разве? Далеко ходить не будем:

Http::fake([
    'local1' => 99,
    'local2' => 100,
    'local3' => "100",
    'local4' => 204,
    'local5' => 204.01,
]);

$response = Http::get('local1');
$response->status; // 200
$response->body(); // 99

$response = Http::get('local2');
$response->status; // 100
$response->body(); // ""

$response = Http::get('local3');
$response->status; // 200
$response->body(); // 100

$response = Http::get('local4');
$response->status; // 204
$response->body(); // No Content


$response = Http::get('local5');
$response->status; // 200
$response->body(); // 204.01

Логично? :)

11.34 можно было использовать сокращённые массивы, но этот PR добавляет возможность задавать строку в качестве тела ответа или целое число для статус-кода.

В Ларе с этим есть проблемы. Статусом будет считаться число от 100 до 599 включительно. Всё остальное будет возвращено как тело ответа с кодом 200, а ещё 204 вернёт no content со статусом 204, а ‘204’ - вернёт текст «204» со статусом 200 😀

Обсуждения были в ветке с https://github.com/laravel/framework/pull/53663

Http::fake([
    'google.com' => 'Hello World', // no problem
    'github.com' => ['foo' => 'bar'], // no problem

    'bar.laravel.com' => '204', // it's a response body with status code 200

    'foo.laravel.com' => 99, // it's a response body with status code 200
    'foo.laravel.com' => 100, // it's a status code 100
    'foo.laravel.com' => 204, // it's a status code 204
    'foo.laravel.com' => 204.99, // it's a response body with status code 200
    'foo.laravel.com' => 599, // it's a status code 599
    'foo.laravel.com' => 600, // it's a response body with status code 200
]);

Учитывая что англосаксы исчезли в начале 7-го века, добитые норманнами, а сейчас 21-й век во всю набирает ход.

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

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

Хм... Конституция... Знакомое слово... Не слышал о ней лет так 20 с хвостиком.

Уже кричат ¯\_(ツ)_/¯

Официально ютуб стал тормозить потому что железки гугла устарели.

1
23 ...

Information

Rating
Does not participate
Location
Россия
Date of birth
Registered
Activity

Specialization

Backend Developer
Lead
From 350,000 ₽
PHP
MySQL
Git
OOP
Docker
Redis
SQL
Laravel
Elasticsearch