Skip to content

Instantly share code, notes, and snippets.

@farconada
Last active October 28, 2015 08:13
Show Gist options
  • Save farconada/d59445416bafd6a73b27 to your computer and use it in GitHub Desktop.
Save farconada/d59445416bafd6a73b27 to your computer and use it in GitHub Desktop.
Async HTTP integration with PHP
As a way to integrate microservices I want to use HTTP calls and avoid the use of a MQ (Message Queue).
If the app is small and contained in one host you could avoid the use of MQ.
Description of the scenario:
I have one app (made with Symfony. Call it MainApp) and one microservice (made with Sylex. Call MicroApp), both served using PHP-FPM NGINX
1) MainApp calls an URL POST /api/internal/do-something with Guzzle,
2) then MicroAPP do its work (it takes long)
3) MicroApp calls an URL from /api/internal/i-have-finished
To avoid keep MainApp waiting in 1). I've configured a very small guzzle timeout and it catches the exception. With this trick I have an Async HTTP call.
Are there any way to 2) in background without a MQ (and without anykind of worker proccess).
I'm tempted to use threads for 2) but I've read that they are only suitable for CLI (https://github.com/krakjoe/pthreads).
I've heard that Spring have async REST.
What's the best way to solve this scenario and avoid waiting for 2) ?
@grEvenX
Copy link

grEvenX commented Oct 23, 2015

Is this a possible solution on #2 for you: http://davedevelopment.co.uk/2011/12/02/handling-symfony-events-asynchronously.html (closing the request early, leveraging the event-system to continue processing data after it is closed)

@farconada
Copy link
Author

sorry It uses 0mq

@grEvenX
Copy link

grEvenX commented Oct 23, 2015

Sorry, that article wasn't that relevant, the top "notice" of the page was. Can't you use the kernel.terminate event to perform the long-running code? See http://symfony.com/doc/current/components/http_kernel/introduction.html#the-kernel-terminate-event for more information.

For a Silex specific example, see http://gonzalo123.com/2013/10/14/using-the-event-dispatcher-in-a-silex-application/

It might not work for you though because of this limitation:

Internally, the HttpKernel makes use of the fastcgi_finish_request PHP function. This means that at the moment, only the PHP FPM server API is able to send a response to the client while the server's PHP process still performs some tasks. With all other server APIs, listeners to kernel.terminate are still executed, but the response is not sent to the client until they are all completed

@ingluisjimenez
Copy link

@farconada as @grEvenX commented, you can either implement your code as a listener to the kernel.terminate event or you can manually call fastcgi_finish_request on the controller and after that point you can execute whatever logic you need in the background.

You'll need to make sure to set any headers on the response and set the content, before calling fastcgi_finish_request().

I don't have an example on Silex, but I'm using this on an App with an internal framework.

@farconada
Copy link
Author

this solution seems ok but only works with php-fpm I'll try it in a few minutes. thanks

@farconada
Copy link
Author

Dont you think that it will be a better solution with with threads? (pthreads are only available in CLI)

@farconada
Copy link
Author

Silex after() isn't the solution but $app->finish() do the work pretty well

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment