Статьи

Запуск задач в облаке с помощью IronWorker

В этой статье я собираюсь показать вам, как мы можем использовать IronWorker для запуска кода в облаке, как если бы он выполнялся внутри кода нашего PHP-приложения. Для запуска задач в облаке есть ряд преимуществ, например:

  • Задачи с интенсивным использованием процессора могут быть выгружены с вашего веб-сервера
  • лучшая отказоустойчивость
  • выполнение вашего кода не блокируется в ожидании длительных задач

Вот как IronWorker описывает свой сервис:

Простая в использовании масштабируемая очередь задач, которая предоставляет разработчикам облачных вычислений простой способ выгрузки внешних задач, выполнения запланированных заданий и обработки задач в фоновом режиме и в масштабе.

Словарь терминов

Прежде чем мы начнем, давайте рассмотрим некоторые термины, используемые IronWorker, и эту статью, которая может быть вам незнакома.

Рабочий — это наш код, который выполняет задачу. Мы можем написать и протестировать его локально, но в конечном итоге мы загружаем его на серверы IronWorker, и он будет выполняться там, а не на нашем веб-сервере.

Задача — это выполнение кода либо по требованию (думайте об этом, как о вызове функции), либо по расписанию (как задание cron). Мы можем отложить выполнение, поставить его в очередь для запуска определенное количество раз или запустить его несколько раз до определенного времени и даты.

Полезная нагрузка — это данные, используемые для выполнения задачи (используя аналогию с функцией, полезная нагрузка будет аргументами, передаваемыми функции).

Среда IronWorker — это, по сути, песочница Linux в облаке, в которой выполняются наши задачи

Проект можно использовать для группировки работников, возможно, для конкретного применения.

HUD — это веб-интерфейс IronWorker, который мы используем для управления нашими проектами и задачами, просмотра результатов, редактирования и просмотра графиков, а также отслеживания нашего использования.

Установка и настройка

Есть несколько шагов, необходимых для настройки всего.

Во-первых, нам нужно создать учетную запись с IronWorker. Он предлагает бесплатный уровень с до 200 часов времени обработки в месяц, что должно быть более чем достаточно, чтобы следовать этой статье.

Нам также нужен инструмент IronWorker CLI; посетите документацию для получения полной инструкции по установке. Но если вы выполняете предварительные условия для его установки — в первую очередь у вас должен быть установлен Ruby — вы можете установить его в одну строку:

  gem install iron_worker_ng 

Далее нам нужно скачать клиентскую библиотеку PHP для работы с IronWorker, либо из GitHub, либо с Composer.

{ "require": { "iron-io/iron_worker": "dev-master" } } 

Самый простой способ настроить IronWorker — это файл JSON, который выглядит следующим образом:

 { "token": "YOUR-TOKEN", "project_id": "YOUR-PROJECT-ID" } 

Токен идентифицирует вашу учетную запись, а идентификатор проекта может быть установлен по умолчанию и переопределен конкретным работником. Вы можете найти всю эту информацию в HUD.

Если вы .iron.json файл JSON .iron.json (обратите внимание на предыдущую точку) и поместите его в свой домашний каталог, он будет использоваться для предоставления значений по умолчанию для любого из ваших проектов. В качестве альтернативы вы можете назвать его iron.json (без предшествующей точки) и поместить его в тот же каталог, что и рабочий. Файл в том же каталоге будет переопределять значения в домашнем файле, так что вы можете легко установить глобальные значения по умолчанию для и затем переопределить их локально для конкретных проектов по мере необходимости.

Кроме того, вы можете установить эти параметры с помощью переменных среды:

  IRON_TOKEN = MY_TOKEN
 IRON_PROJECT_ID = MY_PROJECT_ID 

Пример Hello World

Мы начнем с очень простого примера, чтобы показать, что связано с выполнением задач в облаке. Сначала создайте файл с именем HelloWorld.php :

 <?php echo 'Hello World'; 

Хотя это не делает ничего удаленно полезного, оно продемонстрирует важный момент, который вы увидите, когда мы его запустим — все, что напечатано в STDOUT (например, с помощью echo , print и т. Д.), Регистрируется IronWorker и позволяет HUD.

Затем создайте файл с именем HelloWorld.worker со следующим:

  время выполнения "php"
 exec 'HelloWorld.php' 

