PHP WebSocket Async task - php

I have the following scenario:
I have a WebSocket running with Ratchet (PHP WebSocket)
I use the onMessage() callback function to handle incomming data and respond accordingly.
If I get the 'start-broadcast' message via the WebSocket I have to start a loop which will send out a broadcast message to all connected clients on the WebSocket every 0.2 sec. So I need to make a loop which can do this, but I can't put it into the onMessage() function, as this will block, and I won't be able to receive any more messages via the WS.
If I get the 'stop-broadcast' message via the WebSocket I have to stop the broadcast loop.
So basically I need a way to start and stop this loop, and have this loop running parallel to the WebSocket loop so it doesn't block up.
Problems: The Socket->send() method I'm pretty sure is not thread-safe, so I need to make sure that the WS loop and my broadcast loop are not trying to send a message at the same time.
Possible approaches I have considered:
ReactPHP/Promise
Somehow use this to make an async function inside which I have a loop. I have no experience with Promise, and I don't know if it can do what I need.
Running a spearate PHP-CLI process, and use ZMQ for inter-process communication between the WS instance and the Broadcast loop.
With this I could send message back and forth from the websocket, and
I could send a message to start or stop the broadcast, also I could
send a message from the broadcast loop to the WS loop to send out a
message to the WS clients.
Using pthreads
Spawn a new Thread for the broadcast loop, this can be killed when I
want it to stop. I'm pretty sure I'll have to make sure the Socket is
only used by one thread at a time, so I'll have handle that somehow.
My question is, which approach should I take, and are there any examples or tutorials for the suggested approach?

If I get you right:
You get in a web-socket - command "start"
After receiving the request, you want to start broadcasting with 0.2
seconds interval
If you will come - command "stop", you need to stop broadcasting
Maybe I misunderstood the problem, but it's a bad idea, getting client requests start and stop brodcasting (what if everyone will send a "start command"?)
In general, I would recommend using ZMQ. This is the most scalable solution. (It is best to separate the services)
You start the server.
Waiting for commands from ZMQ, that you need to start broadcasting.
Once you get a command of ZMQ, create a timer with 0.2 second intervals and broadcasts
As soon as you get "command" stop in ZMQ - kill the timer.
OR
Your start the server ZMQ PUB and start brodcasting
Yout start web-socket
You give command start and start receive ZMQ SUB messages
You give command stop and stop receive ZMQ SUB messages
If you want a pub/sub service. Then simply create a Timer and have a list of who to broadcast. Client send "subscribe", and receive messages. Good idea use Redis for storing data between processes (WebSocket - ZMQ)
You need read ZMQ PHP DOC, before using ZMQ and see reactphp/zmq lib

Related

How to properly use AWS SQS

I was looking for a good way to manage a lot of background tasks, and i found out AWS SQS.
My software is coded in PHP. To complete a background task, the worker must be a CLI PHP application.
How am i thinking of acclompishing this with AWS SQS:
Client creates a message (message = task)
Message Added to Mysql DB
A Cron Job checks mysql db for messages and adds them to SQS queue
SQS Queue Daemon listents to queue for messages and sends HTTP POST requests to worker when a message is received
Worker receives POST request and forks a php shell_execute with parameters to do the work
Its neccessary to insert messages in MySQL because they are scheduled to be completed at a certain time
A little over complicated.
I need to know what is the best way to do this.
I would use AWS Lambda, with an SQS trigger to asynchronoulsy process messages dropped in the queue.
First, your application can post messages directly to SQS, there is no need to first insert the message in MySQL and have a separate daemon to feed the queue.
Secondly, you can write an AWS Lambda function in PHP, check https://aws.amazon.com/blogs/apn/aws-lambda-custom-runtime-for-php-a-practical-example/
Thirdly, I would wire the Lambda function to the queue, following this documentation : https://aws.amazon.com/blogs/apn/aws-lambda-custom-runtime-for-php-a-practical-example/
This will simplify your architecture (less moving parts, less code) and make it more scalable.

PHP react parallel requests

I have an app which communicate through websocket with my server. I am using Ratchet and everything works perfect. The next thing i want to implement is to make requests to some other server and push responses through websocket to clients. My question is how to make parallel requests with react. Let say i have 5 endpoints which response i want to get parallel (thread). I want to call each endpoint every .2s for example and send response to websocket server clients. For example (this is just demonstration code):
$server->loop->addPeriodicTimer(.2, function ($timer) {
curl('endpoint1');
});
$server->loop->addPeriodicTimer(.2, function ($timer) {
curl('endpoint2');
});
$server->loop->addPeriodicTimer(.2, function ($timer) {
curl('endpoint3');
});
But this timer does not work this way. Is it even possible to achive this with react?
Im am not showing websocket code because communication between clients works nice.
To start. "React (Ratchet)" - operate in one thread mode (feature libevent). That is, anything that will block the process - bad idea... Curl request - will stop work socket server until it receives a response.
For your application - I would use ZMQ.
The point is this:
you run worker process (for example: ZMQWorker),
your server sends curl-data on ZMQWorker (via ZMQ).
ZMQWorker send Curl request
after sending the request, ZMQWorker send a response to the WebSocket
(via ZMQ). It you can get via reactphp/zmq
If you need to send a lot of concurrent requests - You will need pthread library - it provides multi-threading.
I've also heard that it is possible to provide work pthread + libevent, but personally I did not do.
P.S But the use of architecture ZMQ, you get a distributed architecture, to the same scalable!

