How to properly use AWS SQS - php

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.

Related

How would I run a queue of an Amazon SQS ? Is it a cron job?

I understand the basic of Amazon SQS. Yet i'm still confused on how it runs? Is it an infinite running function that polls messages and deal with it? how would I achieve that in php?
What I have in mind is a cron job that triggers the polling and process the messages. is my understanding right?
There's more than one answer to this.
Yes, you could have cron poll regularly for new queue items. You could have a daemon running indefinitely (likely monitored by something like supervisor) that continues to poll in a loop.
There's also SQS triggers, where a new SQS item can automatically initiate something. There are multiple options available: new queue items can make an SNS notification, which could trigger a HTTP POST to a URL. They can also trigger a Lambda function.

How to batch read sqs messages inside beanstalk worker

Our web application running on elastic beanstalk logs activity of incoming request to a database. We want to decouple the dB logging from the request processing path, so that response time can be sped up. We decided to use sqs queues and beanstalk worker. The idea is to queue the logging event to sqs, and have the worker receive the events and let it do the logging to the dB.
Now the need is to optimize the dB logging operation and avoid creating one connection per message in the queue. From my understanding the sqs daemon would Call the worker for each message, is there a way to have the daemon send messages in a batch, so that there's only one message and it's body has contents of all messages?
Or do we need to use a secondary queue or write a custom sqs message aggregator that processes n messages from the queue and then sends one batch message to another queue and that then gets written to the dB once?
We are using php and mysql
From my experience, defaultly you cannot. The daemon calls your application for each message.
What you can do might be that you cache the messages locally (assuming you are using single instance instead of auto scaling one) in a file (locking system for multi-processing) and then uses the scheduling of ELB cronjob to retrieve information from the file then do your DB operations every a certain amount of time. Thus, you can do that DB operation in a batch.
If you want to use auto scaling with multiple instances, you might need to use another messaging which is a waste compared with another option. This option is you write your own code using based off aws sdk to receive/delete from SQS in a batch and then update your database.

Laravel and SQS - Several connections in one request

I have a Laravel app (iOS API) that pushes data to SQS to be processed in the background. Depending on the request, we need to dispatch anywhere from 1 to 4 jobs to SQS. For example:
Dispatch a job to SQS, to be processed by a Worker:
for connecting to a socket service (Pusher)
for connecting to Apple's APNS service (Push Notifications)
for sending data to Loggly for basic centralized request logging
for storing analytics data in a SQL database (for the time being)
The problem is, we might have a feature like "chat", which is a pretty light request as far as server processing is concerned, however it needs to connect to SQS three times over to send:
1) Socket push to all the devices
2) Analytics processing
3) Centralized Request / Error Logging
In total, these connections end up doubling or tripling the time that the rest of request takes. ie. POSTing to /chat might otherwise take about 40-50ms, but with SQS, it takes more like 100 - 120ms
Should i be approaching this differently? Is there a way batch these to SQS so we only need to connect once rather than 3 times?
As Michael suggests in the comments, one way to do it is to use a sendMessageBatch request to send up to 10 messages to one single queue. When you're using multiple queues, and maybe even if you're not, there's also another approach.
If you can approach all the different messages as the same element, namely a notification of an action to an arbitrary receiver, you will find yourself in the fanout pattern. This is a commonly used pattern in which multiple receivers need to act on a single message, a single action.
Although AWS SQS doesn't natively support it, in combination with AWS Simple Notification Service you can actually achieve the same thing. Jeff Barr wrote a short blog post on the fanout setup using SNS and SQS a while ago (2012). It boils down to sending a notification to SNS that'll trigger messages to be posted on multiple SQS queues.
If anyone is curious, I released an MIT package to batch dispatch :)
https://packagist.org/packages/atymic/laravel-bulk-sqs-queue
It uses async and sendMessageBatch under the hood.

Make notifications response when the job is completed

I am using Symfony framework3 with Pheanstalk bundle and Doctrine. I creating the event which sends data to beanstalk. The other SF app on the different server perform a job and update notification status on the first SF app to completed. How can I check when the status is updated and than set alert like that:
http://byrobin.nl/store/wp-content/uploads/sites/4/2016/03/local.png
I can create a command that have infinitive loop and checking for status update, maybe listener on preUpdate? Also I have the same problem with running command that checking and executing beanstalk jobs. In dev mode i run it by hand, but i try infinitive loop like while(true) but it load my buffer and crash. I was thinking of cron job that runs every minute or two? What is best solution for this two problems? Any advice?
1) It would be good with WebSockets as that doesn't involve while(true) loop. A websocket can be opened by the frontend after a task has been submitted for processing. After the job finished processing it would notify the server side of the websocket to relay the info back on the socket for the frontend.
2) Another option is to submit a message, and in the params name anonymous tube (make a unique name based on time and some prefix) where the worker needs to put the answer. And before submitting the job you subscribe on beanstalkd to the anonymous channel, then submit the job, and the job finishes it will post the answer to the tube. Since there is already a subscriber there it will reserve the job and deal with it, then delete it, and the tube gets removed too.

Message broker and Message queue

I have a scenario where I have drop message to queue and fetch this message from other process and do the stuff.
I have a website written on PHP, I am reading and writing to Redis while main database is MySQL.
I don't want to delay user response time, so i am using Redis. After writing to Redis i want to drop a message in queue and then other process running will read it and store the transaction in database. So sending a message to queue while writing to Redis is not a problem as this can be easily done in PHP, reading from queue can also be achieved by running a PHP script in domain (with open socket), cron etc.
I need to know if there is any opensource software available which can read the message from queue as soon as they arrive and trigger a PHP script with parameters. This mechanism will be fast.
I am not sure about the efficiency of PHP socket running as domain, but for cron there is certain delay.

Categories