Run queue and the scheduler Laravel environment in Elastic Beanstalk

Official documentation for Laravel in detail describes the installation of the web application and related processes-employees, but what if I want to deploy the product in AWS Elastic Beanstalk?


As it turned out, this is almost no articles on the Internet, no ready packages on Packagist, there is no mention in the documentation.


This article will not only show you how you can easily run the scheduler and the handler queue in AWS, but also once again prove that Laravel is very easy to extend.


the

What is Elastic Beanstalk?


For those of you not familiar with the EB services from AWS, I will try to explain in two sentences. Elastic Beanstalk is a complete bundle of services (virtual servers, load balancers, monitoring) for automatic scaling of applications. Thanks EB, the team does not necessarily have DevOps, and the app will adapt itself under any load.


the

Elastic Beanstalk: features


Amazon offers a separate, special environment-employees – environment 'worker'. And despite the fact that AWS allows you to run scheduled tasks, and tasks from the queue, the process differs from the standard:


Processing queues in Laravel

In the standard process, Laravel inserts the task into the queue, and the other copy of the same application polls the queue periodically, hoping to get a task. Scheduled tasks will be processed within Laravel scheduler, which in turn runs every minute via the standard UNIX cron tab.


But AWS EB, we will not be able to set your cron files, or work with a queue directly


Processing queues in AWS EB

Instead, the internal process AWS will send us POST requests, notifying our copies of the application on the scheduled tasks ready to run, or about new tasks in the queue. Sounds simple enough, but Laravel (current version is 5.2) does not support neither one nor the other – the scheduler runs only from the console, and a handler queue want access to the queue directly.


the

Implementation


Scheduler


let's Start with the scheduler. We wanted the same thing that happens when you run in the console php artisan schedule:run, but from a web query (a web hook). To create separate hooks (some developers choose this path) is not desirable, because:


the
    the
  • Want to rely on the built-in scheduler Laravel – syntax easier to read, razrabotchikom not required knowledge of UNIX, business logic remains in the application and not outside of it;
  • the
  • Other environments in which the application operates (local, development) may not be in AWS, and we don't want to have two different ways to work for AWS and non-AWS options;
  • the
  • Not want to create a bunch of methods-hooks to be used only with AWS.

it looks like the final version of the controller method that launches the planner. The method is very similar to the built-in Laravel ScheduleRunCommand::class:


the
/**
* @param Container $laravel
* @param Kernel $kernel
* @param Schedule $schedule
* @return array
*/
public function schedule(Container $laravel, Kernel $kernel, Schedule $schedule)
{
$events = $schedule->dueEvents($laravel);
$eventsRan = 0;
$messages = [];
foreach ($events as $event) {
if (! $event->filtersPass($laravel)) {
continue;
}
$messages[] = 'Running: '.$event->getSummaryForDisplay();
$event->run($laravel);
++$eventsRan;
}
if (count($events) === 0 || $eventsRan === 0) {
$messages[] = 'No scheduled commands are ready to run.';
}
return $this->response($messages);
}

Perhaps the most important line. As we know, Laravel will try to provide all specified in the parameter list dependencies, but in this case we need a side effect from this:


the
public function schedule(Container $laravel, Kernel $kernel, Schedule $schedule)

the Web application is Laravel uses a custom kernel which does not load the scheduled tasks list, but we asked to provide us with the console kernel (Illuminate\Contracts\Console\Kernel) – Laravel'u will have to download it for us. During the boot process there will be 'adverse' effect will be loaded a scheduled task from the App/Console, finally app know about them. When Laravel will provide the following relationship, class Schedule – the application will tasks.


what happens next, is quite simple and clear, almost identical to ScheduleRunCommand. It would be great to use an existing class, but unfortunately it is impossible to extend or override.


Queue


One of the objectives was to reduce the number of new classes to a minimum, so I didn't enter their queue, or connection – it was possible to do only one job class that will be passed to the standard handler queues.


the Method looks like this:


the
/**
* @param Request $request
* @param Worker $worker
* @param Container $laravel
* @return array
*/
public function queue(Request $request, Worker $worker Container $laravel)
{
$this->validateHeaders($request);
$body = $this->validateBody($request, $laravel);
$job = new AwsJob($laravel, $request- > header('X-Aws-Sqsd-Queue'), [
'Body' => $body,
'MessageId' => $request->header('X-Aws-Sqsd-Msgid'),
'ReceiptHandle' => false,
'Attributes' => [
'ApproximateReceiveCount' => $request->header('X-Aws-Sqsd-Receive-Count')
]
]);
try {
$worker- > process(
$request- > header('X-Aws-Sqsd-Queue'), $job, 0, 0
);
} catch (\Exception $e) {
return $this->response([
'Couldn\'t process' . $job- > getJobId()
], 500);
}
return $this->response([
'Processed' . $job- > getJobId()
]);
}

what we need to do is to pull the SQS metadata from HTTP headers, and paste them in your job-class. It turned out a kind of adapter from HTTP to SQS. We don't need to remove a job from the queue or mark it as failed, do everything himself AWS. If we don't return HTTP code 200 (for example, we caught the error), then AWS will do all the rest.


That's all! It remains to add a few routes (only two routes for any number of tasks) and the application is ready for battle!


setup AWS


don't forget to sign worker places the corresponding AWS SQS queue (or topic SNS).


To AWS began to "stick" every minute, at the time of the new application version in the root should be a file cron.yaml. You can add it to the repository, and you can add in the last step. Contents of file:


the
version: 1
cron:
- name: "schedule"
url: "/worker/schedule"
schedule: "* * * * *"

the

Insights


Laravel has once again proved its flexibility and expandability.


the Complete source code for a work package with integration for Laravel and Lumen already posted this on GitHub (and Packagist): https://github.com/dusterio/laravel-aws-worker

Article based on information from habrahabr.ru

Комментарии

Популярные сообщения из этого блога

ODBC Firebird, Postgresql, executing queries in Powershell

Installation LivestreetCMS on MODX Revolution package 10 clicks

The Ministry of communications wants to ban phones without GLONASS