Как вы, вероятно, можете сделать вывод из первой строки, мы не ограничены только PHP; IronWorker поддерживает множество языков. Проверьте документацию для списка поддерживаемых языков .

Теперь нам нужно загрузить наш код на серверы IronWorker. Используя инструмент CLI, это очень просто:

  Iron_worker загрузить HelloWorld 

За кулисами инструмент CLI создает ZIP-файл, содержащий наш код, загружает его в IronWorker и регистрирует как доступную задачу для нашего проекта. Каждый раз, когда вы изменяете свой код и снова запускаете команду загрузки, он повторно загрузит код и создаст новую ревизию. Вы можете скачать любую ревизию с HUD.

Мы можем ставить задачи для запуска из нашего PHP-приложения следующим образом:

 <?php require_once '../vendor/autoload.php'; $worker = new IronWorker(); $taskID = $worker->postTask('HelloWorld'); 

Вы можете просмотреть текущее состояние всех задач в HUD. В зависимости от настроек вашей учетной записи, вы также можете получать электронные письма, чтобы держать вас в курсе, особенно если по какой-либо причине не удается выполнить задачу.

Необязательный второй аргумент для postTask() позволяет нам предоставить полезную нагрузку, если мы хотим отправить ее.

 $payload = array( 'foo' => 'bar', 'biz' => 'fuzz' ); $taskID = $worker->postTask('MyTask', $payload); 

Полезная нагрузка кодируется для нас и отправляется на серверы IronWorker. В самой задаче мы можем получить декодированную полезную нагрузку просто так:

 $payload = getPayload(); 

Мы можем настроить задачу для запуска по расписанию, так же, как запускается задача cron, используя метод postScheduleSimple() . Простое планирование похоже на выражение «запустите это за x секунд».

 // run the task in five minutes time (given in seconds) $schedID = $worker->postScheduleSimple('HelloWorld', $payload, 5 * 60); 

