Как перевести Linux cron-задачи на «путь Amazon»?

112

Хорошо это или плохо, но мы перенесли все наше веб-приложение LAMP с выделенных машин в облако (машины Amazon EC2). Пока все идет отлично, но то, как мы делаем crons, не оптимально. У меня есть специфический для Amazon вопрос о том, как лучше всего управлять заданиями cron в облаке, используя «путь Amazon».

Проблема : у нас есть несколько веб-серверов, и нам нужно запускать crons для пакетных заданий, таких как создание RSS-каналов, запуск электронных писем и многое другое. НО задания cron должны выполняться только на одном компьютере, потому что они часто записываются в базу данных, поэтому при запуске на нескольких машинах результаты будут дублироваться.

До сих пор мы обозначили один из веб-серверов как «главный веб-сервер», и у него есть несколько «специальных» задач, которых нет у других веб-серверов. Компромисс для облачных вычислений - надежность - нам не нужен «главный веб-сервер», потому что это единственная точка отказа. Мы хотим, чтобы все они были идентичными и чтобы можно было повышать и понижать масштаб, не забывая при этом, что главный веб-сервер не следует выводить из кластера.

Как мы можем перепроектировать наше приложение, чтобы преобразовать задания Linux cron в временные рабочие элементы, у которых нет единой точки отказа?

Мои идеи на данный момент:

  • Сделайте машину, предназначенную только для бега. Это было бы немного более управляемым, но все равно было бы единичной точкой отказа, и было бы потрачено немного денег на дополнительный экземпляр.
  • Некоторые задания можно было бы перенести из Linux crons в MySQL Events, однако я не большой поклонник этой идеи, поскольку я не хочу помещать логику приложения на уровень базы данных.
  • Возможно, мы сможем запустить все crons на всех машинах, но изменить наши сценарии cron, чтобы все они начинались с небольшой логики, которая реализует механизм блокировки, так что только один сервер действительно выполняет действие, а другие просто пропускают. Я не фанат этой идеи, поскольку она звучит потенциально ошибочно, и я предпочел бы использовать передовой опыт Amazon, а не использовать собственные.
  • Я представляю ситуацию, когда задания где-то планируются, добавляются в очередь, а затем каждый веб-сервер может быть рабочим, который может сказать: «Эй, я возьму это». Amazon Simple Workflow Service звучит именно так, но в настоящее время я мало что знаю об этом, поэтому любые подробности будут полезны. Это кажется тяжеловесным для чего-то такого простого, как cron? Это правильный сервис или есть более подходящий сервис Amazon?

