Async PHP requests - php

So, I want to create an asynchronous web service in PHP. Why? Because I've a nice async front-end, but Chrome will block my requests if I have more than 6 active TCP connections. Of course I have read some similar questions like:
Async requests in PHP
Multiple PHP Requests Crashing Page
but these don't cover my question.
I installed pthreads with the intention that I would be able to make multiple requests in different threads so that my PHP wasn't blocking other requests(in my situation I start eg. a long process and I want to be able to poll if the process is still busy or not).
PHPReact seems to be a nice library(non-blocking I/O, async) but this won't work either(still sync).
Am I missing something or is this nowadays still not possible in PHP?
class Example{
private $url;
function __construct($url){
$this->url = $url;
echo 'pooooof request to ' . $this->url . ' sent <br />';
$request = new Request($this->url);
$request->start();
}
}
class Request extends Thread{
private $url;
function __construct($url){
$this->url = $url;
}
function run(){
// execute curl, multi_curl, file_get_contents but every request is sync
}
}
new Example('https://gtmetrix.com/why-is-my-page-slow.html');
new Example('http://php.net/manual/en/function.file-get-contents.php');
new Example('https://www.google.nl/webhp?sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8#q=php%20file%20get%20contents');
The ideal situation would be to make use of callbacks.
ps. I have seen some servers(like Node.js) that are providing this functionality, but I prefer a native approach. When this is not possible I'm really thinking of switching to Python, Java, Scala or some other language that supports async.

I can't really make sense of what you are doing ...
Asynchronous and Parallel are not interchangeable words.
Threads at the frontend of a web application don't make sense.
You don't need threads to make many I/O bound tasks concurrent; That is what non-blocking I/O is for (asynchronous concurrency).
Parallel concurrency seems like overkill here.
Regardless, the reason your requests appear synchronous is the way this constructor is written:
function __construct($url){
$this->url = $url;
echo 'pooooof request to ' . $this->url . ' sent <br />';
$request = new Request($this->url);
$request->start();
}
The Request thread will be joined before control is returned to the caller of __construct (new) because the variable goes out of scope, and so is destroyed (joining is part of destruction).

Related

How the Amphp parallel works?

I was reading about amphp, and I had a doubt about parallel
Example code:
<?php
require __DIR__ . '/vendor/autoload.php';
$client = new Amp\Artax\DefaultClient;
$promises = [];
$urls = [
"http://google.com.br",
"http://facebook.com.br",
"http://xat.com/",
"http://kobra.ninja/",
"http://wikipedia.com",
"http://manualdomundo.com.br",
"http://globo.com",
"http://gmail.com"
];
foreach ($urls as $url) {
$promises[$url] = Amp\call(function () use ($client, $url) {
// "yield" inside a coroutine awaits the resolution of the promise
// returned from Client::request(). The generator is then continued.
$response = yield $client->request($url);
// Same for the body here. Yielding an Amp\ByteStream\Message
// buffers the entire message.
$body = yield $response->getBody();
echo $url;
return $url;
});
}
$responses = Amp\Promise\wait(Amp\Promise\all($promises));
Is this code running all curl, or waiting for 1 to perform another?
This is using stream_select functionality. It is not running in parallel in the conventional way you are thinking of. It works by registering a callback to be invoked once streams are readable / writable and then returning when the specific promise you are waiting for is done. All other promises that are resolved in the meantime are completed and cached in their respective promise waiting for you to unwrap the value using yield or Promise::onResolve. Amp's event loop is what is managing the multiple sockets and handling the concurrency for you.
If you want a basic example of how this works, I put a sample project on GitHub that is two classes, but is based on Curl instead of stream_select: https://github.com/kwhat/requestful
The first 7 methods are all that is required to setup the promise interface. All of the magic here is based on the two callbacks passed to the constructor as well as the wrappers around the then/cancel callbacks.
The sendRequestAsync method is how the concurrent Curl requests are created. The magic all happens in the callback for wait() on any promise, which calls an anonymous function that intern calls the tick method in a loop. That tick() method is what resolves all of the promises, regardless which one you call wait on.
As you can see from Amp codebase, it will run all your requests inside the same event loop.
Given your requests are being yielded (yield $client->request($url)), and they are being yielded inside the same event loop, they are being dispatched concurrently.
I recommend you reading this article through, specially the "Async development: how Amp framework works" section. I think it will make it a bit clearer how the engine works behind the scenes.
Hope this was helpful. Cheers! :)

How to pass some data to a running thread in PHP?