Расширенное планирование выполняется с помощью postScheduleAdvanced() и позволяет нам установить время первого запуска, интервал, а также время, когда он должен остановиться, или количество раз, чтобы его запустить. Поскольку требуется так много аргументов, полезно взглянуть на определение метода:

 /** * Schedules task * * @param string $name Package name * @param array $payload Payload for task * @param int|DateTime $start_at Time of first run in unix timestamp format or as DateTime instance. Example: time()+2*60 * @param int $run_every Time in seconds between runs. If omitted, task will only run once. * @param int|DateTime $end_at Time tasks will stop being enqueued in unix timestamp or as DateTime instance format. * @param int $run_times Number of times to run task. * @param int $priority Priority queue to run the job in (0, 1, 2). p0 is default. * @return string Created Schedule id */ public function postScheduleAdvanced($name, $payload = array(), $start_at, $run_every = null, $end_at = null, $run_times = null, $priority = null){ 

Вот несколько примеров его использования:

 // Run the task immediately, then every five minutes – a total of ten times $worker->postScheduleAdvanced('HelloWorld', $payload, time(), 5 * 60, null, 10); // run task in 3 minutes time, every two minutes, five times $worker->postScheduleAdvanced('HelloWorld', $payload, time() + (3 * 60), 2 * 60, null, 5); // run the task every hour for the next 24 hours $worker->postScheduleAdvanced('HelloWorld', $payload, time(), 60 * 60, time() + (60 * 60 * 24)); 

Более полезный пример — отправка электронной почты

Давайте создадим что-то более полезное сейчас и продемонстрируем немного другой подход к тому, как мы структурируем или проектируем и загружаем наш код. Вместо того, чтобы загружать работника с помощью инструмента CLI, мы создадим простой скрипт загрузки.

Создайте новый каталог с именем worker . Скопируйте в него iron.json и при необходимости создайте новый проект через HUD и обновите идентификатор проекта в вашем файле конфигурации. Затем загрузите PHPMailer и поместите его в рабочий каталог.

В worker каталоге создайте файл config.php котором будут храниться некоторые значения конфигурации для PHPMailer. Это должно выглядеть примерно так:

 <?php return array( 'smtp' => array( 'host' => 'smtp.example.com', 'port' => 465, 'encryption' => 'ssl', 'credentials' => array( 'username' => 'username', 'password' => 'password' ) ) ); 

Теперь создайте файл Emailer.php:

 <?php require_once './phpmailer/class.phpmailer.php'; $payload = getPayload(); $config = require './config.php'; $mail = new PHPMailer(); $mail->IsSMTP(); $mail->Host = $config['smtp']['host']; $mail->Port = $config['smtp']['port']; $mail->SMTPAuth = true; $mail->Username = $config['smtp']['credentials']['username']; $mail->Password = $config['smtp']['credentials']['password']; $mail->SMTPSecure = $config['smtp']['encryption']; $mail->From = 'no-reply@example.com'; $mail->FromName = 'SitePoint IronWorker Tutorial'; $mail->AddAddress($payload->recipient->email, $payload->recipient->name); $mail->WordWrap = 100; $mail->IsHTML(true); $mail->Subject = $payload->subject; $mail->Body = $payload->body; if (!$mail->Send()) { print 'Could not send email: ' . $mail->ErrorInfo; } 

Создать Emailer.worker :

  время выполнения "php"
 exec 'Emailer.php' 

И создайте upload.php :

 <?php require_once '../vendor/autoload.php'; $worker = new IronWorker(); $worker->upload('worker/', 'Emailer.php', 'Emailer'); 

Последняя строка сообщает IronWorker о загрузке всего worker каталога, который, конечно, включает в себя не только рабочий код, но и файл конфигурации и вспомогательные библиотеки. Второй аргумент — это имя файла, запускаемого для выполнения самой задачи, а третий аргумент — просто идентификатор работника.

Запустите скрипт загрузки из командной строки:

  php upload.php 

Мы можем запустить задачу из нашего PHP-приложения так же, как и раньше:

 <?php require_once '../vendor/autoload.php'; $worker = new IronWorker(); $payload = array( 'recipient' => array( 'name' => 'Joe Bloggs', 'email' => 'joe.bloggs@example.com' ), 'subject' => 'This is a test', 'body' => 'This is the body' ); $taskID = $worker->postTask('Emailer', $payload); 

Если вы хотите отправить пакет электронных писем, вы можете сделать простой цикл для постановки в очередь нескольких задач или дождаться завершения выполнения предыдущей задачи, например:

 // loop... $taskID = $worker->postTask('Emailer', $payload); $worker->waitFor($taskID); 

Дополнительная информация

Вы должны обратиться к документации, чтобы понять среду IronWorker, в которой будет выполняться ваш код. Основные моменты включают (на момент написания этой статьи):

  • Операционная система — Ubuntu Linux 12.04 x64.
  • Версия PHP — 5.3.10.
  • Установлены модули php-curl, php-mysql, php-gdm и mongo (хотя для их использования необходимо вызвать require_once (‘module-name’)).
  • Доступны ImageMagick , FreeImage , SoX и cURL .
  • Задачи имеют доступ к 10 Гбайт временного локального дискового пространства.
  • Максимальная полезная нагрузка данных составляет 64 КБ.
  • Каждый работник имеет около 320 МБ доступной памяти и максимальное время работы 60 минут.
  • По умолчанию вы можете иметь до 100 запланированных задач на проект.

Несмотря на то, что за рамками этой статьи, есть также несколько особенностей, на которые стоит обратить внимание:

  • REST API — есть API, с помощью которого вы можете просматривать или изменять проекты, задачи и графики.
  • Webhooks — вы можете настроить выполнение ваших задач при выполнении запроса POST к указанной конечной точке. Например, вы можете настроить задачу для запуска, когда вы фиксируете код в GitHub.
  • Статус — вы можете вызвать getTaskDetails($taskID) чтобы получить статус этой задачи — «в очереди», «выполнено», «ошибка» и т. Д.
  • Ход выполнения — вы можете установить ход выполнения задачи в своем работнике, используя setProgress($percent, $message) , который доступен для getTaskDetails() выше.
  • Журналы — как уже упоминалось, все, что напечатано в STDOUT, регистрируется IronWorker и отображается в HUD. Вы также можете получить к нему доступ от рабочего с помощью getLog($taskID) .

Резюме

В этой статье мы рассмотрели выполнение задач в облаке с помощью IronWorker. Я показал вам, как загружать рабочих, ставить их в очередь и планировать задачи, а также упомянул некоторые из доступных дополнительных функций. Если вы хотите узнать больше, я бы рекомендовал уделить время чтению документации и просмотру репозитория примеров на GitHub.