Обновление: задав вопрос, я посмотрел веб-семинар Amazon Simple Workflow Service на YouTube и заметил в 34:40 ( http://www.youtube.com/watch?v=lBUQiek8Jqk#t=34m40s ) мельком слайд с упоминанием заданий cron в качестве примера приложения. На странице документации « Примеры AWS Flow Framework для Amazon SWF » Amazon сообщает, что у них есть образец кода для crons:

... > Задания Cron В этом примере длительный рабочий процесс периодически выполняет действие. Демонстрируется возможность продолжать выполнение как новое выполнение, так что выполнение может выполняться в течение очень продолжительных периодов времени. ...

Я загрузил AWS SDK для Java ( http://aws.amazon.com/sdkforjava/ ) и, конечно же, похоронил в нелепых слоях папок есть некоторый код java ( aws-java-sdk-1.3.6/samples/AwsFlowFramework/src/com/amazonaws/services/simpleworkflow/flow/examples/periodicworkflow).

Проблема в том, если честно, это не совсем помогает, потому что я не могу легко переварить это с моим набором навыков. Тот же образец отсутствует в PHP SDK, и, похоже, нет учебника, который бы прошел через этот процесс. В общем, я все еще ищу совет или подсказку.

Том
источник
2
Возможно, связано: stackoverflow.com/questions/8812025/scheduling-a-job-on-aws-ec2
Илмари Каронен

Ответы:

38

Я подписался на поддержку Amazon Gold, чтобы задать им этот вопрос, они ответили:

Том

Я быстро опросил некоторых своих коллег и ничего не нашел в cron, но, поспав с ним, я понял, что важный шаг может быть ограничен блокировкой. Поэтому я поискал «распределенную блокировку заданий cron» и нашел ссылку на Zookeeper, проект Apache.

http://zookeeper.apache.org/doc/r3.2.2/recipes.html

http://highscalability.com/blog/2010/3/22/7-secrets-to-successfully-scaling-with-scalr-on-amazon-by-se.html

Также я видел упоминание об использовании memcached или подобного механизма кэширования как способа создания блокировок с помощью TTL. Таким образом, вы устанавливаете флаг с TTL равным 300 секундам, и никакой другой работник cron не будет выполнять задание. Блокировка будет автоматически снята по истечении TTL. Это концептуально очень похоже на вариант SQS, который мы обсуждали вчера.

Также см; Пухлый http://static.googleusercontent.com/external_content/untrusted_dlcp/research.google.com/en//archive/chubby-osdi06.pdf от Google

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

С уважением,

Ронан Г. Веб-службы Amazon

Том
источник
13

Я думаю, что это видео отвечает на ваш точный вопрос - cronjobs a aws way (масштабируемый и отказоустойчивый):

Использование Cron в облаке с Amazon Simple Workflow

Видео описывает службу SWF с использованием конкретного варианта использования cronjobs.

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

Натан Бюсгенс
источник
2
это отличный ответ, поскольку он использует хорошо поддерживаемый инструмент от AWS, а SWF - мощный продукт. Единственным недостатком, я думаю, является то, что SWF требует значительного обучения, и с ним может быть сложно делать сложные вещи. По крайней мере, таков был мой опыт работы с учебными пособиями по Java
Дон Чидл
11

Будьте осторожны с использованием SQS для cronjobs, так как они не гарантируют, что «только одно задание просматривается только одной машиной». Они гарантируют, что «хотя бы один» получит сообщение.

От: http://aws.amazon.com/sqs/faqs/#How_many_times_will_I_receive_each_message

В: Сколько раз я получу каждое сообщение?

Amazon SQS спроектирован так, чтобы обеспечивать «хотя бы один раз» доставку всех сообщений в своих очередях. Хотя в большинстве случаев каждое сообщение доставляется в ваше приложение ровно один раз, вы должны спроектировать свою систему так, чтобы обработка сообщения более одного раза не приводила к ошибкам или несоответствиям.

Пока что я могу подумать о решении, в котором у вас есть один экземпляр с установленным экземпляром Gearman Job Server: http://gearman.org/ . На том же компьютере вы настраиваете задания cron, которые создают команду для выполнения вашей задачи cronjob в фоновом режиме. Тогда один из ваших веб-серверов (воркеров) начнет выполнять эту задачу, это гарантирует, что ее возьмет на себя только один. Неважно, сколько у вас воркеров (особенно, когда вы используете автоматическое масштабирование).

Проблемы с этим решением:

  • Сервер Gearman является единственной точкой отказа, если вы не настроите его с распределенным хранилищем, например, с использованием memcached или какой-либо базы данных.
  • Затем, используя несколько серверов Gearman, вы должны выбрать тот, который создает задачу через cronjob, поэтому мы снова возвращаемся к той же проблеме. Но если вы можете жить с такой единой точкой отказа, использование Gearman выглядит неплохим решением. Тем более, что для этого не нужен большой экземпляр (в нашем случае достаточно микро-экземпляра).
Мацей Маевский
источник
Что ж, сообщения остаются на сервере после их получения. После этого разработчик может удалить их. Пока они обрабатываются, другой сервер не может получить к ним доступ.
Frederik Wordenskjold 02
2
@FrederikWordenskjold Это неверно, даже после того, как сообщение было передано одному клиенту, оно все еще может быть передано другому, поскольку репликация состояния SQS является асинхронной. Вы даже можете получить копию сообщения «после» его удаления!
Крис Питман,
Этот ответ устарел. Сейчас есть 2 типа очередей. Используйте FIFO для получения одноразовой обработки: сообщение доставляется один раз и остается доступным до тех пор, пока потребитель не обработает и не удалит его. Дубликаты в очередь не вносятся. aws.amazon.com/sqs/features
Лукас Лисис
10

Amazon только что выпустила новые функции для Elastic Beanstalk. Из документов :

AWS Elastic Beanstalk поддерживает периодические задачи для
уровней рабочей среды в средах с предварительно определенной конфигурацией со стеком решений, содержащим «v1.2.0» в имени контейнера. "

Теперь вы можете создать среду, содержащую cron.yamlфайл, который настраивает задачи планирования:

version: 1
cron:
- name: "backup-job"          # required - unique across all entries in this file
  url: "/backup"              # required - does not need to be unique
  schedule: "0 */12 * * *"    # required - does not need to be unique
- name: "audit"
  url: "/audit"
   schedule: "0 23 * * *"

Я бы предположил, что страховка запуска его только один раз в автомасштабируемой среде используется через очередь сообщений (SQS). Когда демон cron запускает событие, он помещает этот вызов в очередь SQS, и сообщение в очереди оценивается только один раз. В документах говорится, что выполнение может быть отложено, если SQS имеет много сообщений для обработки.

user541905
источник
Не могли бы вы также включить какой-нибудь контент из ссылок?
Роберт
6

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

В нашем случае, посмотрев возможные решения, мы решили, что у нас есть два варианта:

  • Настройте сервер cronjob, который запускает задания, которые следует запускать только один раз, автоматически масштабируйте его и убедитесь, что он заменен, когда определенные статистические данные CloudWatch не такие, какими они должны быть. Мы используем cloud-initскрипты для запуска cronjobs. Конечно, это сопровождается простоем, что приводит к пропущенным cronjobs (при выполнении определенных задач каждую минуту, как мы).
  • Используйте логику, которая rcronиспользует. Конечно, магия на самом деле не в rcronсебе, а в логике, которую вы используете для обнаружения отказавшего узла (мы используем keepalivedздесь) и «обновления» другого узла до уровня мастера.

Мы решили выбрать второй вариант просто потому, что он блестяще быстр, и у нас уже был опыт работы с веб-серверами, на которых выполнялись эти cronjobs (в эпоху до появления AWS).

Конечно, это решение предназначено специально для замены традиционного подхода cronjob с одним узлом, где решающим фактором является время (например, «Я хочу, чтобы задание A выполнялось один раз в день в 5 часов утра» , или как в нашем случае «Я хочу задание B» бегать раз в минуту » ). Если вы используете cronjobs для запуска логики пакетной обработки, вам действительно стоит взглянуть на SQS. Нет никакой дилеммы активного и пассивного, что означает, что вы можете использовать один сервер или всю рабочую силу для обработки своей очереди. Я также предлагаю рассмотреть SWFвозможность масштабирования вашей рабочей силы (хотя auto scalingв большинстве случаев это тоже может помочь).

Мы хотели избежать зависимости от другой третьей стороны.

Яап Хаагманс
источник
6

12 февраля 2016 года Amazon опубликовал блог о планировании заданий SSH с помощью AWS Lambda . Думаю, это ответ на вопрос.

Том
источник
1
Можно ли добавлять динамические cronjobs или расписания с помощью AWS lambda?
Sanjay Kumar NS
Да, вы можете вызвать Lambda с помощью событий Cloudwatch. Время так, как вы считаете нужным.
Майкл
4

Распределение осуществляется «амазонским» способом, а это означает, что громоздкие кроны следует разделить на множество более мелких работ и передать нужным машинам.

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

FIFO Exactly-Once Processing : сообщение доставляется один раз и остается доступным до тех пор, пока потребитель не обработает и не удалит его. Дубликаты в очередь не вносятся.

Также подумайте, действительно ли вам нужно «группировать» эти операции. Что произойдет, если обновлений за одну ночь будет значительно больше, чем ожидалось? Даже при динамическом выделении ресурсов ваша обработка может быть отложена до тех пор, пока не запустится достаточное количество машин. Вместо этого храните данные в SDB, уведомляйте машины об обновлениях через SQS и создавайте RSS-канал «на лету» (с кэшированием).

Пакетные задания относятся к временам, когда ресурсы обработки были ограничены, а «живые» сервисы имели приоритет. В облаке дело обстоит иначе.

всехар
источник
Спасибо - мне нравится направление, которое вы описываете.
Том
5
Имейте в виду, что SQS гарантирует только то, что сообщение в конечном итоге будет увидено машиной, а не то, что сообщения будут видеть только один сервер. Все, что вы помещаете в очередь SQS, должно быть идемпотентным.
Richard Hurt
Мое задание cron должно выполняться ежедневно, а с помощью SQS вы можете отложить только до 15 минут. Одним из вариантов может быть добавление настраиваемого тега к сообщению с указанием целевого времени для его выполнения и помещения его обратно в очередь, если это время еще не достигнуто, но это действительно выглядит глупо. Также мне все еще нужно задание cron для первоначального заполнения очереди. Кажется, проблема курица-яйцо :) Но я все же считаю, что SQS - это правильный выбор, потому что он гарантирует масштабируемость и отказоустойчивость,
Раффаэле Росси
«Пакетные задания относятся к временам, когда ресурсы обработки были ограничены, а« живые »сервисы имели приоритет. В облаке это не так». Это верно для некоторых, но не для всех видов деятельности. Например, обработка журналов трафика - это лучше как пакетный процесс, чем в реальном времени.
Jordan Reiter
1

Зачем строить собственное? Почему бы не использовать что-то вроде Quartz (с кластерным планированием). См. Документацию.

http://quartz-scheduler.org/documentation/quartz-2.x/configuration/ConfigJDBCJobStoreClustering

Рама Налламилли
источник
Я использовал Quartz.NET в решении SaaS, которое сильно зависело от запланированных задач. Кое-где выполнялись задачи по обслуживанию системы, но чаще всего выполнялись действия, запланированные конечными пользователями. Все наши задачи записывались в очереди сообщений (amq), для которых у нас было любое количество идемпотентных служб. API очень хорош и позволяет создавать мощные расписания. Мы не кластеризовали несколько экземпляров Quartz, но он это поддерживает.
Джерико Сандхорн,
1

Что мы делаем, так это то, что у нас есть один конкретный сервер, который является частью нашего кластера веб-приложений за ELB, которому также назначено определенное DNS-имя, чтобы мы могли запускать задания на этом одном конкретном сервере. Это также имеет то преимущество, что если это задание вызывает замедление работы этого сервера, ELB удалит его из кластера, а затем вернет его, когда задание будет завершено, и он снова станет работоспособным.

Работает как чемпион.

Патрик Стейл
источник
1

Один из способов убедиться, что ваше выражение cron работает аналогично Amazon, - запустить его с помощью команды events. Например:

aws events put-rule --name "DailyLambdaFunction" --schedule-expression "<your_schedule_expression>

Если выражение вашего расписания недействительно, это не удастся.

Дополнительные ресурсы: https://docs.aws.amazon.com/cli/latest/reference/events/put-rule.html

Кевин Ид
источник
0

Поскольку никто не упомянул событие CloudWatch , я бы сказал, что это способ AWS для выполнения заданий cron. Он может запускать множество действий, таких как лямбда-функция, задача ECS.

Wanghq
источник