So let's say I create a thread and detach it from the main process, and start it.
So, after the thread is detached, how is it possible to pass some chunks of data like strings, or ints to the already running thread?
Edit
What I am basically doing is trying to implement the WS protocol:
<?php
// Pseudo-Code
class LongRunningThread extends \Thread {
private $handshakeReq;
public function __construct(Request $handshakeRequest) {
$this->handshakeReq = $handshakeRequest;
}
public function run() {
// Do handshake
// But do not exit, because after the handshake is done the socket connection needs to be maintained.
// Probably some trigger which notifies that a new message is here and the message arrives <automagically>
if(trigger) {
$message = $message;
$this->onNewWsMessage($message);
}
}
public function onNewWsMessage(string $rawMessage) {
// Process the message...
}
}
$stream = stream_socket_server(sprintf("tcp://%s:%d",
"localhost",
1337
), $errno, $errmsg);
// Boiler plate, and connection acceptance (blah blah blah)
// $client is the the accepted connection
$message = fread($client, 4096);
// Cannot pass the $client in here because the instability of resources with threads
// as passing them here, apparently converts them to <bool> false
$longRunningThread = new \LongRunningThread($message);
$longRunningThread->start() && $longRunningThread->join();
I found various answers related to passing data to a running thread, but I couldn't find any specifically for PHP.
I am using pthreads
The actual question is quite vague.
What you want to do falls to my understanding under the IPC (interprocess communication) and can be implemented with a couple of ways (to my knowledge the most common one is :http://php.net/manual/en/function.stream-socket-pair.php).
I would suggest though that you could use some kind of queueing and polling system like rabbitmq to pass around messages.It will provide some overhead but its a well known and highly used solution

Dependency injection php website

The more I read about dependency injection the more I get confused. I know what it is for, that is not the problem. Trying to do some design on paper this is what I came up with and somehow it seems to me I am overlooking something.
First I imagined building an actual server that would accept incoming requests and returns responses to the user.
class Server {
private $responseBuilder;
public function __construct($responseBuilder) {
$this->responseBuilder = $responseBuilder;
}
public function run() {
// create socket, receive request
$response = $this->responsebuilder->build($request);
// send response
}
}
class Response {
private $method;
private $message;
private $url;
// getters & setters
}
class ServerBuilder {
public build() {
// construction logic
return new Server(new ResponseBuilder());
}
}
Since Apache is used to handle server requests we could replace the server with something that just send the response.
$bldr = new ResponseBuilder();
$response = $bldr->build();
// send response some way
Note that ResponseBuilder has direct access to the request ($_SERVER['..'])
and so it has everything it needs to choose the right response.
PHP however allows us to build and send responses inline. So we could have a Controller object for each page or something else that send the response and have a builder for that.
$bldr = new ControllerBuilder();
$controller = $bldr->build();
$controller->run();
class ExampleController implements Controller {
public function run() {
header("HTTP/1.1 404 Not Found");
echo 'sorry, page not found';
}
}
This all makes sense to me. But let's look at the server example again.
It calls $responseBuilder->build() and gets a response back. But this would mean that the builder (or other builders if we split it) is also responsible for anything else that might occur like authenticating a user, writing to the database,... and I can't get my head around the fact that writing to a database would be part of the object graph construction.
It would be like: Send me your request. Oh you want the homepage? I will build you your response and while I'm at it I will also do some things that have nothing to do with building it like logging what I just did and saving some of your data in a cookie and sending a mail to the administrator that you are the first visitor on this page ever, ...
You should decouple them. You have a few assumptions that I think are a bit strange. Let's start with them.
The main purpose of an incoming http request is to give back some html
I have built PHP backends that only return JSON, instead of HTML. I had a really strong border between back and front end. I only used the backend to give me data from the database, or add/edit data in the databse. The front end was just a PHP script that would build the pages any way i wanted.
Since it is the web there is in theory no use for setters since
everything can be injected in the constructor
You could use the constructor, but you don't have too. You can use setters. Dependency injection is actually just turning the flow around.
You are on the right track though. You want some class that is responsible for building your pages. So, make it only responsible for your building your pages, and take out the other responsibilities. Things like logging, authentication etc should be outside of that.
For instance if you want logging, you could have your builder create your page, and your logger could then listen to all the things your builder is doing (with the observer pattern for instance). So if your builder says: "i created the home page", you can log it with your logger, who is actually listening to your builder.
Authentication for instance should happen even before your builder starts. You don't want your builder to go to work if you can already figure out that a user is not supposed to be on a page. You could use a database for that, and whitelist any usertype/pagerequest combination.
Then for data handling, i would create a backend, that only handles requests that are supposed to give back data, or save it. The front end could then communicate to get it's content by pulling it.
I hope this clears up a few things, but I'll be happy to answer more indept questions.

How to implement event driven code in PHP?

Is it possible to implement event driven program in PHP?
Something like javascript.
As an example, try to open a socket(open_socket) and execute some other command(do_something_else) instead of waiting for the success response of socket request.
After getting the success response execute callback_execute.
//--------------------------------------------------------------------
public function open_socket(){
$this->socketResource = fsockopen($this->nodeIp,$this->portNumber);
}
public function callback_execute(){
fputs($this->socketResource,$command);
}
public function do_something_else{ xxxxx }
//--------------------------------------------------------------------
Non_blocking_function($obj->open_socket(),$obj->callback_execute());
$obj->do_something_else();
There is only a single thread in PHP. Therefore doing something useful whilst waiting for some event is not possible in PHP.
Some workarounds are available but probably not very reliable – especially not when you plan to write portable code. I would assume the workarounds are risky since the language does not have a concept of concurrency. It's therefore probably best to write multi-threaded code in another language (Java, Scala, …) and use PHP just for displaying the prepared results (if using PHP at all for such problems).

Best Practice for returning cross-site JSON response

I'm currently working on a small application that works like this:
When the user clicks a link, an Ajax GET request is fired.
The request hits a server-side PHP script.
The script, which requests information for another domain, retrieves a JSON feed.
The feed is then echoed back to the client for parsing.
I'm not really a PHP developer, so I am looking for some best practices with respect to cross-domain requests. I'm currently using file_get_contents() to retrieve the JSON feed and, although it's functional, it seems like a weak solution.
Does the PHP script do anything other than simply call the other server? Do you have control over what the other server returns? If the answers are No and Yes, you could look into JSONP.
You might want to abstract the retrieval process in PHP with an interface so you can swap out implementations if you need too. Here is a naive example:
interface CrossSiteLoader
{
public function loadURL($url);
}
class SimpleLoader implements CrossSiteLoader
{
public function loadURL($url)
{
return file_get_contents($url);
}
}
Comes in handy if you need to test locally with your own data because you can use a test implementation:
public ArrayLoader implements CrossSiteLoader
{
public function loadURL($url)
{
return json_encode(array('var1' => 'value1', 'var2' => 'value2'));
}
}
or if you just want to change from file_get_contents to something like curl

Categories