Replies: 2 comments
-
Yes. If there are four workers and all of them are working, no more requests can be processed until one of those is done.
PHP already has async processing: Fibers. As of this writing, there are no core functions using fibers, and FrankenPHP has a bug (#46) that only occurs if you output from a fiber. So, if all you're doing is work, you can send it to a fiber and finish the request. There are some great fiber-based libraries out there like ReactPHP, amphp, and phasync.
In general, this appears to be an application-level problem. You should architect your application such that http requests can return as quickly as necessary. If you don't need to wait for a long-running query to end, put it on a (work) queue using NATs, RabbitMQ, Beanstalkd, or whatever is most appropriate for your needs. From there, you should return a message that allows you to asynchronously check the status through polling, or use something like Mecure to send a completion message.
PHP is a share-nothing model. Once a request is started, PHP isn't designed to handle another request until the current one has finished. At least, if you want to use traditional methods for interacting with the request (super-globals, environment, etc) anyway. There are "ways around it" such as serving an HTTP server purely in PHP and passing request/response objects around. |
Beta Was this translation helpful? Give feedback.
-
I think it's not unfeasible to run PHP asynchronously with FrankenPHP, it would just be a lot of work to get there and as @withinboredom mentioned, the PHP ecosystem isn't quite ready for async. What would be necessary:
The alternative would be to just dynamically scale threads up to some limit. |
Beta Was this translation helpful? Give feedback.
-
Hello! I have a question regarding FrankenPHP async model. How does it work?
For example; I have a worker mode enabled with 4 workers, so I have 4 processes that handle incoming HTTP requests. Now, let's say each request needs to execute a heavy database query that takes 100 seconds. We have 4 incoming HTTP requests. What happens? Is the application totally blocked and cannot handle any further incoming HTTP requests because of workers exhaustion? Do I need to wait 100 seconds to be able to process more HTTP requests?
I am asking for a feature (or maybe it is already here? If yes, maybe it should be advertised more, because I could not find any information regarding this in the docs) - async IO processing.
We can look at C# async / await for reference;
https://learn.microsoft.com/en-us/ef/core/miscellaneous/async
https://learn.microsoft.com/en-us/aspnet/core/fundamentals/best-practices?view=aspnetcore-8.0
https://learn.microsoft.com/en-us/aspnet/core/fundamentals/best-practices?view=aspnetcore-8.0#avoid-synchronous-read-or-write-on-httprequesthttpresponse-body
https://learn.microsoft.com/en-us/aspnet/core/tutorials/first-web-api?view=aspnetcore-8.0&tabs=visual-studio#routing-and-url-paths
The main idea is to introduce an option in FrankenPHP to perform async operations.
When an async operation is performed (i.e.; a database query, an HTTP call to an external service, etc.) the worker process should be released and should be able to pick another task.
With this feature enabled, the above example would change significantly, because workers wouldn't be blocked by the IO operation any longer (a database query - the worker wouldn't wait until the database returned data [100 seconds of the blocked worker]), and would be ready to handle incoming HTTP requests. When database records are available, the process will continue the execution from the point of the last async operation (the database query here) and finish the execution. So the outcome will be; instead of handling only 4 requests simultaneously, we can now handle many more requests, because all the work is on the database side, not on the PHP (CPU) side.
Beta Was this translation helpful? Give feedback.
All reactions