REST Heartbeat for checking service availability

I need to implement a heartbeat to check whether my rest server is up and running, I was thinking about a service called "heartbeat" or "echo" together with my other services, that just perform a read from database to response with some value, eg: a version number o whatever, or just saying Hello. And then use curl to send request periodically (eg: every 20 seconds), so far so good. Now I need to develop some scripting for using curl periodically and if there are continuous error response (eg: 3 errors one after the other) I send an alert by email.
I was wondering whether there is any non-comercial (or not-paid) solution "out-of-the-box" to implement the last part (the script sending periodic request and sending alert emails), or if not, how would it the easiest way to get it done.
Thank you !
You can, and probably should use monit (or other equivalent tools) to achieve this. Monit can check HTTP services, and take some action (restart service, alert) when request fails

Forcing chat bot made with JAXL/XMPPHP to reconnect upon disconnection

I'm using the JAXL library to implement a jabber chat bot written in php, which is then ran as a background process using the PHP CLI.
Things work quite well, but I've been having a hard time figuring out how to make the chat bot reconnect upon disconnection!
I notice when I leave it running over night sometimes it drops off and doesn't come back. I've experimented with $jaxl->connect() and $jaxl->startStream(), and $jaxl->startCore() after jaxl_post_disconnect hook, but I think I'm missing something.
One solution would be to test your connection:
1) making a "ping" request to your page/controller or whatever
2) setTimeout(functionAjaxPing(), 10000);
3) then read the Ajax response and if == "anyStringKey" then your connection works find
4) else: reconnect() / errorMessage() / whatEver()
This is what IRC chat use i think.
But this will generate more traffic since the ping/ping request will be needed.
Hop this will help you a bit. :)
If you are using Jaxl v3.x all you need is to add a callback for on_disconnect event.
Also you must be using XEP-0199 XMPP Ping. What this XEP will do is, periodically send out XMPP pings to connected jabber server. It will also receive server pings and send back required pong packet (for instance if your client is not replying to server pings, jabber.org will drop your connection after some time).
Finally you MUST also use whitespace pings. A whitespace ping is a single space character sent to the server. This is often enough to make NAT devices consider the connection “alive”, and likewise for certain Jabber servers, e.g. Openfire. It may also make the OS detect a lost connection faster—a TCP connection on which no data is sent or received is indistinguishable from a lost connection.
What I ended up doing was creating a crontab that simply executed the PHP script again.
In the PHP script I read a specific file for the pid of the last fork. If it exists, the script attempts to kill it. Then the script uses pcntl_fork() to fork the process (which is useful for daemonifying a PHP script anyway) and capture the new PID to a file. The fork then logs in with to Jabber with JAXL per usual.
After talking with the author of JAXL it became apparent this would be the easiest way to go about this, despite being hacky. The author may have worked on this particular flaw in more recent iterations, however.
One flaw to this particular method is it requires pcntl_fork() which is not compiled with PHP by default.

How can a background service running in a webserver inform client browser the progress of the service?

First of all, I am completely new on many stuff, so I will welcome any inputs, including suggestions, existing projects, existing models, etc.
My current problems are:
The background service maintains a queue of tasks. The background service is written in C++ or python.
When a client clicks "Create Task" button in browser, the information will be sent to web server and the web server script (written in PHP) will initiate an RPC call to the background service to append the task to the internal queue.
The client browser will initiate an AJAX request to wait for the completion of the task. The AJAX request will hold until the task is completed (or failed) or the client cancels the request.
Thus, I need an low cost way to get the task progress which is run on a background service process.
I can think of two ways:
The background service can inform the server AJAX script about the progress pro-actively. This is low cost but I actually do not know how to do it. Does any RPC framework provides such asynchronous call back? Currently the RPC framework I decided to use is Thrift because of its multi-languages support.
The AJAX script on server side will make an RPC call to get current progress every a few seconds, and sleep in between. Upon completion, the AJAX script will return, otherwise it will just let the client browser wait by not returning. This is actually simpler but I am not sure about its cost. Note that delay isn't an issue to me here because I suppose that the clients are okay to wait for a few more seconds.
Is there any common way/model to deal with this problem?
Thanks for the help.
Depends on how you code it. The common way to do it is to make a javascripted ajax request every 1-3 seconds or so and poll the progress from the server.
This will intermediately close the connection and be more gentle to the server. If you use a persistent connection (WebSockets also fall into this category), you will keep the server busy. Besides, a "sleep" keeps the CPU busy - which is something I would try to avoid if I were you. On the other hand, if you've got the resources for that...
I can only repeat myself: it depends on how you code it and what you expect of it in the end.
If you want the client do some more work and treat the server gentle, choose your 1st option and if you think your server can handle it, choose the 2nd option and go "persistent" and even use WebSockets (which represent persistent connections to your server - remember that they aren't widely supported by web-browsing clients yet either).
Although I think that in the end - the trade-off of a simple progress compared to hogging your server CPU with constant sleeps and some persistent connections on-top of that will make you choose your 1st option: poll the server script for the progress value every x secs from the client side. Btw.: it's what Twitter does and their servers survived until today! ;)
I think, You can use WebSockets for that.
You can use WebSockets.
Establish a WebSockets connection between the client and a web service that has access to the information you need to pass to the client.
With web sockets, you don't need to poll the server asking it for progress, but rather have the server notify the client whenever it's ready.
A backwards compatible implementation would be long polling.
Cheers

Categories