Closed clemask closed 1 year ago
Feel free to work on it! š
Octane is a great project that is pushing Laravel in a new direction in the realm of the internet, making Laravel more powerful. However, there seem to be some issues with the way it's being handled in certain aspects. Octane's support for Swoole has excited many developers, including myself, envisioning a strong combination of Laravel's ecosystem with Swoole's coroutine advantages.
One crucial point that is not clearly stated in the official documentation is the inability to use Swoole's coroutine. This omission is significant because developers might unknowingly configure coroutine parameters, expecting Octane to work seamlessly with Swoole's coroutine features. However, Octane does not disable the creation of Swoole services with coroutine parameters, leading to subtle issues in the production environment. Problems like network connections being used by other coroutines and issues with Monolog log cycling detection can arise. In the end, developers are forced to disable coroutines as a quick solution, which is a severe incident.
I hope the official team promptly considers adding coroutine support to their roadmap. It's a fantastic feature that not only enhances Laravel but is also crucial for the broader PHP ecosystem.
I hope the official team promptly considers adding coroutine support to their roadmap.
This isn't a trivial thing to do. Right now we don't have the time to work on this ourselves but we'd love to see PR's kickstarting this.
Hey @driesvints, are you familiar with @themsaid's talk from Laracon 2021 on how Swoole coroutines could be integrated into Octane? This is the timestamp: https://youtu.be/-l8o4KMaS4c?feature=shared&t=1792
That change has already been merged into Swoole core: https://github.com/swoole/swoole-src/pull/4330
I'm not sure how difficult it would be to implement, but it'd increase Laravel's performance by a whole order of magnitude.
Welcoming prs š
If you want octane to support coroutine, you must first make database, redis, etc. support connection pooling.
I guess the problem is Laravel supports a lot of DB and cache backends and itād be hard to implement pooling for them allā¦
@taylorotwell @driesvints @nunomaduro Would the core team be interested in having pooling for a select few drivers? Maybe just MySQL and Redis to start. Itād mean coroutines could only be enabled when using those drivers, but Hyperf can handle 100k req/second. Even if coroutines āonlyā bumped Laravelās concurrency to 10k-20k, thatād be nuts and create some serious buzz. Thatās faster than Nodeā¦
FYI @huangdijia is a key Hyperf contributor: https://github.com/hyperf/hyperf/commits/master. He might be willing to help if you guys want to move ahead.
@binaryfire I review all PRs - merging just depends on added complexity / maintenance burden. š
It would be amazing feature for highload apps!
Can this be related? š
Can this be related? š
No thatās not related. Running a few tasks concurrently is different to workers that can properly handle multiple requests per second, which requires db connection pooling etc. I donāt think thereās much interest from the core team in increasing Laravelās performance beyond the current Octane implementation, which only helps by keeping the app booted in memory. It doesnāt use Swoole coroutines at all.
If you want to handle 40k - 100k req/s in real life workloads instead of Octaneās 500-ish, youāll need to either run a bunch of Octane instances behind a load balancer, or look at a proper coroutine framework like Hyperf. The performance difference is night and day.
People who say ~500 req/s is enough just arenāt building certain kinds of apps. Eg. a log ingestion app, API gateways etc. Even a core team member has written articles about adding Go to a Laravel app stack to handle endpoints which receive high numbers of requests, which clearly demonstrates Laravelās performance limitations.
Shipping more features seems to be a higher priority than a major upgrade to performance. This kind of change, and the refactoring that would be required (eg. adding db connection pooling) wonāt ever come from a third party PR. It would need be be driven by the core team.
Hyperf is heavily inspired by Laravel so there are plenty of code references there the core team could look at.
Can this be related? š
No thatās not related. Running a few tasks concurrently is different to workers that can properly handle multiple requests per second, db connection pooling etc. I donāt think thereās much interest from the core team in increasing Laravelās performance beyond Octane, which only helps by keeping the app booted in memory.
So if you want to handle 40k - 100k req/s in real life workloads instead of Octaneās 500-ish, youāll need to either run a bunch of Octane instances behind a load balancer, or look at a PHP framework like Hyperf.
People who say 500 req/s is enough just arenāt building certain kinds of apps. Eg. a log ingestion app, an API gateway etc. Even a member of the core team has written articles about adding Go to a Laravel app stack to handle endpoints which receive high numbers of requests, which is saying something.
Shipping more features seems to be a higher priority than any major upgrades to performance. This kind of change and the refactoring (eg. adding db connection pooling) wonāt come from a third party PR. It would need be be driven by the core team.
The design idea of octane is still based on fpm,To get better performance, you need to redesign
Managed to get Laravel working with multiple Swoole coroutines in one process today. I still have allot of cleaning up to do before a PR, but I am confident it could be ok. Currently we got it working for a custom Kernel that processes sqs jobs for aws lambda, but to get it working for the http kernel is trivial. By Friday, I'll have it up and running in multiple processes as well (probably already works, but needs further testing).
@taylorotwell , @nunomaduro , is this still of interest?
Managed to get Laravel working with multiple Swoole coroutines in one process today. I still have allot of cleaning up to do before a PR, but I am confident it could be ok. Currently we got it working for a custom Kernel that processes sqs jobs for aws lambda, but to get it working for the http kernel is trivial. By Friday, I'll have it up and running in multiple processes as well (probably already works, but needs further testing).
@taylorotwell , @nunomaduro , is this still of interest?
This will be the most long-awaited and amazing feature for all highload Laravel projects!
This kind of change, and the refactoring that would be required (eg. adding db connection pooling) wonāt ever come from a third party PR. It would need be be driven by the core team.
Interestingly enough I did run into this today with testing multiple processes with multiple coroutines each. Database pooling is kinda of a solved problem upstream in openswoole at least (I am using openswoole atm).
https://github.com/openswoole/openswoole/blob/master/example/src/Coroutine/MySQLClientPool.php
Also available: Redis, Postgres.
Going to implement a mysql and redis pool next, which seems to be the last step I need to get the whole thing running blazingly fast. It is actually quite amazing how fast everything is.
@SMFloris Nice! Iād suggest using Swoole rather than Openswoole for testing - all Swoole development happens there. The whole āsecurityā thing was blown completely out of proportion by the Openswoole guy who now just repackages Swoole by himself to try and steal some brand recognition.
Also one of the core Swoole maintainers (@deminy) has said heās happy to answer questions to help: https://github.com/swoole/swoole-src/pull/4330#issuecomment-1837271923
Re: the performance difference - yeah Iāve used Hyperf for several high load projects and the difference is night and day. It can handle approx 40x more req/s than Laravel Octane thanks to being built with coroutines from the ground up. Pretty comparable to Go. Companies are building game server backends with it, which is pretty nuts for a PHP framework.
IMHO properly implementing coroutines in Laravel would open up the framework to a whole group of devs who would never have considered PHP otherwise.
@huangdijia is a core Hyperf contributor and might be willing to review your PR too
Iād also suggest posting some benchmarks with your PR to show the performance benefits.
@binaryfire thanks for your input! Will use Swoole going forward.
I was just thinking that the level of speed is at the level of Go as well.
What I'll do after implementing the pooling connections as well (I'm trying not to hack to much, doing things the Laravel way as much as possible) is that I'll create a repo with a docker compose so that anyone can run the benchmark easily.
What sort of things would be nice to benchmark? I'm thinking of a route that simply returns an OK status and a route that does some inserts or reads from the database. I personally want to compare: simple Laravel behind nginx, laravel octane as it currently is and laravel octane with all the bells and whistles from coroutines.
This weekend I made some headway;
Turns out there are allot more stuff to wire together than I thought initially.
Why not using coroutine hooks?
It don't need to change code base, just hooking the PHP C code interface.
We can enable it by calling \OpenSwoole\Runtime::enableCoroutine();
before worker start.
I've tried it as issue #906 mentioned but encountered some issues in binding process.
@SMFloris can you possibly push your changes so another person can pick up from where you are at or assist.
@SMFloris Is there any new progress?
To anyone being passionate about this feature, I recommend reading https://openswoole.com/article/isolating-variables-with-coroutine-context.
As I see it, simply flipping the switch to do Runtime::enableCoroutine
and implementing connection pooling would result in a buggy behaviour throughout the app, due to the number of static variables that would essentially get shared between all of the coroutines. You can look at how Octane currently has to reset the state of the container inside each worker before processing a request.
There appears to be an architectural problem with static variables which wouldn't let us use coroutines as of right now. All of that state which is being reset has to be stored in the coroutine context rather than globally.
I'll also look into this later.
Upd: Not just static variables, many of the container instances have to be retrieved from the coroutine state rather than just reset.
https://laravel-hyperf.com/ @binaryfire
https://laravel-hyperf.com/ @binaryfire
Can it be migrated safely, easily and quickly?
No yet. The project is at alpha stage.
https://laravel-hyperf.com/ @binaryfire
Can it be migrated safely, easily and quickly?
Currently the laravel ecosystem is not supported, such as horizon, telescope, etc.
No yet. The project is at alpha stage.
Hyperf is a completely different framework. The starter project Deeka linked to is just arranged in a way thatāll be familiar to Laravel devs. Directory structure etc.
You canāt swap out Laravel for Hyperf in an exisiting project. It would require significant rewriting.
No yet. The project is at alpha stage.
Hyperf is a completely different framework. The starter project Deeka linked to is just arranged in a way thatāll be familiar to Laravel devs. Directory structure etc.
You canāt swap out Laravel for Hyperf in an exisiting project. It would require significant rewriting.
We migrated a module from our Laravel-Monolith to Hyperf, to run it as a separate Service. We only had to setup the bootstrapping (Services/middlewares and so on). For the business logic, we copied over the models, the controllers and everything was working almost out of the box.
We migrated a module from our Laravel-Monolith to Hyperf, to run it as a separate Service. We only had to setup the bootstrapping (Services/middlewares and so on). For the business logic, we copied over the models, the controllers and everything was working almost out of the box.
Yeah it's great for microservices. We have several high traffic services using Hyperf - the performance difference is massive. The framework was heavily inspired by Laravel and uses a forked coroutine-friendly version of Eloquent so it's easy for Laravel devs to pick up. Things like models are easy to move over but there are many additional considerations when building complex apps eg. the way Context works.
Not everything in the ecosystem can be ported over eg Livewire: https://github.com/hyperf/hyperf/issues/5517. We've gone all in on Livewire so unfortunately that makes Hyperf a no-go for our core apps. Also there's no first-party auth package since the framework is geared towards microservices. But it's our first choice for anything we have to break out.
https://laravel-hyperf.com/ @binaryfire
Can it be migrated safely, easily and quickly?
Currently the laravel ecosystem is not supported, such as horizon, telescope, etc.
I donāt know the usage of Horizon and Telescope. Compared with those using Laravel, it should be relatively low. It would be very exciting if it could support the migration of Laravel projects. @huangdijia
I donāt know the usage of Horizon and Telescope. Compared with those using Laravel, it should be relatively low. It would be very exciting if it could support the migration of Laravel projects. @huangdijia
Welcome to learn about and use Hyperf. It can be accessed via the documentation (https://hyperf.wiki) to Learn about it.
Hello everyone,
I'm the creator of the Laravel Hyperf project. This project is currently in its final stage before the first dev release. I've migrated most components from Laravel to make them coroutine-friendly while striving to maintain a similar development experience to Laravel.
From my perspective, implementing full coroutine support in the Laravel framework presents significant challenges for several reasons:
Laravel's components weren't designed with coroutines in mind. This means all states would need to be isolated within the coroutine context, as @osbre mentioned. Laravel Octane's approach of resetting states after each request doesn't address this fully. For instance, if a singleton object needs to be shared across coroutines, the reset mechanism becomes ineffective.
Swoole introduced a max_concurrency
setting (see here) to enable Laravel Octane to support coroutines with limited restrictions. When max_concurrency
is set to 1, the worker won't accept new requests until the current one is completed. While this ensures coroutine safety and allows for state resets, it essentially makes coroutines an alternative concurrency feature in Laravel without improving QPS performance, as a worker can still only handle one request at a time.
Even if Laravel Octane were to support full coroutines in the future, it would necessitate significant breaking changes in Laravel components. All states would need to be safely stored using context, which would have a substantial impact on the third-party ecosystem.
The complexity of migrating from Laravel to Laravel Hyperf depends on the extent of state management and third-party packages used in your project. If you're considering migration, keep in mind:
In conclusion, I highly recommend trying Laravel Hyperf for new projects with intensive I/O requirements. However, if you're planning to migrate an existing Laravel project, be prepared for necessary modifications and consider the ecosystem implications carefully.
For current Hyperf users, you can also refer to firendsofhyperf for some useful packages.
Even if Laravel Octane were to support full coroutines in the future, it would necessitate significant breaking changes in Laravel components. All states would need to be safely stored using context, which would have a substantial impact on the third-party ecosystem.
No need to introduce breaking changes, They need to fork laravel/framework and continue developing the fork version. @themsaid
Trying to integrate Swoole into PHP-FPM-based (PHP-) Frameworks (like, Laravel) is entirely (and, philosophically) a wrong direction to go.
People who want to enjoy modern (CSP based) Asynchronous PHP-Programming will need to shift the paradigm of their thought Process from PHP-FPM based frameworks to "Asynchronous Programming Paradigm".
They (PHP-FPM and Swoole) both utilise entirely different OS-concepts and entirely different programming concepts, and entirely different Application Architectures. Swoole is just like Go, VertX, Netty, Erlang, Tornado etc.
We really look forward to Octane supporting Swoole coroutines, which will bring higher performance and solve more business scenarios. We hope the official will include this in the roadmap as soon as possible.